📄 continuous2d.java
字号:
{ double height = this.height; if (Math.abs(y1-y2) <= height / 2) return y1 - y2; // no wraparounds -- quick and dirty check double dy = _sty(y1,height) - _sty(y2,height); if (dy * 2 > height) return dy - height; if (dy * 2 < -height) return dy + height; return dy; } /** Minimum Toroidal Distance Squared between two points. This computes the "shortest" (squared) distance between two points, considering wrap-around possibilities as well. */ public double tds(final Double2D d1, final Double2D d2) { double dx = tdx(d1.x,d2.x); double dy = tdy(d1.y,d2.y); return (dx * dx + dy * dy); } /** Minimum Toroidal difference vector between two points. This subtracts the second point from the first and produces the minimum-length such subtractive vector, considering wrap-around possibilities as well*/ public Double2D tv(final Double2D d1, final Double2D d2) { return new Double2D(tdx(d1.x,d2.x),tdy(d1.y,d2.y)); } /** Returns a bag containing AT LEAST those objects within the bounding box surrounding the specified distance of the specified position. The bag could include other objects than this. In this case we include the object if any part of the bounding box could overlap into the desired region. To do this, if nonPointObjects is true, we extend the search space by one extra discretization in all directions. For small distances within a single bucket, this returns nine bucket's worth rather than 1, so if you know you only care about the actual x/y points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. [assumes non-toroidal, point objects] */ public Bag getObjectsWithinDistance( final Double2D position, final double distance) { return getObjectsWithinDistance(position,distance,false,false, null); } /** Returns a bag containing AT LEAST those objects within the bounding box surrounding the specified distance of the specified position. The bag could include other objects than this. If toroidal, then wrap-around possibilities are also considered. In this case we include the object if any part of the bounding box could overlap into the desired region. To do this, if nonPointObjects is true, we extend the search space by one extra discretization in all directions. For small distances within a single bucket, this returns nine bucket's worth rather than 1, so if you know you only care about the actual x/y points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. [assumes point objects] */ public Bag getObjectsWithinDistance( final Double2D position, final double distance, final boolean toroidal) { return getObjectsWithinDistance(position,distance,toroidal,false, null); } /** Returns a bag containing AT LEAST those objects within the bounding box surrounding the specified distance of the specified position. The bag could include other objects than this. If toroidal, then wrap-around possibilities are also considered. If nonPointObjects, then it is presumed that the object isn't just a point in space, but in fact fills an area in space where the x/y point location could be at the extreme corner of a bounding box of the object. In this case we include the object if any part of the bounding box could overlap into the desired region. To do this, if nonPointObjects is true, we extend the search space by one extra discretization in all directions. For small distances within a single bucket, this returns nine bucket's worth rather than 1, so if you know you only care about the actual x/y points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. */ public Bag getObjectsWithinDistance( final Double2D position, final double distance, final boolean toroidal, final boolean nonPointObjects) { return getObjectsWithinDistance(position, distance, toroidal, nonPointObjects, null); } /** Puts into the result Bag (and returns it) AT LEAST those objects within the bounding box surrounding the specified distance of the specified position. If the result Bag is null, then a Bag is created. <p>The bag could include other objects than this. If toroidal, then wrap-around possibilities are also considered. If nonPointObjects, then it is presumed that the object isn't just a point in space, but in fact fills an area in space where the x/y point location could be at the extreme corner of a bounding box of the object. In this case we include the object if any part of the bounding box could overlap into the desired region. To do this, if nonPointObjects is true, we extend the search space by one extra discretization in all directions. For small distances within a single bucket, this returns nine bucket's worth rather than 1, so if you know you only care about the actual x/y points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. */ public Bag getObjectsWithinDistance( final Double2D position, final double distance, final boolean toroidal, final boolean nonPointObjects, Bag result) { double discDistance = distance / discretization; double discX = position.x / discretization; double discY = position.y / discretization; if (nonPointObjects) { // We assume that the discretization is larger than the bounding // box width or height for the object in question. In this case, then // we can just increase the range by 1 in each direction and we are // guaranteed to have the location of the object in our collection. discDistance++; } // we're using StrictMath.floor instead of Math.floor because // Math.floor just calls StrictMath.floor, and so using the // StrictMath version may help in the inlining (one function // to inline, not two). They should be identical in function anyway. int minX = (int) StrictMath.floor(discX - discDistance); int maxX = (int) StrictMath.floor(discX + discDistance); int minY = (int) StrictMath.floor(discY - discDistance); int maxY = (int) StrictMath.floor(discY + discDistance); final int expectedBagSize = 1; // in the future, pick a smarter bag size? if (result!=null) { result.clear(); // result.resize(expectedBagSize); // presently 1, why bother? } else result = new Bag(expectedBagSize); Bag temp; MutableInt2D speedyMutableInt2D = this.speedyMutableInt2D; // a little faster (local) // do the loop if( toroidal ) { final int iWidth = (int)(StrictMath.ceil(width / discretization)); final int iHeight = (int)(StrictMath.ceil(height / discretization)); // we promote to longs so that maxX - minX can't totally wrap around by accident if ((long)maxX - (long)minX >= (long)iWidth) // total wrap-around. { minX = 0; maxX = iWidth-1; } if ((long)maxY - (long)minY >= (long)iHeight) // similar { minY = 0; maxY = iHeight-1; } // okay, now tx 'em. // we promote to longs so that the value + iWidth etc. can't totally wrap around by accident final int tmaxX = toroidal(maxX,iWidth); final int tmaxY = toroidal(maxY,iHeight); final int tminX = toroidal(minX,iWidth); final int tminY = toroidal(minY,iHeight); int x = tminX ; do { int y = tminY; do { // grab location speedyMutableInt2D.x=x; speedyMutableInt2D.y=y; temp = super.getObjectsAtLocation(speedyMutableInt2D); if( temp != null && !temp.isEmpty()) { // a little efficiency: add if we're 1, addAll if we're > 1, // do nothing if we're <= 0 (we're empty) final int n = temp.numObjs; if (n==1) result.add(temp.objs[0]); else result.addAll(temp); } // update y if( y == tmaxY ) break; if( y == iHeight-1 ) y = 0; else y++; } while(true); // update x if( x == tmaxX ) break; if( x == iWidth-1 ) x = 0; else x++; } while(true); } else { // for non-toroidal, it is easier to do the inclusive for-loops for(int x = minX; x<= maxX; x++) for(int y = minY ; y <= maxY; y++) { // grab location speedyMutableInt2D.x=x; speedyMutableInt2D.y=y; temp = super.getObjectsAtLocation(speedyMutableInt2D); if( temp != null && !temp.isEmpty()) { // a little efficiency: add if we're 1, addAll if we're > 1, // do nothing if we're <= 0 (we're empty) final int n = temp.numObjs; if (n==1) result.add(temp.objs[0]); else result.addAll(temp); } } } return result; } // used internally in getObjectsWithinDistance. Note similarity to // AbstractGrid2D's tx method final int toroidal(final int x, final int width) { if (x >= 0) return (x % width); final int width2 = (x % width) + width; if (width2 < width) return width2; return 0; } MutableInt2D speedyMutableInt2D = new MutableInt2D(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -