📄 continuous3d.java
字号:
{ if (z >= 0) { if (z < length) return z ; return z - length; } return z + length; } /** Minimum toroidal distance between two values in the Z dimension. */ public double tdz(final double z1, final double z2) { double length = this.length; if (Math.abs(z1-z2) <= length / 2) return z1 - z2; // no wraparounds -- quick and dirty check double dz = _stz(z1,length) - _stz(z2,length); if (dz * 2 > length) return dz - length; if (dz * 2 < -length) return dz + length; return dz; } /** 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 Double3D d1, final Double3D d2) { double dx = tdx(d1.x,d2.x); double dy = tdy(d1.y,d2.y); double dz = tdz(d1.z,d2.z); return (dx * dx + dy * dy + dz * dz); } /** 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 Double3D tv(final Double3D d1, final Double3D d2) { return new Double3D(tdx(d1.x,d2.x),tdy(d1.y,d2.y),tdz(d1.z,d2.z)); } /** 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 27 bucket's worth rather than 1 (!!!), so if you know you only care about the actual x/y/z points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. That's a lot of extra hash table lookups. [assumes non-toroidal, point objects] */ public Bag getObjectsWithinDistance( final Double3D position, final double distance) { return getObjectsWithinDistance(position,distance,false,false, new Bag()); } /** 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 27 bucket's worth rather than 1 (!!!), so if you know you only care about the actual x/y/z points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. That's a lot of extra hash table lookups. [assumes point objects] */ public Bag getObjectsWithinDistance( final Double3D position, final double distance, final boolean toroidal) { return getObjectsWithinDistance(position,distance,toroidal,false, new Bag()); } /** 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 27 bucket's worth rather than 1 (!!!), so if you know you only care about the actual x/y/z points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. That's a lot of extra hash table lookups. */ public Bag getObjectsWithinDistance( final Double3D position, final double distance, final boolean toroidal, final boolean nonPointObjects) { return getObjectsWithinDistance(position, distance, toroidal, nonPointObjects, new Bag()); } /** Puts into the result Bag (and returns it) 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 27 bucket's worth rather than 1 (!!!), so if you know you only care about the actual x/y/z points stored, rather than possible object overlap into the distance sphere you specified, you'd want to set nonPointObjects to FALSE. That's a lot of extra hash table lookups. */ public Bag getObjectsWithinDistance( final Double3D 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; double discZ = position.z / 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); int minZ = (int) StrictMath.floor(discZ - discDistance); int maxZ = (int) StrictMath.floor(discZ + 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; MutableInt3D speedyMutableInt3D = this.speedyMutableInt3D; // 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)); final int iLength = (int)(StrictMath.ceil(length / 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; } if ((long)maxZ - (long)minZ >= (long)iLength) // similar { minZ = 0; maxZ = iLength-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 tmaxZ = toroidal(maxZ,iLength); final int tminX = toroidal(minX,iWidth); final int tminY = toroidal(minY,iHeight); final int tminZ = toroidal(minZ,iLength); int x = tminX ; do { int y = tminY; do { int z = tminZ; do { // grab location speedyMutableInt3D.x=x; speedyMutableInt3D.y=y; speedyMutableInt3D.z=z; temp = super.getObjectsAtLocation(speedyMutableInt3D); 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) int n = temp.numObjs; if (n==1) result.add(temp.objs[0]); else result.addAll(temp); } // update z if( z == tmaxZ ) break; if( z == iLength-1 ) z = 0; else z++; } while(true); // 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++) for (int z = minZ ; z <= maxZ; z++) { // grab location speedyMutableInt3D.x=x; speedyMutableInt3D.y=y; speedyMutableInt3D.z=z; temp = super.getObjectsAtLocation(speedyMutableInt3D); 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 // AbstractGrid3D'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; } MutableInt3D speedyMutableInt3D = new MutableInt3D(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -