You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Mike Zimmerman (JIRA)" <ji...@apache.org> on 2015/04/08 17:45:12 UTC
[jira] [Issue Comment Deleted] (MATH-1211)
PolyhedronsSet.firstIntersection(Vector3D point, Line line) sometimes
reports intersections on wrong end of line
[ https://issues.apache.org/jira/browse/MATH-1211?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Mike Zimmerman updated MATH-1211:
---------------------------------
Comment: was deleted
(was: Sure thing, Luc. Please try this code that procedurally generates a triangulated cube and repeats my tests of the PolyhedronSet interior check and intersection routines. I'm using commons-math-3.4.
Sometimes the rays I'm casting from the origin are found to intersect a face "behind" the ray direction; I think the fi
********************************************
package trimesh;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.math3.geometry.euclidean.threed.Euclidean3D;
import org.apache.commons.math3.geometry.euclidean.threed.Line;
import org.apache.commons.math3.geometry.euclidean.threed.Plane;
import org.apache.commons.math3.geometry.euclidean.threed.PolyhedronsSet;
import org.apache.commons.math3.geometry.euclidean.threed.SubPlane;
import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet;
import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
import org.apache.commons.math3.geometry.partitioning.Region;
import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
public class IntersectionTest {
static PolyhedronsSet polyset;
static double tol=1e-8;
public static void createCubeFromTriangles() {
Vector3D[] verts=new Vector3D[8];
double xmin=-1,xmax=1;
double ymin=-1,ymax=1;
double zmin=-1,zmax=1;
verts[0]=new Vector3D(xmin,ymin,zmin);
verts[1]=new Vector3D(xmax,ymin,zmin);
verts[2]=new Vector3D(xmax,ymax,zmin);
verts[3]=new Vector3D(xmin,ymax,zmin);
verts[4]=new Vector3D(xmin,ymin,zmax);
verts[5]=new Vector3D(xmax,ymin,zmax);
verts[6]=new Vector3D(xmax,ymax,zmax);
verts[7]=new Vector3D(xmin,ymax,zmax);
//
int[][] faces=new int[12][];
faces[0]=new int[]{3,1,0}; // bottom (-z)
faces[1]=new int[]{1,3,2}; // bottom (-z)
faces[2]=new int[]{5,7,4}; // top (+z)
faces[3]=new int[]{7,5,6}; // top (+z)
faces[4]=new int[]{2,5,1}; // right (+x)
faces[5]=new int[]{5,2,6}; // right (+x)
faces[6]=new int[]{4,3,0}; // left (-x)
faces[7]=new int[]{3,4,7}; // left (-x)
faces[8]=new int[]{4,1,5}; // front (-y)
faces[9]=new int[]{1,4,0}; // front (-y)
faces[10]=new int[]{3,6,2}; // back (+y)
faces[11]=new int[]{6,3,7}; // back (+y)
//
Set<SubHyperplane<Euclidean3D>> pset=new HashSet<>();
for (int f=0; f<faces.length; f++) {
int[] vidx=faces[f];
Plane p=new Plane(verts[vidx[0]],verts[vidx[1]],verts[vidx[2]],tol);
checkNormal(p);
Vector2D p0=p.toSubSpace(verts[vidx[0]]);
Vector2D p1=p.toSubSpace(verts[vidx[1]]);
Vector2D p2=p.toSubSpace(verts[vidx[2]]);
PolygonsSet lset=new PolygonsSet(tol,p0,p1,p2);
pset.add(new SubPlane(p,lset));
}
polyset=new PolyhedronsSet(pset,tol);
}
public static void checkNormal(Plane p) {
if (p.getNormal().dotProduct(p.getOrigin())<0)
System.out.println("Normal bad");
else
System.out.println("Normal ok");
}
public static void interiorTest() {
int npts=10;
for (int i=0; i<npts; i++) {
Vector3D pos=new Vector3D(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).scalarMultiply(1.25); // pick random point in cube of size 1.25; it could be inside or outside the cube
if (polyset.checkPoint(pos).equals(Region.Location.OUTSIDE)) // check to see if it is inside or outside
System.out.println("Point "+pos+": OUTSIDE");
else
System.out.println("Point "+pos+": INSIDE");
}
}
public static void intersectionTest() {
int nrays=10;
for (int i=0; i<nrays; i++) {
Vector3D origin=Vector3D.ZERO;
Vector3D direction=new Vector3D(2*Math.random()-1,2*Math.random()-1,2*Math.random()-1).normalize();
Line line=new Line(origin,origin.add(direction),tol);
SubHyperplane<Euclidean3D> plane=polyset.firstIntersection(origin, line);
if (plane==null)
System.out.println("No intersection for ray from "+origin+" along "+direction);
else {
Vector3D intersectionPoint=((Plane)plane.getHyperplane()).intersection(line);
System.out.println("Ray from "+origin+" along "+direction+" intersects cube at "+intersectionPoint);
System.out.println("Direction of intersection point from origin is "+intersectionPoint.normalize()+", which should match the ray direction");
double dotProduct=direction.dotProduct(intersectionPoint.subtract(origin));
System.out.println(" (ray direction) dot (intersectionPoint-origin) = "+dotProduct);
if (dotProduct<0) {
System.out.println(" ***** the dot product should be positive *****");
System.out.println(" ***** i.e. the intersection should lie in *front* of the ray not behind *****");
}
}
System.out.println();
}
}
public static void main(String[] args) {
createCubeFromTriangles();
System.out.println();
interiorTest();
System.out.println();
intersectionTest();
}
}
)
> PolyhedronsSet.firstIntersection(Vector3D point, Line line) sometimes reports intersections on wrong end of line
> ----------------------------------------------------------------------------------------------------------------
>
> Key: MATH-1211
> URL: https://issues.apache.org/jira/browse/MATH-1211
> Project: Commons Math
> Issue Type: Bug
> Reporter: Mike Zimmerman
> Attachments: IntersectionTest.java
>
>
> I constructed a PolyhedronsSet from a list of triangular faces representing an icosphere (using the instructions found at https://mail-archives.apache.org/mod_mbox/commons-user/201208.mbox/<50...@free.fr>). This seems to produce correct INSIDE/OUTSIDE results for randomly chosen points. I think my mesh triangles are defined appropriately.
> However, using PolyhedronsSet.firstIntersection(Vector3D point, Line line) to shoot randomly oriented rays from the origin sometimes gives a wrong mesh intersection point "behind" the origin. The intersection algorithm is sometimes picking up faces of the sphere-shaped mesh on the wrong semi-infinite portion of the line, i.e. meshIntersectionPoint.subtract(point).dotProduct(line.getDirection())<0 where point is the Vector3D at center of the sphere and line extends outward through the mesh.
> I think the dot product above should always be positive. If multiple intersections exist along a "whole" line then the first one in "front" of the line's origin should be returned. This makes ray tracing with a PolyhedronsSet possible.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)