public SpatialRelation relate(SpanUnitsNRShape spanShape) { assertDecoded(); int startCmp = comparePrefix(spanShape.getMinUnit(), this); if (startCmp > 0) { // start comes after this cell return SpatialRelation.DISJOINT; } int endCmp = comparePrefix(spanShape.getMaxUnit(), this); if (endCmp < 0) { // end comes before this cell return SpatialRelation.DISJOINT; } int nrMinLevel = spanShape.getMinUnit().getLevel(); int nrMaxLevel = spanShape.getMaxUnit().getLevel(); if ((startCmp < 0 || startCmp == 0 && nrMinLevel <= getLevel()) && (endCmp > 0 || endCmp == 0 && nrMaxLevel <= getLevel())) return SpatialRelation.WITHIN; // or equals // At this point it's Contains or Within. if (startCmp != 0 || endCmp != 0) return SpatialRelation.INTERSECTS; // if min or max Level is less, it might be on the equivalent edge. for (; nrMinLevel < getLevel(); nrMinLevel++) { if (getValAtLevel(nrMinLevel + 1) != 0) return SpatialRelation.INTERSECTS; } for (; nrMaxLevel < getLevel(); nrMaxLevel++) { if (getValAtLevel(nrMaxLevel + 1) != getNumSubCells(getShapeAtLevel(nrMaxLevel)) - 1) return SpatialRelation.INTERSECTS; } return SpatialRelation.CONTAINS; }
public SpatialRelation relate(SpanUnitsNRShape ext) { // This logic somewhat mirrors RectangleImpl.relate_range() int extMin_intMax = comparePrefix(ext.getMinUnit(), getMaxUnit()); if (extMin_intMax > 0) return SpatialRelation.DISJOINT; int extMax_intMin = comparePrefix(ext.getMaxUnit(), getMinUnit()); if (extMax_intMin < 0) return SpatialRelation.DISJOINT; int extMin_intMin = comparePrefix(ext.getMinUnit(), getMinUnit()); int extMax_intMax = comparePrefix(ext.getMaxUnit(), getMaxUnit()); if ((extMin_intMin > 0 || extMin_intMin == 0 && ext.getMinUnit().getLevel() >= getMinUnit().getLevel()) && (extMax_intMax < 0 || extMax_intMax == 0 && ext.getMaxUnit().getLevel() >= getMaxUnit().getLevel())) return SpatialRelation.CONTAINS; if ((extMin_intMin < 0 || extMin_intMin == 0 && ext.getMinUnit().getLevel() <= getMinUnit().getLevel()) && (extMax_intMax > 0 || extMax_intMax == 0 && ext.getMaxUnit().getLevel() <= getMaxUnit().getLevel())) return SpatialRelation.WITHIN; return SpatialRelation.INTERSECTS; }
private void initIter(Shape filter) { cellNumber = -1; if (filter instanceof UnitNRShape && ((UnitNRShape) filter).getLevel() == 0) filter = null; // world means everything -- no filter iterFilter = filter; NRCell parent = getShapeAtLevel(getLevel() - 1); // Initialize iter* members. // no filter means all subcells if (filter == null) { iterFirstCellNumber = 0; iterFirstIsIntersects = false; iterLastCellNumber = getNumSubCells(parent) - 1; iterLastIsIntersects = false; return; } final UnitNRShape minLV; final UnitNRShape maxLV; final int lastLevelInCommon; // between minLV & maxLV if (filter instanceof SpanUnitsNRShape) { SpanUnitsNRShape spanShape = (SpanUnitsNRShape) iterFilter; minLV = spanShape.getMinUnit(); maxLV = spanShape.getMaxUnit(); lastLevelInCommon = spanShape.getLevelsInCommon(); } else { minLV = (UnitNRShape) iterFilter; maxLV = minLV; lastLevelInCommon = minLV.getLevel(); } // fast path optimization that is usually true, but never first level if (iterFilter == parent.iterFilter && (getLevel() <= lastLevelInCommon || parent.iterFirstCellNumber != parent.iterLastCellNumber)) { // TODO benchmark if this optimization pays off. We avoid two comparePrefixLV calls. if (parent.iterFirstIsIntersects && parent.cellNumber == parent.iterFirstCellNumber && minLV.getLevel() >= getLevel()) { iterFirstCellNumber = minLV.getValAtLevel(getLevel()); iterFirstIsIntersects = (minLV.getLevel() > getLevel()); } else { iterFirstCellNumber = 0; iterFirstIsIntersects = false; } if (parent.iterLastIsIntersects && parent.cellNumber == parent.iterLastCellNumber && maxLV.getLevel() >= getLevel()) { iterLastCellNumber = maxLV.getValAtLevel(getLevel()); iterLastIsIntersects = (maxLV.getLevel() > getLevel()); } else { iterLastCellNumber = getNumSubCells(parent) - 1; iterLastIsIntersects = false; } if (iterFirstCellNumber == iterLastCellNumber) { if (iterLastIsIntersects) iterFirstIsIntersects = true; else if (iterFirstIsIntersects) iterLastIsIntersects = true; } return; } // not common to get here, except for level 1 which always happens int startCmp = comparePrefix(minLV, parent); if (startCmp > 0) { // start comes after this cell iterFirstCellNumber = 0; iterFirstIsIntersects = false; iterLastCellNumber = -1; // so ends early (no cells) iterLastIsIntersects = false; return; } int endCmp = comparePrefix(maxLV, parent); // compare to end cell if (endCmp < 0) { // end comes before this cell iterFirstCellNumber = 0; iterFirstIsIntersects = false; iterLastCellNumber = -1; // so ends early (no cells) iterLastIsIntersects = false; return; } if (startCmp < 0 || minLV.getLevel() < getLevel()) { // start comes before... iterFirstCellNumber = 0; iterFirstIsIntersects = false; } else { iterFirstCellNumber = minLV.getValAtLevel(getLevel()); iterFirstIsIntersects = (minLV.getLevel() > getLevel()); } if (endCmp > 0 || maxLV.getLevel() < getLevel()) { // end comes after... iterLastCellNumber = getNumSubCells(parent) - 1; iterLastIsIntersects = false; } else { iterLastCellNumber = maxLV.getValAtLevel(getLevel()); iterLastIsIntersects = (maxLV.getLevel() > getLevel()); } if (iterFirstCellNumber == iterLastCellNumber) { if (iterLastIsIntersects) iterFirstIsIntersects = true; else if (iterFirstIsIntersects) iterLastIsIntersects = true; } }