Skip to content

Commit 1f423fe

Browse files
Fix GeoCoordinateValid always success (#1918)
* Fix GeoCoordinateValid always success * Fix GeoCoordinateValid.java * Update java/bundles/org.eclipse.set.feature.plazmodel/src/org/eclipse/set/feature/plazmodel/check/GeoCoordinateValid.java Fix typo in error message --------- Co-authored-by: Marius Heine <[email protected]>
1 parent c0fad23 commit 1f423fe

File tree

7 files changed

+184
-68
lines changed

7 files changed

+184
-68
lines changed

java/bundles/org.eclipse.set.application/src/org/eclipse/set/application/geometry/GeoKanteGeometryServiceImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,9 @@ public GEOKanteCoordinate getCoordinate(final GEOKanteMetadata md,
362362
.valueOf(md.getGeometry().getLength());
363363
final BigDecimal localDistance = distance.subtract(md.getStart());
364364
final BigDecimal scaledDistance = localDistance.doubleValue() != 0
365-
? localDistance.multiply(geoLength.divide(edgeLength,
366-
ToolboxConstants.ROUNDING_TO_PLACE,
367-
RoundingMode.HALF_UP))
365+
? localDistance.multiply(geoLength)
366+
.divide(edgeLength, ToolboxConstants.ROUNDING_TO_PLACE,
367+
RoundingMode.HALF_UP)
368368
: BigDecimal.ZERO;
369369
final SegmentPosition position = Geometries.getSegmentPosition(
370370
md.getGeometry(),

java/bundles/org.eclipse.set.basis/src/org/eclipse/set/basis/constants/ToolboxConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,11 @@ public interface CacheId {
342342
*/
343343
public static final String TABLE_TOPOLOGICAL_CELL = "topologicalCell";
344344

345+
/**
346+
* The tolerance value between TOP_Kante length and the sum of GEO_Kanten
347+
* length, which belong to this TOP_Kante (in Meter)
348+
*/
349+
public static final double TOP_GEO_LENGTH_TOLERANCE = 0.01;
345350
static {
346351
DEFAULT_HOME_DIR = "./";
347352
TMP_BASE_DIR = System.getProperty(ToolboxProperties.TMP_BASE_DIR,

java/bundles/org.eclipse.set.basis/src/org/eclipse/set/basis/geometry/Geometries.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
package org.eclipse.set.basis.geometry;
1010

1111
import java.math.BigDecimal;
12+
import java.math.RoundingMode;
1213
import java.util.LinkedList;
1314
import java.util.List;
1415

16+
import org.eclipse.set.basis.constants.ToolboxConstants;
1517
import org.eclipse.set.basis.graph.DirectedElementImpl;
1618
import org.locationtech.jts.algorithm.Angle;
1719
import org.locationtech.jts.geom.Coordinate;
@@ -230,8 +232,29 @@ private static DirectedElementImpl<LineString> getLineStringAtStart(
230232
private static SegmentPosition getSegmentPosition(
231233
final List<SegmentWithDistance> segments,
232234
final BigDecimal distance) {
235+
// Avoid worst case distance == 0
236+
if (distance.equals(BigDecimal.ZERO)) {
237+
return new SegmentPosition(segments.getFirst().segment,
238+
segments.getFirst().startDistance);
239+
}
240+
241+
// Avoid worst case distance == segment length
242+
// Return the last segment when the distance is greater than end
243+
// position with the acceptable value
244+
if (distance.compareTo(segments.getLast().endDistance()) >= 0) {
245+
final BigDecimal diff = distance
246+
.subtract(segments.getLast().endDistance())
247+
.setScale(ToolboxConstants.ROUNDING_TO_PLACE,
248+
RoundingMode.HALF_UP);
249+
if (diff.compareTo(BigDecimal.ZERO) == 0) {
250+
return new SegmentPosition(segments.getLast().segment,
251+
segments.getLast().startDistance);
252+
}
253+
return null;
254+
}
255+
233256
int left = 0;
234-
int right = segments.size();
257+
int right = segments.size() - 1;
235258
while (left <= right) {
236259
final int mid = left + (right - left) / 2;
237260
final SegmentWithDistance midSegment = segments.get(mid);
@@ -240,12 +263,14 @@ private static SegmentPosition getSegmentPosition(
240263
return new SegmentPosition(midSegment.segment,
241264
distance.subtract(midSegment.startDistance));
242265
}
243-
if (midSegment.startDistance().compareTo(distance) >= 0) {
266+
267+
if (midSegment.startDistance.compareTo(distance) >= 0) {
244268
right = mid - 1;
245269
} else {
246270
left = mid + 1;
247271
}
248272
}
273+
249274
return null;
250275
}
251276

java/bundles/org.eclipse.set.feature.plazmodel/src/org/eclipse/set/feature/plazmodel/check/GeoCoordinateValid.java

Lines changed: 131 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
import java.math.RoundingMode;
2222
import java.text.DecimalFormat;
2323
import java.util.ArrayList;
24+
import java.util.Deque;
2425
import java.util.HashMap;
25-
import java.util.Iterator;
26+
import java.util.LinkedList;
2627
import java.util.List;
2728
import java.util.Map;
2829
import java.util.Objects;
@@ -41,6 +42,7 @@
4142
import org.eclipse.set.core.services.geometry.PointObjectPositionService;
4243
import org.eclipse.set.model.planpro.BasisTypen.ENUMLinksRechts;
4344
import org.eclipse.set.model.planpro.BasisTypen.ENUMWirkrichtung;
45+
import org.eclipse.set.model.planpro.Basisobjekte.Basis_Objekt;
4446
import org.eclipse.set.model.planpro.Basisobjekte.Bereich_Objekt;
4547
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt;
4648
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt_TOP_Kante_AttributeGroup;
@@ -49,6 +51,7 @@
4951
import org.eclipse.set.model.planpro.Geodaten.GEO_Knoten;
5052
import org.eclipse.set.model.planpro.Geodaten.GEO_Punkt;
5153
import org.eclipse.set.model.planpro.Geodaten.TOP_Kante;
54+
import org.eclipse.set.model.planpro.Geodaten.TOP_Knoten;
5255
import org.eclipse.set.model.planpro.Ortung.FMA_Komponente;
5356
import org.eclipse.set.model.planpro.PZB.PZB_Element;
5457
import org.eclipse.set.model.planpro.Verweise.ID_GEO_Punkt_ohne_Proxy_TypeClass;
@@ -58,9 +61,11 @@
5861
import org.eclipse.set.ppmodel.extensions.BasisAttributExtensions;
5962
import org.eclipse.set.ppmodel.extensions.BasisObjektExtensions;
6063
import org.eclipse.set.ppmodel.extensions.EObjectExtensions;
64+
import org.eclipse.set.ppmodel.extensions.GeoKanteExtensions;
6165
import org.eclipse.set.ppmodel.extensions.GeoKnotenExtensions;
6266
import org.eclipse.set.ppmodel.extensions.GeoPunktExtensions;
6367
import org.eclipse.set.ppmodel.extensions.TopKanteExtensions;
68+
import org.eclipse.set.ppmodel.extensions.TopKnotenExtensions;
6469
import org.eclipse.set.ppmodel.extensions.container.MultiContainer_AttributeGroup;
6570
import org.eclipse.set.ppmodel.extensions.geometry.GEOKanteGeometryExtensions;
6671
import org.eclipse.set.ppmodel.extensions.utils.IterableExtensions;
@@ -74,6 +79,8 @@
7479
import org.osgi.service.event.EventAdmin;
7580
import org.osgi.service.event.EventConstants;
7681
import org.osgi.service.event.EventHandler;
82+
import org.slf4j.Logger;
83+
import org.slf4j.LoggerFactory;
7784

7885
import com.google.common.collect.Streams;
7986

@@ -89,6 +96,8 @@
8996
@SuppressWarnings("nls")
9097
public class GeoCoordinateValid extends AbstractPlazContainerCheck
9198
implements PlazCheck, EventHandler {
99+
static final Logger logger = LoggerFactory
100+
.getLogger(GeoCoordinateValid.class);
92101

93102
private static record GeoKnotenRange(Pair<GEO_Knoten, BigDecimal> start,
94103
Pair<GEO_Knoten, BigDecimal> end) {
@@ -106,7 +115,7 @@ public BigDecimal startDistance() {
106115
}
107116

108117
public GEO_Knoten endNode() {
109-
return start.getKey();
118+
return end.getKey();
110119
}
111120

112121
public GEO_Kante getGeoKante() {
@@ -161,36 +170,49 @@ protected List<PlazError> run(
161170
Map.of("GUID", po.getIdentitaet().getWert())));
162171
return;
163172
}
164-
final GEOKanteCoordinate geoKanteCoordinate = calculateCoordinate(
173+
174+
final GEOKanteCoordinate topCoordinate = calculateCoordinate(
165175
po, potk);
166-
if (geoKanteCoordinate == null
167-
|| getNullableObject(geoKanteCoordinate,
176+
if (topCoordinate == null
177+
|| getNullableObject(topCoordinate,
168178
e -> e.getCoordinate()).isEmpty()) {
179+
result.add(createGeoCoordinateError(po,
180+
"Es gibt Fehler bei der Berechnung der topologischen Koordinate",
181+
Map.of()));
169182
return;
170183
}
171184

172-
final GEO_Punkt relevantGeoPunkt = getSameCRSGEOPunkt(potk,
173-
geoKanteCoordinate.getCRS());
174-
if (relevantGeoPunkt == null) {
175-
return;
176-
}
177-
final Coordinate coordinate = geoKanteCoordinate
178-
.getCoordinate();
179-
final Coordinate gpCoordinate = GeoPunktExtensions
180-
.getCoordinate(relevantGeoPunkt);
181-
if (gpCoordinate == null) {
182-
result.add(creatErrorReport(relevantGeoPunkt));
183-
}
184-
185-
final double diff = coordinate.distance(gpCoordinate);
186-
if (diff > TOLERANT) {
187-
result.add(createErrorReport(po, potk, relevantGeoPunkt,
188-
diff));
185+
final PlazError error = validGeoCoordinate(po, potk,
186+
topCoordinate);
187+
if (error != null) {
188+
result.add(error);
189189
}
190190
}));
191191
return result;
192192
}
193193

194+
private PlazError validGeoCoordinate(final Punkt_Objekt po,
195+
final Punkt_Objekt_TOP_Kante_AttributeGroup potk,
196+
final GEOKanteCoordinate topCoordinate) {
197+
final GEO_Punkt relevantGeoPunkt = getSameCRSGEOPunkt(potk,
198+
topCoordinate.getCRS());
199+
if (relevantGeoPunkt == null) {
200+
return null;
201+
}
202+
final Coordinate coordinate = topCoordinate.getCoordinate();
203+
final Coordinate geoCoordinate = GeoPunktExtensions
204+
.getCoordinate(relevantGeoPunkt);
205+
if (geoCoordinate == null) {
206+
return creatErrorReport(relevantGeoPunkt);
207+
}
208+
209+
final double diff = coordinate.distance(geoCoordinate);
210+
if (diff > TOLERANT) {
211+
return createErrorReport(po, potk, relevantGeoPunkt, diff);
212+
}
213+
return null;
214+
}
215+
194216
private static List<Punkt_Objekt> getRelevantPOs(
195217
final MultiContainer_AttributeGroup container) {
196218
return Streams.stream(container.getPunktObjekts())
@@ -202,6 +224,10 @@ private static List<Punkt_Objekt> getRelevantPOs(
202224
.isPresent())
203225
|| po instanceof FMA_Komponente
204226
|| po instanceof PZB_Element)
227+
.filter(po -> po.getPunktObjektTOPKante()
228+
.stream()
229+
.anyMatch(potk -> !potk.getIDGEOPunktBerechnet()
230+
.isEmpty()))
205231
.toList();
206232
}
207233

@@ -211,15 +237,7 @@ private GEOKanteCoordinate calculateCoordinate(final Punkt_Objekt po,
211237
BigDecimal lateralDistance = null;
212238
GEOKanteMetadata geoKanteMetaData = alreadyFoundMetaData
213239
.parallelStream()
214-
.filter(md -> md.getGeoKante()
215-
.getIDGEOArt()
216-
.getValue()
217-
.equals(potk.getIDTOPKante().getValue())
218-
&& md.getStart()
219-
.compareTo(potk.getAbstand().getWert()) <= 0
220-
&& md.getEnd()
221-
.compareTo(
222-
potk.getAbstand().getWert()) >= 0)
240+
.filter(md -> isBelongToThisMetadata(md, potk))
223241
.findFirst()
224242
.orElse(null);
225243
if (geoKanteMetaData == null) {
@@ -250,9 +268,41 @@ private GEOKanteCoordinate calculateCoordinate(final Punkt_Objekt po,
250268
}
251269
return calculateCoordinate(geoKanteMetaData, potk);
252270
} catch (final Exception e) {
271+
logger.error(e.getMessage());
253272
return null;
254273
}
274+
}
275+
276+
private static boolean isBelongToThisMetadata(final GEOKanteMetadata md,
277+
final Punkt_Objekt_TOP_Kante_AttributeGroup potk) {
278+
final Basis_Objekt geoArt = md.getGeoKante().getIDGEOArt().getValue();
279+
if (!geoArt.equals(potk.getIDTOPKante().getValue())) {
280+
return false;
281+
}
255282

283+
final BigDecimal distance = potk.getAbstand().getWert();
284+
final BigDecimal start = md.getStart();
285+
if (distance.compareTo(start) < 0) {
286+
return false;
287+
}
288+
289+
final BigDecimal end = md.getEnd();
290+
if (distance.compareTo(end) <= 0) {
291+
return true;
292+
}
293+
294+
// Fall the GEOKanteMetadata is the last Geo_Kante of the Top_Kante and
295+
// the length of this Top_Kante greater than the sum Geo_Kanten length
296+
final GEO_Knoten endGeoKnoten = GeoKanteExtensions
297+
.getOpposite(md.getGeoKante(), md.getGeoKnoten());
298+
final TOP_Knoten topKnotenB = TopKanteExtensions
299+
.getTOPKnotenB(potk.getIDTOPKante().getValue());
300+
if (TopKnotenExtensions.getGEOKnoten(topKnotenB).equals(endGeoKnoten)) {
301+
final BigDecimal diff = distance.subtract(end);
302+
return diff.compareTo(BigDecimal
303+
.valueOf(ToolboxConstants.TOP_GEO_LENGTH_TOLERANCE)) <= 0;
304+
}
305+
return false;
256306
}
257307

258308
private GEOKanteCoordinate calculateCoordinate(
@@ -285,18 +335,36 @@ private static GEOKanteCoordinate calculateCoordinate(
285335
final ENUMWirkrichtung wirkrichtung) {
286336
final BigDecimal geoLength = BigDecimal
287337
.valueOf(md.getGeometry().getLength());
288-
final BigDecimal geoKanteLength = md.getGeoKante()
289-
.getGEOKanteAllg()
290-
.getGEOLaenge()
291-
.getWert();
292-
final BigDecimal localDistance = potk.getAbstand()
338+
final BigDecimal geoKanteLength = md.getLength();
339+
340+
BigDecimal localDistance = potk.getAbstand()
293341
.getWert()
294342
.subtract(md.getStart());
343+
344+
// In the case, that the TOP_Kante length is greater than the sum of
345+
// GEO_Kante length and the different value is in acceptable range, then
346+
// take end distance of GeoKanteMetadata
347+
if (potk.getAbstand()
348+
.getWert()
349+
.compareTo(TopKanteExtensions
350+
.getLaenge(potk.getIDTOPKante().getValue())) == 0
351+
&& potk.getAbstand().getWert().compareTo(md.getEnd()) > 0) {
352+
final BigDecimal diff = potk.getAbstand()
353+
.getWert()
354+
.subtract(md.getEnd());
355+
if (diff.compareTo(BigDecimal
356+
.valueOf(ToolboxConstants.TOP_GEO_LENGTH_TOLERANCE)) <= 0) {
357+
localDistance = md.getLength();
358+
}
359+
}
360+
295361
final BigDecimal scaleDistance = localDistance.doubleValue() != 0
296-
? localDistance.multiply(geoLength.divide(geoKanteLength,
297-
ToolboxConstants.ROUNDING_TO_PLACE,
298-
RoundingMode.HALF_UP))
362+
? localDistance.multiply(geoLength)
363+
.divide(geoKanteLength,
364+
ToolboxConstants.ROUNDING_TO_PLACE,
365+
RoundingMode.HALF_UP)
299366
: BigDecimal.ZERO;
367+
300368
final SegmentPosition position = getSegmentPosition(md.getGeometry(),
301369
getCoordinate(md.getGeoKnoten()), scaleDistance);
302370
final LineSegment tangent = getTangent(md.getGeoKante(), position);
@@ -312,10 +380,10 @@ private static GEOKanteMetadata getGeoKanteMetaData(
312380
final TOP_Kante topkante = potk.getIDTOPKante().getValue();
313381
final GeoKnotenRange relevantGeoKnotenRange = getRelevantGeoKnotenRange(
314382
potk);
383+
315384
final GEO_Kante geoKante = relevantGeoKnotenRange.getGeoKante();
316385
final BigDecimal geoArtScalingFactor = BasisObjektExtensions
317386
.getGeoArtScalingFactor(topkante);
318-
319387
final BigDecimal geoKanteLength = geoKante.getGEOKanteAllg()
320388
.getGEOLaenge()
321389
.getWert()
@@ -347,16 +415,29 @@ private static GeoKnotenRange getRelevantGeoKnotenRange(
347415
final Punkt_Objekt_TOP_Kante_AttributeGroup potk) {
348416
final TOP_Kante topKante = potk.getIDTOPKante().getValue();
349417
final BigDecimal distance = potk.getAbstand().getWert();
350-
final Iterator<Pair<GEO_Knoten, BigDecimal>> geoKnotenWithDistance = Streams
351-
.stream(TopKanteExtensions.getGeoKnotenWithDistance(topKante))
352-
.iterator();
353-
final List<GeoKnotenRange> ranges = new ArrayList<>();
354-
Pair<GEO_Knoten, BigDecimal> current = geoKnotenWithDistance.next();
355-
while (geoKnotenWithDistance.hasNext()) {
356-
final Pair<GEO_Knoten, BigDecimal> next = geoKnotenWithDistance
357-
.next();
358-
ranges.add(new GeoKnotenRange(current, next));
359-
current = next;
418+
final Deque<Pair<GEO_Knoten, BigDecimal>> geoKnotenDeque = TopKanteExtensions
419+
.getGeoKnotenWithDistance(topKante);
420+
if (distance.equals(BigDecimal.ZERO)) {
421+
// Get two first element of the deque
422+
return new GeoKnotenRange(geoKnotenDeque.poll(),
423+
geoKnotenDeque.poll());
424+
}
425+
426+
if (distance
427+
.equals(topKante.getTOPKanteAllg().getTOPLaenge().getWert())) {
428+
final Pair<GEO_Knoten, BigDecimal> lastNode = geoKnotenDeque
429+
.pollLast();
430+
final Pair<GEO_Knoten, BigDecimal> previousLastNode = geoKnotenDeque
431+
.pollLast();
432+
return new GeoKnotenRange(previousLastNode, lastNode);
433+
}
434+
435+
final List<GeoKnotenRange> ranges = new LinkedList<>();
436+
for (Pair<GEO_Knoten, BigDecimal> currentNode; (currentNode = geoKnotenDeque
437+
.poll()) != null && !geoKnotenDeque.isEmpty();) {
438+
final Pair<GEO_Knoten, BigDecimal> nextNode = geoKnotenDeque
439+
.element();
440+
ranges.add(new GeoKnotenRange(currentNode, nextNode));
360441
}
361442

362443
return ranges.stream()

0 commit comments

Comments
 (0)