Skip to content

Commit f732db6

Browse files
committed
Merge remote-tracking branch 'origin/codex/type-resonite-texture-payload-variants' into codex/review-pr355-current
2 parents 3463a24 + 8db6f10 commit f732db6

58 files changed

Lines changed: 1993 additions & 874 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/PlateauResoniteLink/Application/Importing/BuildingAttributeModels.cs

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -52,49 +52,49 @@ internal enum PlateauBuildingStructure
5252

5353
internal sealed record BuildingCodeValue<T>(T Value, string Code);
5454

55-
internal abstract record BuildingMetricValue
55+
internal enum BuildingMetricKind
5656
{
57-
public static BuildingMetricValue Missing { get; } = new MissingMetricValue();
57+
MeasuredHeightMeters,
58+
StoreysAboveGround,
59+
StoreysBelowGround,
60+
BuildingFootprintArea,
61+
BuildingRoofEdgeArea,
62+
BuildingHeight,
63+
EaveHeight,
64+
}
5865

59-
public static BuildingMetricValue Known(double value)
66+
internal readonly record struct BuildingMetricValue
67+
{
68+
public BuildingMetricValue(double value)
6069
{
61-
return new KnownMetricValue(value);
62-
}
70+
ArgumentOutOfRangeException.ThrowIfNegative(value);
6371

64-
public static BuildingMetricValue Invalid(string raw)
65-
{
66-
return new InvalidMetricValue(raw);
67-
}
72+
if (!double.IsFinite(value))
73+
{
74+
throw new ArgumentOutOfRangeException(nameof(value));
75+
}
6876

69-
internal sealed record MissingMetricValue : BuildingMetricValue
70-
{
77+
Value = value;
7178
}
7279

73-
internal sealed record KnownMetricValue : BuildingMetricValue
74-
{
75-
public KnownMetricValue(double value)
76-
{
77-
ArgumentOutOfRangeException.ThrowIfNegative(value);
78-
79-
if (!double.IsFinite(value))
80-
{
81-
throw new ArgumentOutOfRangeException(nameof(value));
82-
}
80+
public double Value { get; }
81+
}
8382

84-
Value = value;
85-
}
83+
internal sealed record BuildingMetricMeasurements
84+
{
85+
public static BuildingMetricMeasurements Empty { get; } = new(new Dictionary<BuildingMetricKind, BuildingMetricValue>());
8686

87-
public double Value { get; }
87+
public BuildingMetricMeasurements(IReadOnlyDictionary<BuildingMetricKind, BuildingMetricValue> values)
88+
{
89+
ArgumentNullException.ThrowIfNull(values);
90+
Values = new Dictionary<BuildingMetricKind, BuildingMetricValue>(values);
8891
}
8992

90-
internal sealed record InvalidMetricValue : BuildingMetricValue
91-
{
92-
public InvalidMetricValue(string raw)
93-
{
94-
Raw = raw ?? throw new ArgumentNullException(nameof(raw));
95-
}
93+
public IReadOnlyDictionary<BuildingMetricKind, BuildingMetricValue> Values { get; }
9694

97-
public string Raw { get; }
95+
public bool TryGet(BuildingMetricKind kind, out BuildingMetricValue value)
96+
{
97+
return Values.TryGetValue(kind, out value);
9898
}
9999
}
100100

@@ -105,13 +105,7 @@ internal sealed record BuildingAttributeContext(
105105
IReadOnlyList<BuildingCodeValue<PlateauBuildingStructure>> Structures,
106106
IReadOnlyList<string> CityGmlClassCodes,
107107
IReadOnlyList<string> CityGmlFunctionCodes,
108-
BuildingMetricValue MeasuredHeightMeters,
109-
BuildingMetricValue StoreysAboveGround,
110-
BuildingMetricValue StoreysBelowGround,
111-
BuildingMetricValue BuildingFootprintArea,
112-
BuildingMetricValue BuildingRoofEdgeArea,
113-
BuildingMetricValue BuildingHeight,
114-
BuildingMetricValue EaveHeight)
108+
BuildingMetricMeasurements Metrics)
115109
{
116110
public static BuildingAttributeContext Empty { get; } = new(
117111
RoofShape: null,
@@ -120,11 +114,5 @@ internal sealed record BuildingAttributeContext(
120114
Structures: [],
121115
CityGmlClassCodes: [],
122116
CityGmlFunctionCodes: [],
123-
MeasuredHeightMeters: BuildingMetricValue.Missing,
124-
StoreysAboveGround: BuildingMetricValue.Missing,
125-
StoreysBelowGround: BuildingMetricValue.Missing,
126-
BuildingFootprintArea: BuildingMetricValue.Missing,
127-
BuildingRoofEdgeArea: BuildingMetricValue.Missing,
128-
BuildingHeight: BuildingMetricValue.Missing,
129-
EaveHeight: BuildingMetricValue.Missing);
117+
Metrics: BuildingMetricMeasurements.Empty);
130118
}

src/PlateauResoniteLink/Application/Importing/BuildingAttributeParser.cs

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,15 @@ internal static class BuildingAttributeParser
1010
{
1111
internal static BuildingAttributeContext Parse(XElement cityObjectElement)
1212
{
13+
BuildingMetricMeasurements metrics = ParseMetrics(cityObjectElement);
1314
return new BuildingAttributeContext(
1415
RoofShape: ParseOptionalRoofShape(GetFirstDirectElementValue(cityObjectElement, "roofType")),
1516
Uses: ParseBuildingUses(GetDirectElementValues(cityObjectElement, "usage")),
1617
DetailedUses: ParseBuildingUses(GetDescendantElementValues(cityObjectElement, "detailedUsage")),
1718
Structures: ParseBuildingStructures(GetDescendantElementValues(cityObjectElement, "buildingStructureType")),
1819
CityGmlClassCodes: GetDirectElementValues(cityObjectElement, "class"),
1920
CityGmlFunctionCodes: GetDirectElementValues(cityObjectElement, "function"),
20-
MeasuredHeightMeters: ParseMetricValue(GetFirstDirectElement(cityObjectElement, "measuredHeight"), requireMeters: true),
21-
StoreysAboveGround: ParseIntegerMetricValue(GetFirstDirectElement(cityObjectElement, "storeysAboveGround")),
22-
StoreysBelowGround: ParseIntegerMetricValue(GetFirstDirectElement(cityObjectElement, "storeysBelowGround")),
23-
BuildingFootprintArea: ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingFootprintArea"), requireMeters: false),
24-
BuildingRoofEdgeArea: ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingRoofEdgeArea"), requireMeters: false),
25-
BuildingHeight: ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingHeight"), requireMeters: true),
26-
EaveHeight: ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "eaveHeight"), requireMeters: true));
21+
Metrics: metrics);
2722
}
2823

