//Half-Edge Mesh //Source: http://www.flipcode.com/archives/The_Half-Edge_Data_Structure.shtml class HE_Mesh{ ArrayList vertices; ArrayList faces; ArrayList halfEdges; ArrayList edges; PVector bodyCenter; ArrayList faceCenters; ArrayList faceNormals; ArrayList vertexNormals; ArrayList edgeCenters; ArrayList edgeNormals; boolean bodyCenterUpdated; boolean faceCentersUpdated; boolean faceNormalsUpdated; boolean vertexNormalsUpdated; boolean edgeCentersUpdated; boolean edgeNormalsUpdated; boolean indicesUpdated; //CONSTRUCTOR HE_Mesh(){ vertices=new ArrayList(); faces=new ArrayList(); halfEdges=new ArrayList(); edges=new ArrayList(); faceCenters=new ArrayList(); faceNormals=new ArrayList(); vertexNormals=new ArrayList(); edgeCenters=new ArrayList(); edgeNormals=new ArrayList(); bodyCenter=new PVector(0,0,0) ; bodyCenterUpdated=false; faceCentersUpdated=false; faceNormalsUpdated=false; vertexNormalsUpdated=false; edgeCentersUpdated=false; edgeNormalsUpdated=false; indicesUpdated=false; } //DRAWING ROUTINES void draw(){ if(!faceCentersUpdated) setFaceCenters(); Iterator faceItr = faces.iterator(); Iterator faceCtrItr = faceCenters.iterator(); while(faceItr.hasNext()){ HE_Face face=(HE_Face)faceItr.next(); HE_Vertex faceCenter =(HE_Vertex)faceCtrItr.next(); if(face.visible){ HE_HalfEdge halfEdge=face.halfEdge; /*if(halfEdge.next.next.next==halfEdge){ beginShape(); do{ HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); halfEdge= halfEdge.next; } while(halfEdge!=face.halfEdge); endShape(CLOSE); } else{*/ beginShape(TRIANGLE_STRIP); do{ HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); vertex(faceCenter.x,faceCenter.y,faceCenter.z); halfEdge= halfEdge.next; } while(halfEdge!=face.halfEdge); HE_Vertex v=halfEdge.vert; vertex(v.x,v.y,v.z); endShape(); //} } } } void drawVertices(){ Iterator vertexItr = vertices.iterator(); while(vertexItr.hasNext()){ HE_Vertex v=(HE_Vertex)vertexItr.next(); pushMatrix(); translate(v.x,v.y,v.z); box(10); popMatrix(); } } void drawFaceCenters(){ Iterator vertexItr = faceCenters.iterator(); while(vertexItr.hasNext()){ HE_Vertex v=(HE_Vertex)vertexItr.next(); pushMatrix(); translate(v.x,v.y,v.z); box(5); popMatrix(); } } void drawEdgeCenters(){ Iterator vertexItr = edgeCenters.iterator(); while(vertexItr.hasNext()){ HE_Vertex v=(HE_Vertex)vertexItr.next(); pushMatrix(); translate(v.x,v.y,v.z); box(5); popMatrix(); } } void drawEdges(){ Iterator eItr = edges.iterator(); while(eItr.hasNext()){ HE_Edge e=(HE_Edge)eItr.next(); if(e.visible)line(e.halfEdge.vert.x,e.halfEdge.vert.y,e.halfEdge.vert.z,e.halfEdge.next.vert.x,e.halfEdge.next.vert.y,e.halfEdge.next.vert.z); } } void drawEdgesSketch(int r, float d){ for(int i=0;i4) polyFaces.add(f); } for(int i=0;i0f)&&(f<1f)){ HE_HalfEdge origHE1= origE.halfEdge; HE_HalfEdge origHE2= origHE1.pair; HE_Vertex v1=origHE1.vert; HE_Vertex v2=origHE2.vert; HE_Vertex v; v=new HE_Vertex(0,0,0,0); v.x=v1.x+f*(v2.x-v1.x); v.y=v1.y+f*(v2.y-v1.y); v.z=v1.z+f*(v2.z-v1.z); result.vertices.add(v); HE_HalfEdge newHE1=new HE_HalfEdge(); result.halfEdges.add(newHE1); HE_HalfEdge newHE2=new HE_HalfEdge(); result.halfEdges.add(newHE2); newHE1.vert=v; newHE1.next=origHE1.next; newHE1.face=origHE1.face; newHE1.pair=origHE2; origHE1.next=newHE1; origHE1.pair=newHE2; newHE2.vert=v; newHE2.next=origHE2.next; newHE2.face=origHE2.face; newHE2.pair=origHE1; origHE2.next=newHE2; origHE2.pair=newHE1; v.halfEdge=newHE1; HE_Edge newE= new HE_Edge(); result.edges.add(newE); newE.halfEdge=newHE1; newHE1.edge=newE; origHE2.edge=newE; newHE2.edge=origE; origHE1.edge=origE; newE.visible=origE.visible; } result.bodyCenterUpdated=false; result.faceCentersUpdated=false; result.faceNormalsUpdated=false; result.vertexNormalsUpdated=false; result.edgeCentersUpdated=false; result.edgeNormalsUpdated=false; return result; } void insertPointInEdgeSelf(int id, float f){ HE_Edge origE=(HE_Edge)edges.get(id); if((f>0f)&&(f<1f)){ HE_HalfEdge origHE1= origE.halfEdge; HE_HalfEdge origHE2= origHE1.pair; HE_Vertex v1=origHE1.vert; HE_Vertex v2=origHE2.vert; HE_Vertex v; v=new HE_Vertex(0,0,0,0); v.x=v1.x+f*(v2.x-v1.x); v.y=v1.y+f*(v2.y-v1.y); v.z=v1.z+f*(v2.z-v1.z); vertices.add(v); HE_HalfEdge newHE1=new HE_HalfEdge(); halfEdges.add(newHE1); HE_HalfEdge newHE2=new HE_HalfEdge(); halfEdges.add(newHE2); newHE1.vert=v; newHE1.next=origHE1.next; newHE1.face=origHE1.face; newHE1.pair=origHE2; origHE1.next=newHE1; origHE1.pair=newHE2; newHE2.vert=v; newHE2.next=origHE2.next; newHE2.face=origHE2.face; newHE2.pair=origHE1; origHE2.next=newHE2; origHE2.pair=newHE1; v.halfEdge=newHE1; HE_Edge newE= new HE_Edge(); edges.add(newE); newE.halfEdge=newHE1; newHE1.edge=newE; origHE2.edge=newE; newHE2.edge=origE; origHE1.edge=origE; newE.visible=origE.visible; } bodyCenterUpdated=false; faceCentersUpdated=false; faceNormalsUpdated=false; vertexNormalsUpdated=false; edgeCentersUpdated=false; edgeNormalsUpdated=false; indicesUpdated=false; } HE_Mesh insertMidEdgePoints(){ HE_Mesh result=get(); int n=result.edges.size(); for(int i=0;i0f) { result.insertPointInEdgeSelf(i,u); newVertices.add((HE_Vertex)result.vertices.get(result.vertices.size()-1)); numOfIntersections++; } } for(int i=0;i0f) { result.insertPointInEdgeSelf(i,u); newVertices.add((HE_Vertex)result.vertices.get(result.vertices.size()-1)); numOfIntersections++; } } for(int i=0;i=0f){ newFaces.add(nf); } else{ newFaces.add(f); } } else{ if(P.side(c,0.0001f)*P.side((PVector)result.faceCenters.get(i),0.0001f)>=0f)newFaces.add(f); } } result.faces=newFaces; result.cleanUnusedElements(); result.capOpenLoop(); result.bodyCenterUpdated=false; result.faceCentersUpdated=false; result.faceNormalsUpdated=false; result.vertexNormalsUpdated=false; result.edgeCentersUpdated=false; result.edgeNormalsUpdated=false; result.indicesUpdated=false; return (result.validate(false,false)||(!safe))?result:get(); } HE_Mesh cutMesh(ArrayList cutPlanes, PVector c,boolean safe){ HE_Mesh result=get(); float[] r=new float[cutPlanes.size()]; for(int k=0;k= 0; ) { for (int m = 0; m < k; m++) { Plane pl = (Plane)cutPlanes.get(m); Plane pll = (Plane)cutPlanes.get(m+1); if (r[m] > r[m+1]) { Collections.swap(cutPlanes,m,m+1); float tmp=r[m]; r[m]=r[m+1]; r[m+1]=tmp; } } } for(int k=0;k0){ if(!reverse){ for(int j=0;j0){ ArrayList loopedHalfEdges=new ArrayList(); HE_HalfEdge start = (HE_HalfEdge)unpairedEdges.get(0); loopedHalfEdges.add(start); HE_HalfEdge he=start; HE_HalfEdge hen=start; boolean stuck=false; do{ for(int i=0;i1f+cutoff)) return -1f;// intersection beyond endpoints if(abs(u)<=cutoff) return 0f;// intersection at startpoint if((u>=1f-cutoff)&&(u<=1f+cutoff))return 1f;//intersection at endpoint return u;//intersection on edge } } class HE_Vertex extends PVector{ int id; HE_HalfEdge halfEdge; HE_Vertex(float x, float y, float z, int id){ super(x,y,z); this.id=id; } HE_Vertex get(){ return new HE_Vertex(x,y,z,id); } void projectToPlane(Plane P){ float d=P.A*x+P.B*y+P.C*z+P.D; float x0=x-P.A*d; float y0=y-P.B*d; float z0=z-P.C*d; set(x0,y0,z0); } } class HE_Face{ int id; boolean visible; boolean fixed; HE_HalfEdge halfEdge; HE_Face(){ } } float sign(float v){ return (v<0)?-1:((v>0)?1:0); }