Skip to content

Commit

Permalink
PlaZ-Model: Improve GeoCoordinateValid (#904)
Browse files Browse the repository at this point in the history
  • Loading branch information
TruongQuangSB authored Sep 27, 2024
1 parent 930d651 commit 8820e99
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
package org.eclipse.set.application.geometry;

import static org.eclipse.set.ppmodel.extensions.EObjectExtensions.getNullableObject;

import java.util.List;

import org.eclipse.set.basis.geometry.GEOKanteCoordinate;
Expand Down Expand Up @@ -72,64 +74,31 @@ public GEOKanteCoordinate getCoordinate(final Punkt_Objekt punktObjekt) {
@Override
public GEOKanteCoordinate getCoordinate(
final Punkt_Objekt_TOP_Kante_AttributeGroup singlePoint) {
if (singlePoint == null || singlePoint.getAbstand() == null
|| singlePoint.getAbstand().getWert() == null) {
final GEOKanteMetadata geoKante = getGeoKanteMetadata(singlePoint);
if (geoKante == null) {
return null;
}

final double distance = singlePoint.getAbstand().getWert()
.doubleValue();
ENUMWirkrichtung direction = null;
if (singlePoint.getWirkrichtung() != null) {
direction = singlePoint.getWirkrichtung().getWert();
}
final double lateralDistance = getLateralDistance(singlePoint,
geoKante);
return getCoordinate(singlePoint, lateralDistance);
}

final TOP_Kante topKante = singlePoint.getIDTOPKante().getValue();
final TOP_Knoten topKnotenA = topKante.getIDTOPKnotenA().getValue();
@Override
public GEOKanteCoordinate getCoordinate(
final Punkt_Objekt_TOP_Kante_AttributeGroup singlePoint,
final double lateralDistance) {

final GEOKanteMetadata geoKante = geometryService
.getGeoKanteAt(topKante, topKnotenA, distance);
final GEOKanteMetadata geoKante = getGeoKanteMetadata(singlePoint);
if (geoKante == null) {
return null;
}

double lateralDistance = 0;
if (singlePoint.getSeitlicherAbstand() != null
&& singlePoint.getSeitlicherAbstand().getWert() != null) {
lateralDistance = singlePoint.getSeitlicherAbstand().getWert()
.doubleValue();
} else {
// Determine the track type
final GEOKanteSegment segment = geoKante
.getContainingSegment(distance);
final List<ENUMGleisart> trackType = segment.getBereichObjekte()
.stream().filter(Gleis_Art.class::isInstance)
.map(ga -> ((Gleis_Art) ga).getGleisart().getWert())
.filter(c -> c != null).toList();

// Determine the object distance according to the local track type
if (trackType.isEmpty()) {
// No local track type. Default to 0 and record an error
lateralDistance = 0;
return geometryService.getCoordinate(geoKante, distance,
lateralDistance, direction);
}

if (trackType
.getFirst() == ENUMGleisart.ENUM_GLEISART_STRECKENGLEIS) {
lateralDistance = PUNKT_OBJEKT_LATERAL_DISTANCE_OTHER;
} else {
lateralDistance = PUNKT_OBJEKT_LATERAL_DISTANCE_IN_STATION;
}

// If the object should be positioned to the left of the track,
// invert the lateral distance
if (singlePoint.getSeitlicheLage() != null && singlePoint
.getSeitlicheLage()
.getWert() == ENUMLinksRechts.ENUM_LINKS_RECHTS_LINKS) {
lateralDistance = -lateralDistance;
}
ENUMWirkrichtung direction = null;
if (singlePoint.getWirkrichtung() != null) {
direction = singlePoint.getWirkrichtung().getWert();
}
final double distance = singlePoint.getAbstand().getWert()
.doubleValue();
if (direction == ENUMWirkrichtung.ENUM_WIRKRICHTUNG_BEIDE) {
// For Punkt_Objekte with a bilateral direction fall back to
// ENUM_WIRKRICHTUNG_IN
Expand All @@ -140,4 +109,53 @@ public GEOKanteCoordinate getCoordinate(
return geometryService.getCoordinate(geoKante, distance,
lateralDistance, direction);
}

private GEOKanteMetadata getGeoKanteMetadata(
final Punkt_Objekt_TOP_Kante_AttributeGroup singlePoint) {
if (singlePoint == null || singlePoint.getAbstand() == null
|| singlePoint.getAbstand().getWert() == null) {
return null;
}

final double distance = singlePoint.getAbstand().getWert()
.doubleValue();

final TOP_Kante topKante = singlePoint.getIDTOPKante().getValue();
final TOP_Knoten topKnotenA = topKante.getIDTOPKnotenA().getValue();

return geometryService.getGeoKanteAt(topKante, topKnotenA, distance);
}

private static double getLateralDistance(
final Punkt_Objekt_TOP_Kante_AttributeGroup singlePoint,
final GEOKanteMetadata geoKante) {
if (singlePoint.getSeitlicherAbstand() != null
&& singlePoint.getSeitlicherAbstand().getWert() != null) {
return singlePoint.getSeitlicherAbstand().getWert().doubleValue();
}
final double distance = singlePoint.getSeitlicherAbstand().getWert()
.doubleValue();
// Determine the track type
final GEOKanteSegment segment = geoKante.getContainingSegment(distance);
final List<ENUMGleisart> trackType = segment.getBereichObjekte()
.stream().filter(Gleis_Art.class::isInstance)
.map(ga -> ((Gleis_Art) ga).getGleisart().getWert())
.filter(c -> c != null).toList();

// Determine the object distance according to the local track type
if (trackType.isEmpty()) {
// No local track type. Default to 0 and record an error
return 0;
}
final double lateralDistance = trackType
.getFirst() == ENUMGleisart.ENUM_GLEISART_STRECKENGLEIS
? PUNKT_OBJEKT_LATERAL_DISTANCE_OTHER
: PUNKT_OBJEKT_LATERAL_DISTANCE_IN_STATION;
final ENUMLinksRechts side = getNullableObject(singlePoint,
point -> point.getSeitlicheLage().getWert()).orElse(null);
if (side != null && side == ENUMLinksRechts.ENUM_LINKS_RECHTS_LINKS) {
return -lateralDistance;
}
return lateralDistance;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt_TOP_Kante_AttributeGroup;

/**
*
*
*/
public interface PointObjectPositionService {
Expand All @@ -32,4 +33,14 @@ public interface PointObjectPositionService {
*/
GEOKanteCoordinate getCoordinate(
Punkt_Objekt_TOP_Kante_AttributeGroup potk);

/**
* @param potk
* the punkt objekt top kante
* @param lateralDistance
* the lataral distance of potk
* @return the coordinate at punkt objekt
*/
GEOKanteCoordinate getCoordinate(Punkt_Objekt_TOP_Kante_AttributeGroup potk,
double lateralDistance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,20 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.StreamSupport;

import org.apache.commons.text.StringSubstitutor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.set.basis.constants.Events;
import org.eclipse.set.basis.geometry.GEOKanteCoordinate;
import org.eclipse.set.core.services.geometry.GeoKanteGeometryService;
import org.eclipse.set.core.services.geometry.PointObjectPositionService;
import org.eclipse.set.model.planpro.BasisTypen.ENUMLinksRechts;
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt;
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt_TOP_Kante_AttributeGroup;
import org.eclipse.set.model.planpro.Geodaten.ENUMGEOKoordinatensystem;
import org.eclipse.set.model.planpro.Geodaten.GEO_Punkt;
import org.eclipse.set.model.planpro.Ortung.FMA_Komponente;
import org.eclipse.set.model.planpro.PZB.PZB_Element;
import org.eclipse.set.model.planpro.Verweise.ID_GEO_Punkt_ohne_Proxy_TypeClass;
import org.eclipse.set.model.plazmodel.PlazError;
import org.eclipse.set.model.plazmodel.PlazFactory;
Expand All @@ -46,6 +48,8 @@
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

import com.google.common.collect.Streams;

/**
* Plausibilty checked of given geocoordinate from
* {@link Punkt_Objekt_TOP_Kante_AttributeGroup#getIDGEOPunktBerechnet()}
Expand All @@ -66,6 +70,10 @@ public class GeoCoordinateValid extends AbstractPlazContainerCheck
@Reference
EventAdmin eventAdmin;

// The half of track width is lateral distance for PZB_Element and
// FMA_Komponent
static double FMA_PZB_LATERAL_DISTANCE = 1.435 / 2;

@Override
public void handleEvent(final Event event) {
final Map<String, Class<? extends PlazCheck>> properties = new HashMap<>();
Expand All @@ -81,56 +89,86 @@ protected List<PlazError> run(
}

final List<PlazError> result = new ArrayList<>();
final List<Punkt_Objekt> punktObjekts = StreamSupport
.stream(container.getAllContents().spliterator(), false)
.filter(Punkt_Objekt.class::isInstance)
.map(Punkt_Objekt.class::cast).toList();
punktObjekts.forEach(po -> po.getPunktObjektTOPKante().forEach(potk -> {
if (isNotDistinctCoordinateSystem(potk)) {
result.add(createGeoCoordinateError(po,
"Der Punkt_Objekt_Top_Kante des Punkt_Objekt: {GUID} würde auf mehrere GEO_Punkt mit gleichen Koordinatensystem verweisen",
Map.of("GUID", po.getIdentitaet().getWert())));
return;
}
final GEOKanteCoordinate geoKanteCoordinate = pointObjectPositionService
.getCoordinate(potk);
if (geoKanteCoordinate == null
|| getNullableObject(geoKanteCoordinate,
e -> e.getCoordinate().getCoordinate()).isEmpty()) {
return;
}
final List<GEO_Punkt> givenGEOPunkts = potk.getIDGEOPunktBerechnet()
.stream().map(e -> e.getValue()).filter(Objects::nonNull)
.toList();
final Coordinate coordinate = geoKanteCoordinate.getCoordinate()
.getCoordinate();
final GEO_Punkt relevantGeoPunkt = givenGEOPunkts.stream()
.filter(gp -> getNullableObject(gp, e -> e.getGEOPunktAllg()
.getGEOKoordinatensystem().getWert()).isPresent())
.filter(gp -> {
final ENUMGEOKoordinatensystem coorsys = gp
.getGEOPunktAllg().getGEOKoordinatensystem()
.getWert();
return coorsys.equals(geoKanteCoordinate.getCRS());
}).findFirst().orElse(null);
if (relevantGeoPunkt == null) {
return;
}
givenGEOPunkts.forEach(gp -> {
final Coordinate gpCoordinate = GeoPunktExtensions
.getCoordinate(gp);
if (gpCoordinate == null) {
result.add(creatErrorReport(gp));
}
final double diff = coordinate.distance(gpCoordinate);
if (diff > TOLERANT) {
result.add(createErrorReport(po, potk, gp, diff));
}
});
}));
getRelevantPOs(container)
.forEach(po -> po.getPunktObjektTOPKante().forEach(potk -> {
if (isNotDistinctCoordinateSystem(potk)) {
result.add(createGeoCoordinateError(po,
"Der Punkt_Objekt_Top_Kante des Punkt_Objekt: {GUID} würde auf mehrere GEO_Punkt mit gleichen Koordinatensystem verweisen",
Map.of("GUID", po.getIdentitaet().getWert())));
return;
}
final GEOKanteCoordinate geoKanteCoordinate = getPointGEOCoordinate(
po, potk);
if (geoKanteCoordinate == null
|| getNullableObject(geoKanteCoordinate,
e -> e.getCoordinate().getCoordinate())
.isEmpty()) {
return;
}

final GEO_Punkt relevantGeoPunkt = getSameCRSGEOPunkt(potk,
geoKanteCoordinate.getCRS());
if (relevantGeoPunkt == null) {
return;
}
final Coordinate coordinate = geoKanteCoordinate
.getCoordinate().getCoordinate();
final Coordinate gpCoordinate = GeoPunktExtensions
.getCoordinate(relevantGeoPunkt);
if (gpCoordinate == null) {
result.add(creatErrorReport(relevantGeoPunkt));
}
final double diff = coordinate.distance(gpCoordinate);
if (diff > TOLERANT) {
result.add(createErrorReport(po, potk, relevantGeoPunkt,
diff));
}
}));
return result;
}

private static List<Punkt_Objekt> getRelevantPOs(
final MultiContainer_AttributeGroup container) {
return Streams.stream(container.getPunktObjekts()).parallel()
.filter(po -> po.getPunktObjektTOPKante().stream()
.anyMatch(potk -> getNullableObject(potk,
ele -> ele.getSeitlicherAbstand().getWert())
.isPresent())
|| po instanceof FMA_Komponente
|| po instanceof PZB_Element)
.toList();
}

private GEOKanteCoordinate getPointGEOCoordinate(final Punkt_Objekt po,
final Punkt_Objekt_TOP_Kante_AttributeGroup potk) {
if (po instanceof PZB_Element || po instanceof FMA_Komponente) {
final ENUMLinksRechts side = getNullableObject(potk,
point -> point.getSeitlicheLage().getWert()).orElse(null);
if (side != null
&& side == ENUMLinksRechts.ENUM_LINKS_RECHTS_LINKS) {
return pointObjectPositionService.getCoordinate(potk,
-FMA_PZB_LATERAL_DISTANCE);
}
return pointObjectPositionService.getCoordinate(potk,
FMA_PZB_LATERAL_DISTANCE);

}
return pointObjectPositionService.getCoordinate(potk);
}

private static GEO_Punkt getSameCRSGEOPunkt(
final Punkt_Objekt_TOP_Kante_AttributeGroup potk,
final ENUMGEOKoordinatensystem crs) {
return potk.getIDGEOPunktBerechnet().stream().map(e -> e.getValue())
.filter(Objects::nonNull).filter(gp -> {
final ENUMGEOKoordinatensystem geoPunktCRS = getNullableObject(
gp, e -> e.getGEOPunktAllg()
.getGEOKoordinatensystem().getWert())
.orElse(null);
return geoPunktCRS != null && geoPunktCRS.equals(crs);
}).findFirst().orElse(null);
}

private PlazError creatErrorReport(final GEO_Punkt gp) {
EObject errObj = gp;
if (gp.getGEOPunktAllg() == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ import org.eclipse.set.model.planpro.Basisobjekte.Ur_Objekt
import org.eclipse.set.model.planpro.Basisobjekte.Basis_Objekt
import org.eclipse.emf.ecore.EClass
import org.eclipse.set.model.planpro.Basisobjekte.Bereich_Objekt
import org.eclipse.set.model.planpro.Basisobjekte.Punkt_Objekt

/**
* Read-only metaobject which provides a similar API to {@link Container_AttributeGroup},
Expand Down Expand Up @@ -260,7 +261,7 @@ class MultiContainer_AttributeGroup {
def Iterable<Ur_Objekt> getUrObjekt() {
return containers.flatMap[eAllContents.filter(Ur_Objekt).toList]
}

/**
* Returns all entities
*
Expand Down Expand Up @@ -288,6 +289,13 @@ class MultiContainer_AttributeGroup {
return containers.flatMap[eContents.filter(Bereich_Objekt)]
}

/**
* @return all Punkt_Objekt instances
*/
def Iterable<Punkt_Objekt> getPunktObjekts() {
return containers.flatMap[eAllContents.filter(Punkt_Objekt).toList]
}

/**
* Returns the size of the combined containers
*
Expand All @@ -302,9 +310,9 @@ class MultiContainer_AttributeGroup {
*
* @return all entities of a given class type
*/
def <T> Iterable<T> get(Class<T> clazz) {
return containers.flatMap[eContents.filter(clazz)]
}
def <T> Iterable<T> get(Class<T> clazz) {
return containers.flatMap[eContents.filter(clazz)]
}

/* Generated methods follow. Each method simply forwards the call to all contained LST_Zustand objects
* and constructs an Iterable from the results. This should reflect the API of Container_AttributeGroup
Expand All @@ -317,7 +325,7 @@ class MultiContainer_AttributeGroup {
def Iterable<TOP_Kante> getTOPKante() {
return containers.flatMap[TOPKante]
}

def Iterable<Ueberhoehungslinie> getUeberhoehungslinie() {
return containers.flatMap[ueberhoehungslinie]
}
Expand Down

0 comments on commit 8820e99

Please sign in to comment.