private double getAreaEnlargement(Node indexNode, Node geomRootNode) { Envelope before = getIndexNodeEnvelope(indexNode); Envelope after = getLeafNodeEnvelope(geomRootNode); after.expandToInclude(before); return getArea(after) - getArea(before); }
public double measure(Geometry g1, Geometry g2) { double distance = DiscreteHausdorffDistance.distance(g1, g2, DENSIFY_FRACTION); Envelope env = new Envelope(g1.getEnvelopeInternal()); env.expandToInclude(g2.getEnvelopeInternal()); double envSize = diagonalSize(env); // normalize so that more similarity produces a measure closer to 1 double measure = 1 - distance / envSize; // System.out.println("Hausdorff distance = " + distance + ", measure = " + measure); return measure; }
/** * Enlarges this <code>Envelope</code> so that it contains the <code>other</code> Envelope. Has no * effect if <code>other</code> is wholly on or within the envelope. * * @param other the <code>Envelope</code> to expand to include */ @Override public void expandToInclude(final Envelope other) { if (other.isNull()) { return; } double otherMinZ = getMinZOf(other); double otherMaxZ = getMaxZOf(other); if (isNull()) { super.expandToInclude(other); minz = otherMinZ; maxz = otherMaxZ; } else { super.expandToInclude(other); if (otherMinZ < minz) { minz = otherMinZ; } if (otherMaxZ > maxz) { maxz = otherMaxZ; } } }
/** * Fix an IndexNode bounding box after a child has been removed * * @param indexNode * @return true if something has changed */ private boolean adjustParentBoundingBox(Node indexNode, RelationshipType relationshipType) { double[] old = null; if (indexNode.hasProperty(INDEX_PROP_BBOX)) { old = (double[]) indexNode.getProperty(INDEX_PROP_BBOX); } Envelope bbox = null; Iterator<Relationship> iterator = indexNode.getRelationships(relationshipType, Direction.OUTGOING).iterator(); while (iterator.hasNext()) { Node childNode = iterator.next().getEndNode(); if (bbox == null) { bbox = new Envelope(getChildNodeEnvelope(childNode, relationshipType)); } else { bbox.expandToInclude(getChildNodeEnvelope(childNode, relationshipType)); } } if (bbox == null) { // this could happen in an empty tree bbox = new Envelope(0, 0, 0, 0); } if (old.length != 4 || bbox.getMinX() != old[0] || bbox.getMinY() != old[1] || bbox.getMaxX() != old[2] || bbox.getMaxY() != old[3]) { indexNode.setProperty( INDEX_PROP_BBOX, new double[] {bbox.getMinX(), bbox.getMinY(), bbox.getMaxX(), bbox.getMaxY()}); return true; } else { return false; } }
/** Create a bounding box encompassing the two bounding boxes passed in. */ private static Envelope createEnvelope(Envelope e, Envelope e1) { Envelope result = new Envelope(e); result.expandToInclude(e1); return result; }
private Node quadraticSplit(Node indexNode, RelationshipType relationshipType) { List<Node> entries = new ArrayList<Node>(); Iterable<Relationship> relationships = indexNode.getRelationships(relationshipType, Direction.OUTGOING); for (Relationship relationship : relationships) { entries.add(relationship.getEndNode()); relationship.delete(); } // pick two seed entries such that the dead space is maximal Node seed1 = null; Node seed2 = null; double worst = Double.NEGATIVE_INFINITY; for (int i = 0; i < entries.size(); ++i) { Node e = entries.get(i); Envelope eEnvelope = getChildNodeEnvelope(e, relationshipType); for (int j = i + 1; j < entries.size(); ++j) { Node e1 = entries.get(j); Envelope e1Envelope = getChildNodeEnvelope(e1, relationshipType); double deadSpace = getArea(createEnvelope(eEnvelope, e1Envelope)) - getArea(eEnvelope) - getArea(e1Envelope); if (deadSpace > worst) { worst = deadSpace; seed1 = e; seed2 = e1; } } } List<Node> group1 = new ArrayList<Node>(); group1.add(seed1); Envelope group1envelope = getChildNodeEnvelope(seed1, relationshipType); List<Node> group2 = new ArrayList<Node>(); group2.add(seed2); Envelope group2envelope = getChildNodeEnvelope(seed2, relationshipType); entries.remove(seed1); entries.remove(seed2); while (entries.size() > 0) { // compute the cost of inserting each entry List<Node> bestGroup = null; Envelope bestGroupEnvelope = null; Node bestEntry = null; double expansionMin = Double.POSITIVE_INFINITY; for (Node e : entries) { Envelope nodeEnvelope = getChildNodeEnvelope(e, relationshipType); double expansion1 = getArea(createEnvelope(nodeEnvelope, group1envelope)) - getArea(group1envelope); double expansion2 = getArea(createEnvelope(nodeEnvelope, group2envelope)) - getArea(group2envelope); if (expansion1 < expansion2 && expansion1 < expansionMin) { bestGroup = group1; bestGroupEnvelope = group1envelope; bestEntry = e; expansionMin = expansion1; } else if (expansion2 < expansion1 && expansion2 < expansionMin) { bestGroup = group2; bestGroupEnvelope = group2envelope; bestEntry = e; expansionMin = expansion2; } else if (expansion1 == expansion2 && expansion1 < expansionMin) { // in case of equality choose the group with the smallest area if (getArea(group1envelope) < getArea(group2envelope)) { bestGroup = group1; bestGroupEnvelope = group1envelope; } else { bestGroup = group2; bestGroupEnvelope = group2envelope; } bestEntry = e; expansionMin = expansion1; } } // insert the best candidate entry in the best group bestGroup.add(bestEntry); bestGroupEnvelope.expandToInclude(getChildNodeEnvelope(bestEntry, relationshipType)); entries.remove(bestEntry); } // reset bounding box and add new children indexNode.removeProperty(INDEX_PROP_BBOX); for (Node node : group1) { addChild(indexNode, relationshipType, node); } // create new node from split Node newIndexNode = database.createNode(); for (Node node : group2) { addChild(newIndexNode, relationshipType, node); } return newIndexNode; }
public Envelope expandEnvelope(Envelope env) { for (int i = 0; i < coordinates.length; i++) { env.expandToInclude(coordinates[i]); } return env; }