2924
private static XElement? GetFirstDirectElement(XElement element, string localName)
@@ -125,51 +120,96 @@ private static PlateauBuildingStructure MapBuildingStructure(string code)
125120
};
126121
}
127122

128-
private static BuildingMetricValue ParseIntegerMetricValue(XElement? element)
123+
private static BuildingMetricMeasurements ParseMetrics(XElement cityObjectElement)
124+
{
125+
Dictionary<BuildingMetricKind, BuildingMetricValue> values = [];
126+
AddMetric(
127+
values,
128+
BuildingMetricKind.MeasuredHeightMeters,
129+
ParseMetricValue(GetFirstDirectElement(cityObjectElement, "measuredHeight"), requireMeters: true));
130+
AddMetric(
131+
values,
132+
BuildingMetricKind.StoreysAboveGround,
133+
ParseIntegerMetricValue(GetFirstDirectElement(cityObjectElement, "storeysAboveGround")));
134+
AddMetric(
135+
values,
136+
BuildingMetricKind.StoreysBelowGround,
137+
ParseIntegerMetricValue(GetFirstDirectElement(cityObjectElement, "storeysBelowGround")));
138+
AddMetric(
139+
values,
140+
BuildingMetricKind.BuildingFootprintArea,
141+
ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingFootprintArea"), requireMeters: false));
142+
AddMetric(
143+
values,
144+
BuildingMetricKind.BuildingRoofEdgeArea,
145+
ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingRoofEdgeArea"), requireMeters: false));
146+
AddMetric(
147+
values,
148+
BuildingMetricKind.BuildingHeight,
149+
ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "buildingHeight"), requireMeters: true));
150+
AddMetric(
151+
values,
152+
BuildingMetricKind.EaveHeight,
153+
ParseMetricValue(GetFirstDescendantElement(cityObjectElement, "eaveHeight"), requireMeters: true));
154+
return new BuildingMetricMeasurements(values);
155+
}
156+
157+
private static void AddMetric(
158+
Dictionary<BuildingMetricKind, BuildingMetricValue> values,
159+
BuildingMetricKind kind,
160+
BuildingMetricValue? metric)
161+
{
162+
if (metric.HasValue)
163+
{
164+
values.Add(kind, metric.Value);
165+
}
166+
}
167+
168+
private static BuildingMetricValue? ParseIntegerMetricValue(XElement? element)
129169
{
130170
if (element is null)
131171
{
132-
return BuildingMetricValue.Missing;
172+
return null;
133173
}
134174

135175
string rawValue = element.Value.Trim();
136176
if (IsPlateauMissingMetricToken(rawValue))
137177
{
138-
return BuildingMetricValue.Missing;
178+
return null;
139179
}
140180

141181
return int.TryParse(rawValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out int value)
142182
&& value >= 0
143-
? BuildingMetricValue.Known(value)
144-
: BuildingMetricValue.Invalid(rawValue);
183+
? new BuildingMetricValue(value)
184+
: null;
145185
}
146186

