2121import java .math .RoundingMode ;
2222import java .text .DecimalFormat ;
2323import java .util .ArrayList ;
24+ import java .util .Deque ;
2425import java .util .HashMap ;
25- import java .util .Iterator ;
26+ import java .util .LinkedList ;
2627import java .util .List ;
2728import java .util .Map ;
2829import java .util .Objects ;
4142import org .eclipse .set .core .services .geometry .PointObjectPositionService ;
4243import org .eclipse .set .model .planpro .BasisTypen .ENUMLinksRechts ;
4344import org .eclipse .set .model .planpro .BasisTypen .ENUMWirkrichtung ;
45+ import org .eclipse .set .model .planpro .Basisobjekte .Basis_Objekt ;
4446import org .eclipse .set .model .planpro .Basisobjekte .Bereich_Objekt ;
4547import org .eclipse .set .model .planpro .Basisobjekte .Punkt_Objekt ;
4648import org .eclipse .set .model .planpro .Basisobjekte .Punkt_Objekt_TOP_Kante_AttributeGroup ;
4951import org .eclipse .set .model .planpro .Geodaten .GEO_Knoten ;
5052import org .eclipse .set .model .planpro .Geodaten .GEO_Punkt ;
5153import org .eclipse .set .model .planpro .Geodaten .TOP_Kante ;
54+ import org .eclipse .set .model .planpro .Geodaten .TOP_Knoten ;
5255import org .eclipse .set .model .planpro .Ortung .FMA_Komponente ;
5356import org .eclipse .set .model .planpro .PZB .PZB_Element ;
5457import org .eclipse .set .model .planpro .Verweise .ID_GEO_Punkt_ohne_Proxy_TypeClass ;
5861import org .eclipse .set .ppmodel .extensions .BasisAttributExtensions ;
5962import org .eclipse .set .ppmodel .extensions .BasisObjektExtensions ;
6063import org .eclipse .set .ppmodel .extensions .EObjectExtensions ;
64+ import org .eclipse .set .ppmodel .extensions .GeoKanteExtensions ;
6165import org .eclipse .set .ppmodel .extensions .GeoKnotenExtensions ;
6266import org .eclipse .set .ppmodel .extensions .GeoPunktExtensions ;
6367import org .eclipse .set .ppmodel .extensions .TopKanteExtensions ;
68+ import org .eclipse .set .ppmodel .extensions .TopKnotenExtensions ;
6469import org .eclipse .set .ppmodel .extensions .container .MultiContainer_AttributeGroup ;
6570import org .eclipse .set .ppmodel .extensions .geometry .GEOKanteGeometryExtensions ;
6671import org .eclipse .set .ppmodel .extensions .utils .IterableExtensions ;
7479import org .osgi .service .event .EventAdmin ;
7580import org .osgi .service .event .EventConstants ;
7681import org .osgi .service .event .EventHandler ;
82+ import org .slf4j .Logger ;
83+ import org .slf4j .LoggerFactory ;
7784
7885import com .google .common .collect .Streams ;
7986
8996@ SuppressWarnings ("nls" )
9097public 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