Skip to content

Commit

Permalink
Add support for LoD changes in geometries
Browse files Browse the repository at this point in the history
  • Loading branch information
Son-HNguyen committed Apr 15, 2024
1 parent 1fb52b3 commit e59b819
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 21 deletions.
23 changes: 23 additions & 0 deletions src/main/java/jgraf/citygml/CityGMLNeo4jDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ private boolean diff(Transaction tx,
case SIMILAR_GEOMETRY -> {
// Found geometric equivalence -> skip geometric and match non-geometric
rightMatchedNodes.add(rightRelNode.getElementId());
attachLodChanges(tx, diffResult, leftRelNode, rightRelNode);
boolean tmpDiffFound = diff(
tx, leftRelNode, rightRelNode, set,
GraphUtils.listAll(skipProps, null),
Expand All @@ -723,6 +724,7 @@ private boolean diff(Transaction tx,
// Found a geometric match but translated by a vector != 0 and with a different size
// First create an interpretation node for later analyses
attachGeomChanges(tx, diffResult, leftRelNode, rightRelNode);
attachLodChanges(tx, diffResult, leftRelNode, rightRelNode);
// Then treat it as usual matched geometry
rightMatchedNodes.add(rightRelNode.getElementId());
boolean tmpDiffFound = diff(
Expand All @@ -736,6 +738,7 @@ private boolean diff(Transaction tx,
// Found a geometric match but translated by a vector != 0
// First create an interpretation node for later analyses
attachGeomChanges(tx, diffResult, leftRelNode, rightRelNode);
attachLodChanges(tx, diffResult, leftRelNode, rightRelNode);
// Then treat it as usual matched geometry
rightMatchedNodes.add(rightRelNode.getElementId());
boolean tmpDiffFound = diff(
Expand All @@ -749,6 +752,7 @@ private boolean diff(Transaction tx,
// Found a geometric match with a different size
// First create an interpretation node for later analyses
attachGeomChanges(tx, diffResult, leftRelNode, rightRelNode);
attachLodChanges(tx, diffResult, leftRelNode, rightRelNode);
// Then treat it as usual matched geometry
rightMatchedNodes.add(rightRelNode.getElementId());
boolean tmpDiffFound = diff(
Expand Down Expand Up @@ -882,6 +886,25 @@ private void attachGeomChanges(Transaction tx, DiffResult diffResult, Node leftR
}
}

private void attachLodChanges(Transaction tx, DiffResult diffResult, Node leftRelNode, Node rightRelNode) {
if (!(diffResult instanceof DiffResultGeo res)) return;
int[] lods = res.getLods();
if (lods == null || lods.length == 0 || lods.length > 2
|| lods[0] == lods[1] || lods[0] < 0 || lods[1] < 0) return;
Label anchor = res.getAnchor();
Node leftTargetNode = null;
Node rightTargetNode = null;
if (anchor != null) {
leftTargetNode = getAnchorNode(tx, leftRelNode, anchor);
rightTargetNode = getAnchorNode(tx, rightRelNode, anchor);
} else {
leftTargetNode = leftRelNode;
rightTargetNode = rightRelNode;
}

Patterns.markLodChange(tx, leftTargetNode, rightTargetNode, lods[0], lods[1]);
}

// protected abstract Node getAnchorNode(Transaction tx, Node node, Label anchor);

private Node getAnchorNode(Transaction tx, Node node, Label anchor) {
Expand Down
31 changes: 22 additions & 9 deletions src/main/java/jgraf/citygml/CityGMLNeo4jDBV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeo(
SimilarityLevel.SIMILAR_GEOMETRY,
-minCentroidTranslation.get(),
null,
null, // TODO Label list to skip for solids
null
));
Expand All @@ -620,6 +621,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeo(
SimilarityLevel.SIMILAR_GEOMETRY,
maxOverlapRatio.get(),
null,
null, // TODO Label list to skip for solids
null
));
Expand Down Expand Up @@ -672,6 +674,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
Node candidateTranslationResize = null;
Vector3D minResize = Vector3D.of(maxAllowed, maxAllowed, maxAllowed);
double minResizeNorm = config.MATCHER_TRANSLATION_DISTANCE;
int candidateLod = -1;

for (Relationship rightRel : rightNode.getRelationships(Direction.OUTGOING, leftRel.getType())) {
Node rightRelNode = rightRel.getEndNode();
Expand All @@ -683,6 +686,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left

// Surface type
Class<?> rightBSType = rightMetricBSP.getSurfaceType();
if (!leftBSType.equals(rightBSType)) continue;

// Using bbox for convex and non-convex polygons
Vector3D[] rightBBox = rightMetricBSP.getBbox();
Expand All @@ -702,12 +706,6 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
// LOD
int rightLOD = rightMetricBSP.getHighestLOD();

// Check label
if (!leftBSType.equals(rightBSType)) continue;

// Check LOD
if (leftLOD != rightLOD) continue;

// Compute diff in orientation
double angle = leftNormal.angle(rightNormal);
if (!anglePrecision.eqZero(angle)) {
Expand All @@ -727,6 +725,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeo(
SimilarityLevel.SIMILAR_GEOMETRY,
1,
new int[]{leftLOD, rightLOD},
List.of(Label.label(MultiSurface.class.getName())),
null
));
Expand All @@ -737,6 +736,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
return new AbstractMap.SimpleEntry<>(rightRelNode,
new DiffResultGeoSize(
sizeChange.toArray(),
new int[]{leftLOD, rightLOD},
List.of(Label.label(MultiSurface.class.getName())),
Label.label(SurfaceProperty.class.getName())
));
Expand Down Expand Up @@ -776,14 +776,18 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
}
if (k == leftPoints.size()) {
// Same orientation, same size, but with translation -> Find min translation
if (isSet) candidateTranslationSameSize = rightRelNode;
if (isSet) {
candidateTranslationSameSize = rightRelNode;
candidateLod = rightLOD;
}
} else {
if (isSet) {
double resizeNorm = sizeChange.norm();
if (resizeNorm < minResizeNorm) {
minResizeNorm = resizeNorm;
minResize = sizeChange;
candidateTranslationResize = rightRelNode;
candidateLod = rightLOD;
}
}
}
Expand Down Expand Up @@ -823,6 +827,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeoTranslationResize(
minTranslation.toArray(),
minResize.toArray(),
new int[]{leftLOD, candidateLod},
List.of(Label.label(MultiSurface.class.getName())),
Label.label(SurfaceProperty.class.getName())
));
Expand All @@ -835,6 +840,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
return new AbstractMap.SimpleEntry<>(candidateTranslationSameSize,
new DiffResultGeoTranslation(
minTranslation.toArray(),
new int[]{leftLOD, candidateLod},
List.of(Label.label(MultiSurface.class.getName())),
Label.label(SurfaceProperty.class.getName())
));
Expand All @@ -847,6 +853,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeoTranslationResize(
minTranslation.toArray(),
minResize.toArray(),
new int[]{leftLOD, candidateLod},
List.of(Label.label(MultiSurface.class.getName())),
Label.label(SurfaceProperty.class.getName())
));
Expand All @@ -872,6 +879,7 @@ protected Map.Entry<Node, DiffResult> findBest(Transaction tx, Relationship left
new DiffResultGeo(
SimilarityLevel.SIMILAR_GEOMETRY,
1,
null, // TODO Diff LODs for implicit geometries?
List.of(Label.label(GeometryProperty.class.getName())),
null
));
Expand Down Expand Up @@ -948,6 +956,7 @@ && isMultiCurveContainedInLines3D(rightMultiCurve, leftLines, lengthPrecision))
new DiffResultGeo(
SimilarityLevel.SIMILAR_GEOMETRY,
1,
null, // TODO Diff LODs for curves?
List.of(Label.label(LineString.class.getName())), // TODO Label list to skip for MultiCurves
null
));
Expand Down Expand Up @@ -983,6 +992,7 @@ && isMultiCurveContainedInLines3D(rightMultiCurve, translatedLeftLines, lengthPr
return new AbstractMap.SimpleEntry<>(candidate,
new DiffResultGeoTranslation(
minTranslation.toArray(),
null, // TODO Diff LODs for curves?
List.of(Label.label(LineString.class.getName())), // TODO Label list to skip for polygons
null
));
Expand Down Expand Up @@ -1034,6 +1044,7 @@ && isMultiCurveContainedInLines3D(rightMultiCurve, translatedLeftLines, lengthPr
new DiffResultGeo(
SimilarityLevel.EQUIVALENCE,
minDistance.get(),
null,
null, // TODO Label list to skip for points
null
));
Expand Down Expand Up @@ -1081,8 +1092,9 @@ && isMultiCurveContainedInLines3D(rightMultiCurve, translatedLeftLines, lengthPr
}
if (leftObj instanceof MeasureAttribute leftGen) {
MeasureAttribute rightGen = (MeasureAttribute) rightObj;
Double diff = compareMeasurements(leftGen, rightGen);
return leftGen.getName().equals(rightGen.getName())
&& compareMeasurements(leftGen.getValue(), rightGen.getValue()) == 0;
&& diff != null && diff == 0;
}
if (leftObj instanceof StringAttribute leftGen) {
StringAttribute rightGen = (StringAttribute) rightObj;
Expand Down Expand Up @@ -1135,7 +1147,8 @@ && isMultiCurveContainedInLines3D(rightMultiCurve, translatedLeftLines, lengthPr
if (!rightRelNode.hasLabel(Label.label(Measure.class.getName()))
&& !rightRelNode.hasLabel(Label.label(Length.class.getName()))) return false;
Measure rightMeasure = (Measure) toObject(rightRelNode);
return compareMeasurements(leftMeasure, rightMeasure) == 0;
Double diff = compareMeasurements(leftMeasure, rightMeasure);
return diff != null && diff == 0;
})
.toList();
if (candidates.isEmpty()) {
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/jgraf/citygml/DiffResultGeo.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,23 @@ public class DiffResultGeo extends DiffResult {
protected List<Label> skip; // skip nodes with these labels -> prune paths while matching
protected Label anchor; // specify where to attach changes (other than default source node where change is detected)

public DiffResultGeo(SimilarityLevel level, double value, List<Label> skip, Label anchor) {
protected int[] lods; // lods[0] = original lod, lods[1] = new lod

public DiffResultGeo(SimilarityLevel level, double value, int[] lods, List<Label> skip, Label anchor) {
super(level, value);
this.lods = lods;
this.skip = skip;
this.anchor = anchor;
}

public int[] getLods() {
return lods;
}

public void setLods(int[] lods) {
this.lods = lods;
}

public List<Label> getSkip() {
return skip;
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/jgraf/citygml/DiffResultGeoSize.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
public class DiffResultGeoSize extends DiffResultGeo {
private double[] delta;

public DiffResultGeoSize(double[] delta, List<Label> skip, Label anchor) {
public DiffResultGeoSize(double[] delta, int[] lods, List<Label> skip, Label anchor) {
// Switch sign of deltas so that higher value means higher confidence
super(SimilarityLevel.SIMILAR_GEOMETRY_SIZE_CHANGE, -1 * (delta[0] + delta[1] + delta[2]), skip, anchor);
super(SimilarityLevel.SIMILAR_GEOMETRY_SIZE_CHANGE,
-1 * (delta[0] + delta[1] + delta[2]), lods, skip, anchor);
// Avoid multiplication of delta[i] since they can be 0
this.delta = delta;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/jgraf/citygml/DiffResultGeoTranslation.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
public class DiffResultGeoTranslation extends DiffResultGeo {
private double[] vector;

public DiffResultGeoTranslation(double[] vector, List<Label> skip, Label anchor) {
public DiffResultGeoTranslation(double[] vector, int[] lods, List<Label> skip, Label anchor) {
// Switch sign of norm of vector so that higher value means higher confidence
super(SimilarityLevel.SIMILAR_GEOMETRY_TRANSLATION,
-1 * Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]),
skip, anchor);
lods, skip, anchor);
this.vector = vector;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ public class DiffResultGeoTranslationResize extends DiffResultGeo {
private double[] vector;
private double[] delta;

public DiffResultGeoTranslationResize(double[] vector, double[] delta,
public DiffResultGeoTranslationResize(double[] vector, double[] delta, int[] lods,
List<Label> skip, Label anchor) {
super(SimilarityLevel.SIMILAR_GEOMETRY_TRANSLATION_SIZE_CHANGE,
-1 * Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2])
- 1 * (delta[0] + delta[1] + delta[2]),
skip,
anchor);
lods, skip, anchor);
this.vector = vector;
this.delta = delta;
}
Expand Down
16 changes: 12 additions & 4 deletions src/main/java/jgraf/citygml/Patterns.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import com.github.davidmoten.rtree.geometry.Rectangle;
import jgraf.neo4j.Neo4jDB;
import jgraf.neo4j.Neo4jGraphRef;
import jgraf.neo4j.diff.Change;
import jgraf.neo4j.diff.DeleteNodeChange;
import jgraf.neo4j.diff.SizeChange;
import jgraf.neo4j.diff.TranslationChange;
import jgraf.neo4j.diff.*;
import jgraf.neo4j.factory.AuxEdgeTypes;
import jgraf.neo4j.factory.AuxNodeLabels;
import jgraf.neo4j.factory.EdgeTypes;
Expand Down Expand Up @@ -51,6 +48,8 @@ public enum _ChangePropNames {
x,
y,
z,
lod_left,
lod_right,
tags
}

Expand Down Expand Up @@ -1111,6 +1110,15 @@ public static void markGeoChange(Transaction tx, Node leftNode, Node rightNode,
});
}

public static void markLodChange(Transaction tx, Node leftNode, Node rightNode, int leftLod, int rightLod) {
Node node = tx.createNode(Label.label(Change.class.getName()), Label.label(LoDChange.class.getName()));
node.createRelationshipTo(leftNode, AuxEdgeTypes.TANDEM);
node.createRelationshipTo(rightNode, AuxEdgeTypes.RIGHT_NODE);
node.setProperty(_ChangePropNames.change_type.toString(), LoDChange.class.getSimpleName());
node.setProperty(_ChangePropNames.lod_left.toString(), leftLod);
node.setProperty(_ChangePropNames.lod_right.toString(), rightLod);
}

private static boolean geoChangeExists(Node leftNode, Node rightNode, Class<?> changeClass) {
// There should exist only one pattern node between leftNode and rightNode with the change class
boolean leftAvailable = leftNode.getRelationships(Direction.INCOMING, AuxEdgeTypes.TANDEM).stream()
Expand Down
1 change: 1 addition & 0 deletions src/main/java/jgraf/neo4j/Neo4jDB.java
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ public void summarize() {
DeleteNodeChange.class,
TranslationChange.class,
SizeChange.class,
LoDChange.class,
TopSplitChange.class
).forEach(clazz -> fillCount(Label.label(clazz.getName()), matchedNodeCount, matchedLabelCount));
dbStats.setMatchedLabelCount(matchedLabelCount);
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/jgraf/neo4j/diff/LoDChange.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package jgraf.neo4j.diff;

public class LoDChange extends Change {
}

0 comments on commit e59b819

Please sign in to comment.