147-
private static BuildingMetricValue ParseMetricValue(XElement? element, bool requireMeters)
187+
private static BuildingMetricValue? ParseMetricValue(XElement? element, bool requireMeters)
148188
{
149189
if (element is null)
150190
{
151-
return BuildingMetricValue.Missing;
191+
return null;
152192
}
153193

154194
string rawValue = element.Value.Trim();
155195
if (IsPlateauMissingMetricToken(rawValue))
156196
{
157-
return BuildingMetricValue.Missing;
197+
return null;
158198
}
159199

160200
string? unitOfMeasure = element.Attribute("uom")?.Value.Trim();
161201
if (requireMeters
162202
&& !string.IsNullOrWhiteSpace(unitOfMeasure)
163203
&& !string.Equals(unitOfMeasure, "m", StringComparison.OrdinalIgnoreCase))
164204
{
165-
return BuildingMetricValue.Invalid(rawValue);
205+
return null;
166206
}
167207

168208
return double.TryParse(rawValue, NumberStyles.Float, CultureInfo.InvariantCulture, out double value)
169209
&& double.IsFinite(value)
170210
&& value > 0.0
171-
? BuildingMetricValue.Known(value)
172-
: BuildingMetricValue.Invalid(rawValue);
211+
? new BuildingMetricValue(value)
212+
: null;
173213
}
174214

175215
private static bool IsPlateauMissingMetricToken(string rawValue)

src/PlateauResoniteLink/Application/Importing/BuildingAttributeQueries.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,24 @@ namespace PlateauResoniteLink.Application.Importing;
77

