private Point3d computeWinCoord( Canvas3D canvas, RenderAtom ra, Point2d winCoord, Point3d objCoord, Transform3D localToImagePlate) { // Get local to Vworld transform RenderMolecule rm = ra.renderMolecule; if (rm == null) { // removeRenderAtom() may set ra.renderMolecule to null // in RenderBin before this renderer thread run. return null; } // MT safe issue: We can't reference ra.renderMolecule below since // RenderBin thread may set it to null anytime. Use rm instead. Transform3D lvw = rm.localToVworld[rm.localToVworldIndex[NodeRetained.LAST_LOCAL_TO_VWORLD]]; Point3d clipCoord3 = new Point3d(); clipCoord3.set(objCoord); Point4d clipCoord4 = new Point4d(); // Transform point from local coord. to clipping coord. lvw.transform(clipCoord3); canvas.vworldToEc.transform(clipCoord3); canvas.projTrans.transform(clipCoord3, clipCoord4); // clip check in Z if ((clipCoord4.w <= 0.0) || (clipCoord4.z > clipCoord4.w) || (-clipCoord4.z > clipCoord4.w)) { return null; } double invW = 1.0 / clipCoord4.w; clipCoord3.x = clipCoord4.x * invW; clipCoord3.y = clipCoord4.y * invW; clipCoord3.z = clipCoord4.z * invW; // Get Vworld to image plate Xform canvas.getLastVworldToImagePlate(localToImagePlate); // v' = vwip x lvw x v // where v' = transformed vertex, // lvw = local to Vworld Xform // vwip = Vworld to Image plate Xform // v = vertex // Compute composite local to image plate Xform localToImagePlate.mul(lvw); // Transform the Raster's position from object to world coordinates localToImagePlate.transform(objCoord); // Get the window coordinates of this point canvas.getPixelLocationFromImagePlate(objCoord, winCoord); return clipCoord3; }
// TODO -- Need to rethink. Might have to consider charTransform[] in returns pickInfo. @Override boolean intersect( PickShape pickShape, PickInfo pickInfo, int flags, Point3d iPnt, GeometryRetained geom, int geomIndex) { Transform3D tempT3D = new Transform3D(); GeometryArrayRetained geo = null; int sIndex = -1; PickShape newPS; double minDist = Double.MAX_VALUE; double distance = 0.0; Point3d closestIPnt = new Point3d(); for (int i = 0; i < numChars; i++) { geo = geometryList[i]; if (geo != null) { tempT3D.invert(charTransforms[i]); newPS = pickShape.transform(tempT3D); if (geo.intersect(newPS, pickInfo, flags, iPnt, geom, geomIndex)) { if (flags == 0) { return true; } distance = newPS.distance(iPnt); if (distance < minDist) { sIndex = i; minDist = distance; closestIPnt.set(iPnt); } } } } if (sIndex >= 0) { // We need to transform iPnt to the vworld to compute the actual distance. // In this method we'll transform iPnt by its char. offset. Shape3D will // do the localToVworld transform. iPnt.set(closestIPnt); charTransforms[sIndex].transform(iPnt); return true; } return false; }
@Override void computeBoundingBox() { if (clipMode == Raster.CLIP_IMAGE) { // Disable view frustum culling by setting the raster's bounds to // infinity. Point3d minBounds = new Point3d(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); Point3d maxBounds = new Point3d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); geoBounds.setUpper(maxBounds); geoBounds.setLower(minBounds); } else { Point3d center = new Point3d(); center.x = position.x; center.y = position.y; center.z = position.z; geoBounds.setUpper(center); geoBounds.setLower(center); } }
public static void main(final String[] args) { final int N_BLOBS = 20; final double RADIUS = 5; // µm final Random RAN = new Random(); final double WIDTH = 100; // µm final double HEIGHT = 100; // µm final double DEPTH = 50; // µm final double[] CALIBRATION = new double[] {0.5f, 0.5f, 1}; final AxisType[] AXES = new AxisType[] {Axes.X, Axes.Y, Axes.Z}; // Create 3D image final Img<UnsignedByteType> source = new ArrayImgFactory<UnsignedByteType>() .create( new int[] { (int) (WIDTH / CALIBRATION[0]), (int) (HEIGHT / CALIBRATION[1]), (int) (DEPTH / CALIBRATION[2]) }, new UnsignedByteType()); final ImgPlus<UnsignedByteType> img = new ImgPlus<UnsignedByteType>(source, "Test", AXES, CALIBRATION); // Random blobs final double[] radiuses = new double[N_BLOBS]; final ArrayList<double[]> centers = new ArrayList<double[]>(N_BLOBS); final int[] intensities = new int[N_BLOBS]; double x, y, z; for (int i = 0; i < N_BLOBS; i++) { radiuses[i] = RADIUS + RAN.nextGaussian(); x = WIDTH * RAN.nextFloat(); y = HEIGHT * RAN.nextFloat(); z = DEPTH * RAN.nextFloat(); centers.add(i, new double[] {x, y, z}); intensities[i] = RAN.nextInt(100) + 100; } // Put the blobs in the image for (int i = 0; i < N_BLOBS; i++) { final Spot tmpSpot = new Spot(centers.get(i)[0], centers.get(i)[1], centers.get(i)[2], radiuses[i], -1d); tmpSpot.putFeature(Spot.RADIUS, radiuses[i]); final SpotNeighborhood<UnsignedByteType> sphere = new SpotNeighborhood<UnsignedByteType>(tmpSpot, img); for (final UnsignedByteType pixel : sphere) { pixel.set(intensities[i]); } } // Instantiate detector final LogDetector<UnsignedByteType> detector = new LogDetector<UnsignedByteType>( img, img, TMUtils.getSpatialCalibration(img), RADIUS, 0, true, false); // Segment final long start = System.currentTimeMillis(); if (!detector.checkInput() || !detector.process()) { System.out.println(detector.getErrorMessage()); return; } final Collection<Spot> spots = detector.getResult(); final long end = System.currentTimeMillis(); // Display image ImageJFunctions.show(img); // Display results final int spot_found = spots.size(); System.out.println("Segmentation took " + (end - start) + " ms."); System.out.println("Found " + spot_found + " blobs.\n"); Point3d p1, p2; double dist, min_dist; int best_index = 0; double[] best_match; final ArrayList<Spot> spot_list = new ArrayList<Spot>(spots); Spot best_spot = null; final double[] coords = new double[3]; final String[] posFeats = Spot.POSITION_FEATURES; while (!spot_list.isEmpty() && !centers.isEmpty()) { min_dist = Float.POSITIVE_INFINITY; for (final Spot s : spot_list) { int index = 0; for (final String pf : posFeats) { coords[index++] = s.getFeature(pf).doubleValue(); } p1 = new Point3d(coords); for (int j = 0; j < centers.size(); j++) { p2 = new Point3d(centers.get(j)); dist = p1.distance(p2); if (dist < min_dist) { min_dist = dist; best_index = j; best_spot = s; } } } spot_list.remove(best_spot); best_match = centers.remove(best_index); int index = 0; for (final String pf : posFeats) { coords[index++] = best_spot.getFeature(pf).doubleValue(); } System.out.println("Blob coordinates: " + Util.printCoordinates(coords)); System.out.println( String.format( " Best matching center at distance %.1f with coords: " + Util.printCoordinates(best_match), min_dist)); } System.out.println(); System.out.println("Unmatched centers:"); for (int i = 0; i < centers.size(); i++) System.out.println("Center " + i + " at position: " + Util.printCoordinates(centers.get(i))); }
@Override void execute( Canvas3D cv, RenderAtom ra, boolean isNonUniformScale, boolean updateAlpha, float alpha, int screen, boolean ignoreVertexColors) { // Compute the offset position of the raster // This has to be done at render time because we need access // to the Canvas3D info // Check if adjusted position needs to be computed Point3d adjPos = new Point3d(); // Position of the Raster after adjusting for dstOffset adjPos.set(position); Point2d winCoord = new Point2d(); // Position of Raster in window coordinates Transform3D localToImagePlate = new Transform3D(); // Local to Image plate transform Point3d clipCoord = computeWinCoord(cv, ra, winCoord, adjPos, localToImagePlate); // Test raster for out of bounds in Z. if (clipCoord == null) { return; } if (clipMode == Raster.CLIP_POSITION) { // Do trivial reject test on Raster position. if (!isRasterClipPositionInside(clipCoord)) { return; } } // Add the destination offset to the Raster position in window coordinates winCoord.x += xDstOffset; winCoord.y += yDstOffset; // System.err.println("Step 2 : adjPos " + adjPos + " winCoord " + winCoord); if ((type == Raster.RASTER_COLOR) || (type == Raster.RASTER_COLOR_DEPTH)) { float devCoordZ = (float) (clipCoord.z * 0.5 - 0.5); // Do textfill stuffs if (texture != null) { // setup Texture pipe. cv.updateTextureForRaster(texture); cv.textureFill(this, winCoord, devCoordZ, alpha); // Restore texture pipe. cv.restoreTextureBin(); } } if ((type == Raster.RASTER_DEPTH) || (type == Raster.RASTER_COLOR_DEPTH)) { Point2i srcOffset = new Point2i(xSrcOffset, ySrcOffset); if (clipMode == Raster.CLIP_IMAGE) { clipImage(cv, ra, winCoord, srcOffset); } computeObjCoord(cv, winCoord, adjPos, localToImagePlate); cv.executeRasterDepth( cv.ctx, (float) adjPos.x, (float) adjPos.y, (float) adjPos.z, srcOffset.x, srcOffset.y, width, height, depthComponent.width, depthComponent.height, depthComponent.type, ((DepthComponentIntRetained) depthComponent).depthData); } }
@Override boolean intersect( PickShape pickShape, PickInfo pickInfo, int flags, Point3d iPnt, GeometryRetained geom, int geomIndex) { Point3d pnts[] = new Point3d[2]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int scount, j, i = 0; int count = 0; int[] vtxIndexArr = new int[2]; pnts[0] = new Point3d(); pnts[1] = new Point3d(); switch (pickShape.getPickType()) { case PickShape.PICKRAY: PickRay pickRay = (PickRay) pickShape; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectLineAndRay( pnts[0], pnts[1], pickRay.origin, pickRay.direction, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKSEGMENT: PickSegment pickSegment = (PickSegment) pickShape; Vector3d dir = new Vector3d( pickSegment.end.x - pickSegment.start.x, pickSegment.end.y - pickSegment.start.y, pickSegment.end.z - pickSegment.start.z); while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectLineAndRay(pnts[0], pnts[1], pickSegment.start, dir, sdist, iPnt) && (sdist[0] <= 1.0)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKBOUNDINGBOX: BoundingBox bbox = (BoundingBox) ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKBOUNDINGSPHERE: BoundingSphere bsphere = (BoundingSphere) ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKBOUNDINGPOLYTOPE: BoundingPolytope bpolytope = (BoundingPolytope) ((PickBounds) pickShape).bounds; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKCYLINDER: PickCylinder pickCylinder = (PickCylinder) pickShape; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKCONE: PickCone pickCone = (PickCone) pickShape; while (i < stripIndexCounts.length) { vtxIndexArr[0] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[0]); scount = stripIndexCounts[i++]; for (j = 1; j < scount; j++) { vtxIndexArr[1] = indexCoord[count]; getVertexData(indexCoord[count++], pnts[1]); if (intersectCone(pnts, pickCone, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } pnts[0].set(pnts[1]); vtxIndexArr[0] = vtxIndexArr[1]; } } break; case PickShape.PICKPOINT: // Should not happen since API already check for this throw new IllegalArgumentException(J3dI18N.getString("IndexedLineStripArrayRetained0")); default: throw new RuntimeException("PickShape not supported for intersection"); } if (minDist < Double.MAX_VALUE) { iPnt.x = x; iPnt.y = y; iPnt.z = z; return true; } return false; }
@Override synchronized void computeBoundingBox() { Point3d l = new Point3d(); Point3d u = new Point3d(); Vector3f location = new Vector3f(this.position); int i, k = 0, numTotal = 0; double width = 0, height = 0; Rectangle2D bounds; // Reset bounds data l.set(location); u.set(location); if (numChars != 0) { // Set loop counters based on path type if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) { k = 0; numTotal = numChars + 1; } else if (path == Text3D.PATH_LEFT || path == Text3D.PATH_DOWN) { k = 1; numTotal = numChars; // Reset bounds to bounding box if first character bounds = glyphVecs[0].getVisualBounds(); u.x += bounds.getWidth(); u.y += bounds.getHeight(); } for (i = 1; i < numTotal; i++, k++) { width = glyphVecs[k].getLogicalBounds().getWidth(); bounds = glyphVecs[k].getVisualBounds(); // 'switch' could be outside loop with little hacking, width += charSpacing; height = bounds.getHeight(); switch (this.path) { case Text3D.PATH_RIGHT: u.x += (width); if (u.y < (height + location.y)) { u.y = location.y + height; } break; case Text3D.PATH_LEFT: l.x -= (width); if (u.y < (height + location.y)) { u.y = location.y + height; } break; case Text3D.PATH_UP: u.y += height; if (u.x < (bounds.getWidth() + location.x)) { u.x = location.x + bounds.getWidth(); } break; case Text3D.PATH_DOWN: l.y -= height; if (u.x < (bounds.getWidth() + location.x)) { u.x = location.x + bounds.getWidth(); } break; } } // Handle string alignment. ALIGN_FIRST is handled by default if (alignment != Text3D.ALIGN_FIRST) { double cx = (u.x - l.x); double cy = (u.y - l.y); if (alignment == Text3D.ALIGN_CENTER) { cx *= .5; cy *= .5; } switch (path) { case Text3D.PATH_RIGHT: l.x -= cx; u.x -= cx; break; case Text3D.PATH_LEFT: l.x += cx; u.x += cx; break; case Text3D.PATH_UP: l.y -= cy; u.y -= cy; break; case Text3D.PATH_DOWN: l.y += cy; u.y += cy; break; } } } l.z = 0.0f; if ((font3D == null) || (font3D.fontExtrusion == null)) { u.z = l.z; } else { u.z = l.z + font3D.fontExtrusion.length; } }
/** * Update per character transform based on Text3D location, per character size and path. * * <p>WARNING: Caller of this method must make sure SceneGraph is live, else exceptions may be * thrown. */ final void updateTransformData() { int i, k = 0, numTotal = 0; double width = 0, height = 0; Vector3f location = new Vector3f(this.position); Rectangle2D bounds; // Reset bounds data lower.set(location); upper.set(location); charTransforms = new Transform3D[numChars]; for (i = 0; i < numChars; i++) { charTransforms[i] = new Transform3D(); } if (numChars != 0) { charTransforms[0].set(location); // Set loop counters based on path type if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) { k = 0; numTotal = numChars + 1; } else if (path == Text3D.PATH_LEFT || path == Text3D.PATH_DOWN) { k = 1; numTotal = numChars; // Reset bounds to bounding box if first character bounds = glyphVecs[0].getVisualBounds(); upper.x += bounds.getWidth(); upper.y += bounds.getHeight(); } for (i = 1; i < numTotal; i++, k++) { width = glyphVecs[k].getLogicalBounds().getWidth(); bounds = glyphVecs[k].getVisualBounds(); // 'switch' could be outside loop with little hacking, width += charSpacing; height = bounds.getHeight(); switch (this.path) { case Text3D.PATH_RIGHT: location.x += width; upper.x += (width); if (upper.y < (height + location.y)) { upper.y = location.y + height; } break; case Text3D.PATH_LEFT: location.x -= width; lower.x -= (width); if (upper.y < (height + location.y)) { upper.y = location.y + height; } break; case Text3D.PATH_UP: location.y += height; upper.y += height; if (upper.x < (bounds.getWidth() + location.x)) { upper.x = location.x + bounds.getWidth(); } break; case Text3D.PATH_DOWN: location.y -= height; lower.y -= height; if (upper.x < (bounds.getWidth() + location.x)) { upper.x = location.x + bounds.getWidth(); } break; } if (i < numChars) { charTransforms[i].set(location); } } // Handle string alignment. ALIGN_FIRST is handled by default if (alignment != Text3D.ALIGN_FIRST) { double cx = (upper.x - lower.x); double cy = (upper.y - lower.y); if (alignment == Text3D.ALIGN_CENTER) { cx *= .5; cy *= .5; } switch (path) { case Text3D.PATH_RIGHT: for (i = 0; i < numChars; i++) { charTransforms[i].mat[3] -= cx; } lower.x -= cx; upper.x -= cx; break; case Text3D.PATH_LEFT: for (i = 0; i < numChars; i++) { charTransforms[i].mat[3] += cx; } lower.x += cx; upper.x += cx; break; case Text3D.PATH_UP: for (i = 0; i < numChars; i++) { charTransforms[i].mat[7] -= cy; } lower.y -= cy; upper.y -= cy; break; case Text3D.PATH_DOWN: for (i = 0; i < numChars; i++) { charTransforms[i].mat[7] += cy; } lower.y += cy; upper.y += cy; break; } } } lower.z = 0.0f; if ((font3D == null) || (font3D.fontExtrusion == null)) { upper.z = lower.z; } else { upper.z = lower.z + font3D.fontExtrusion.length; } // update geoBounds getBoundingBox(geoBounds); }
@Override boolean intersect( PickShape pickShape, PickInfo pickInfo, int flags, Point3d iPnt, GeometryRetained geom, int geomIndex) { Point3d pnts[] = new Point3d[3]; double sdist[] = new double[1]; double minDist = Double.MAX_VALUE; double x = 0, y = 0, z = 0; int[] vtxIndexArr = new int[3]; // NVaidya // Bug 447: While loops below now traverse over all // elements in the valid index range from initialIndexIndex // to initialIndexInex + validIndexCount - 1 int i = initialIndexIndex; int loopStopIndex = initialIndexIndex + validIndexCount; pnts[0] = new Point3d(); pnts[1] = new Point3d(); pnts[2] = new Point3d(); switch (pickShape.getPickType()) { case PickShape.PICKRAY: PickRay pickRay = (PickRay) pickShape; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectRay(pnts, pickRay, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKSEGMENT: PickSegment pickSegment = (PickSegment) pickShape; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectSegment(pnts, pickSegment.start, pickSegment.end, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKBOUNDINGBOX: BoundingBox bbox = (BoundingBox) ((PickBounds) pickShape).bounds; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectBoundingBox(pnts, bbox, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKBOUNDINGSPHERE: BoundingSphere bsphere = (BoundingSphere) ((PickBounds) pickShape).bounds; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectBoundingSphere(pnts, bsphere, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKBOUNDINGPOLYTOPE: BoundingPolytope bpolytope = (BoundingPolytope) ((PickBounds) pickShape).bounds; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectBoundingPolytope(pnts, bpolytope, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKCYLINDER: PickCylinder pickCylinder = (PickCylinder) pickShape; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectCylinder(pnts, pickCylinder, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKCONE: PickCone pickCone = (PickCone) pickShape; while (i < loopStopIndex) { for (int j = 0; j < 3; j++) { vtxIndexArr[j] = indexCoord[i]; getVertexData(indexCoord[i++], pnts[j]); } if (intersectCone(pnts, pickCone, sdist, iPnt)) { if (flags == 0) { return true; } if (sdist[0] < minDist) { minDist = sdist[0]; x = iPnt.x; y = iPnt.y; z = iPnt.z; if ((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } if ((flags & PickInfo.ALL_GEOM_INFO) != 0) { storeInterestData(pickInfo, flags, geom, geomIndex, vtxIndexArr, iPnt, sdist[0]); } } } break; case PickShape.PICKPOINT: // Should not happen since API already check for this throw new IllegalArgumentException(J3dI18N.getString("IndexedTriangleArrayRetained0")); default: throw new RuntimeException("PickShape not supported for intersection"); } if (minDist < Double.MAX_VALUE) { iPnt.x = x; iPnt.y = y; iPnt.z = z; return true; } return false; }