88
internal static class BuildingAttributeQueries
99
{
10-
internal static int? TryGetKnownPositiveInteger(BuildingMetricValue metric)
10+
internal static int? TryGetKnownPositiveInteger(BuildingAttributeContext attributes, BuildingMetricKind kind)
1111
{
12-
if (metric is not BuildingMetricValue.KnownMetricValue knownMetric)
12+
if (!attributes.Metrics.TryGet(kind, out BuildingMetricValue metric))
1313
{
1414
return null;
1515
}
1616

17-
int value = (int)Math.Round(knownMetric.Value, MidpointRounding.AwayFromZero);
18-
return Math.Abs(knownMetric.Value - value) < 1e-9
17+
int value = (int)Math.Round(metric.Value, MidpointRounding.AwayFromZero);
18+
return Math.Abs(metric.Value - value) < 1e-9
1919
&& (value == 0 || FacadeFloorMetrics.IsUsableFloorCount(value))
2020
? value
2121
: null;
2222
}
2323

24-
internal static double? TryGetKnownPositiveMetric(BuildingMetricValue metric)
24+
internal static double? TryGetKnownPositiveMetric(BuildingAttributeContext attributes, BuildingMetricKind kind)
2525
{
26-
return metric is BuildingMetricValue.KnownMetricValue { Value: > 0.0 } knownMetric
27-
? knownMetric.Value
26+
return attributes.Metrics.TryGet(kind, out BuildingMetricValue metric) && metric.Value > 0.0
27+
? metric.Value
2828
: null;
2929
}
3030

src/PlateauResoniteLink/Application/Importing/CityGmlParsedCityObjectProjection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ internal static IEnumerable<ImportedCityObject> ProjectSourceFile(
3232

3333
LocalCityGmlObjectProjection.ValidateCompatibleReferenceSystem(
3434
referenceSystem,
35-
sourceFile.CityObjects.FirstOrDefault()?.ReferenceSystem ?? referenceSystem);
35+
sourceFile.ReferenceSystem);
3636

3737
ParsedCityObject[] projectedInputCityObjects =
3838
DemCityObjectAggregation.AggregateBySourceFileAndThirdMesh(

src/PlateauResoniteLink/Application/Importing/CityGmlParsedCityObjectReader.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ internal static class CityGmlParsedCityObjectReader
3939
actualMeshCode,
4040
sharedAcrossMeshCodes);
4141
BuildingAttributeContext buildingAttributes = BuildingAttributeParser.Parse(cityObjectElement);
42-
int? floorsAboveGround = BuildingAttributeQueries.TryGetKnownPositiveInteger(buildingAttributes.StoreysAboveGround);
43-
double? measuredHeightMeters = BuildingAttributeQueries.TryGetKnownPositiveMetric(buildingAttributes.MeasuredHeightMeters);
42+
int? floorsAboveGround = BuildingAttributeQueries.TryGetKnownPositiveInteger(
43+
buildingAttributes,
44+
BuildingMetricKind.StoreysAboveGround);
45+
double? measuredHeightMeters = BuildingAttributeQueries.TryGetKnownPositiveMetric(
46+
buildingAttributes,
47+
BuildingMetricKind.MeasuredHeightMeters);
4448

4549
bool isMarking = displayName.Contains("Marking", StringComparison.OrdinalIgnoreCase)
4650
|| objectId.Contains("Marking", StringComparison.OrdinalIgnoreCase)

src/PlateauResoniteLink/Application/Importing/CityGmlSurfaceMaterialResolver.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,9 @@ private static ResolvedSurfaceMaterial ResolveSurfaceMaterial(
312312
FloorsAboveGround: cityObject.FloorsAboveGround,
313313
MeasuredHeightMeters: cityObject.MeasuredHeightMeters,
314314
GeometryHeightMeters: cityObject.GeometryHeightMeters,
315-
FootprintAreaSquareMeters: BuildingAttributeQueries.TryGetKnownPositiveMetric(cityObject.BuildingAttributes.BuildingFootprintArea),
315+
FootprintAreaSquareMeters: BuildingAttributeQueries.TryGetKnownPositiveMetric(
316+
cityObject.BuildingAttributes,
317+
BuildingMetricKind.BuildingFootprintArea),
316318
SurfaceRole: ToDefaultMaterialSurfaceRole(face.Role)));
317319
MaterialDepthOffset? depthOffset = cityObject.TerrainAligned
318320
? TerrainAlignedDepthOffset

src/PlateauResoniteLink/Application/Importing/CkanPlateauDatasetSourceResolver.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,19 @@ public async Task<ResolvedLocalPlateauImportRequest> ResolveAsync(
4141
ValidatedLocalDatasetLocation resolvedSource = await ResolveRequiredLocalDatasetLocationAsync(
4242
request.CityGmlSource,
4343
workRoot,
44-
resourcePrefix: "source-archive",
44+
resourcePrefix: ResolvedLocalPlateauImportRequest.RemoteCityGmlResourcePrefix,
4545
invalidateLocalFileCache: true,
4646
cancellationToken);
4747
ValidatedLocalDatasetLocation? resolvedDemTextureSource = await ResolveOptionalLocalDatasetLocationAsync(
4848
request.DemTextureSource,
4949
workRoot,
50-
resourcePrefix: "source-ortho",
50+
resourcePrefix: ResolvedLocalPlateauImportRequest.RemoteDemTextureResourcePrefix,
5151
invalidateLocalFileCache: false,
5252
cancellationToken);
5353

5454
return ResolvedLocalPlateauImportRequest.Create(
5555
request,
56+
workRoot,
5657
resolvedSource,
5758
resolvedDemTextureSource);
5859
}

0 commit comments

Comments
 (0)