public static boolean addOne(Vertex p) { boolean visible = false; // mark from p visible faces QueueElement<Face> wf = ConvexHull.faces.getFirst(); while (wf.getNext() != null) { Face f = wf.getElem(); if (volume(f, p) < 0) { f.visible = true; visible = true; } wf = wf.getNext(); } // no faces visible, p is inside of hull if (!visible) { p.onhull = false; return false; } QueueElement<Edge> we = ConvexHull.edges.getFirst(); while (we.getNext() != null) { Edge e = we.getElem(); if (e.getAdjface(0).visible && e.getAdjface(1).visible) { e.deleted = true; } else { if (e.getAdjface(0).visible || e.getAdjface(1).visible) { e.newface = makeStructs(e, p); } } we = we.getNext(); } return true; }
/** * splits the facet incident to h and g into two facets with a new diagonal between the two * vertices denoted by h and g respectively. The second (new) facet is a copy of the first facet. * Returns h->next() after the operation, i.e., the new diagonal. The new face is to the right of * the new diagonal, the old face is to the left. The time is proportional to the distance from h * to g around the facet. */ public Halfedge splitFacet(Halfedge h, Halfedge g) { if (h == null || g == null) throw new Error("splitFacet: null pointer"); if (h.face != g.face) throw new Error("splitFacet: different incident facets"); if (h == g || h.next == g || g.next == h) { throw new Error("loops and multiple edges are not allowed"); } Halfedge<X> newDiagonal = new Halfedge<X>(); Halfedge<X> oppositeNewDiagonal = new Halfedge<X>(); Face<X> newFace = new Face<X>(); newFace.halfedge = g; newDiagonal.opposite = oppositeNewDiagonal; oppositeNewDiagonal.opposite = newDiagonal; newDiagonal.face = h.face; oppositeNewDiagonal.face = newFace; // a completer Halfedge p = h.next; while (p != g) { p.face = newFace; p = p.next; } h.next = newDiagonal; g.next = oppositeNewDiagonal; return newDiagonal; }
public void setPoint(final Vector3 point) { this.point.set(point); for (final Face<?, ?> face : faces) { face.markDirty(); } owner.markDirty(); }
public void paint(Graphics gg) { int faceSize = Math.min(getWidth() - 4, getHeight() - 4); if (face == null) face = new PADFaceMapped( Math.max(2, (getWidth() - faceSize) / 2), Math.max(2, (getHeight() - faceSize) / 2), faceSize); if (buffer == null) { im = this.createImage(getWidth(), getHeight()); buffer = im.getGraphics(); } super.paint(buffer); buffer.setColor(new Color(255, 255, 255, 0)); buffer.fillRect(0, 0, im.getWidth(null), im.getHeight(null)); face.setDimensions( Math.max(2, (getWidth() - faceSize) / 2), Math.max(2, (getHeight() - faceSize) / 2), faceSize); face.paint(buffer); // draw buffer to screen gg.drawImage(im, 0, 0, null, null); }
public boolean Set(Face f, Mkv a, Mkv b, Mkv c) { Vector3f tmp1 = Stack.alloc(Vector3f.class); Vector3f tmp2 = Stack.alloc(Vector3f.class); Vector3f tmp3 = Stack.alloc(Vector3f.class); Vector3f nrm = Stack.alloc(Vector3f.class); tmp1.sub(b.w, a.w); tmp2.sub(c.w, a.w); nrm.cross(tmp1, tmp2); float len = nrm.length(); tmp1.cross(a.w, b.w); tmp2.cross(b.w, c.w); tmp3.cross(c.w, a.w); boolean valid = (tmp1.dot(nrm) >= -EPA_inface_eps) && (tmp2.dot(nrm) >= -EPA_inface_eps) && (tmp3.dot(nrm) >= -EPA_inface_eps); f.v[0] = a; f.v[1] = b; f.v[2] = c; f.mark = 0; f.n.scale(1f / (len > 0f ? len : cstInf), nrm); f.d = Math.max(0, -f.n.dot(a.w)); return valid; }
/** * This returns an enumeration of all Darts in Graph G in a canonical order starting with * firstDart. The order is canonical in the sense that it only depends on the oriented isomorphism * class of G (and firstDart). That is, if there is an oriented iso G <-> G' sending firstDart <-> * firstDart', then that bijection will send getDarts <-> getDarts'. * * <p>This enumeration is useful in finding explicit bijections of isomorphic graphs. */ public static Dart[] getDarts(Dart firstDart, Graph G) { /** * Description of algorithm: Return all the couples around V0=firstDart.V, then all couples * around V1, .... The order for couples around firstDart.V is counterclockwise starting with * firstDart.F. clockwise around V1,... So we need to order the vertices V0,V1,... and pick the * first face to use at each vertex and the rest is determined. Order on V0,... = first * encountered. Order on faces at vertex = first encountered. */ distinctFIFO vQueue = new distinctFIFO(); util.ConditionGetter fQueue = new util.ConditionGetter(); fQueue.add(firstDart.getF()); vQueue.put(firstDart.getV()); Collection coups = new ArrayList(); int coupsIndex = 0; Vertex V; while ((V = (Vertex) vQueue.remove()) != null) { Face F = (Face) fQueue.get(new incidence(V)); for (int i = 0; i < V.size(); i++) { Face Fx = V.next(F, i); coups.add(new Dart(V, Fx)); vQueue.put(Fx.next(V, 1)); fQueue.add(Fx); } } return (Dart[]) coups.toArray(new Dart[coups.size()]); }
public ImmutableList<Face> bake(Function<Node<?>, Matrix4f> animator) { ImmutableList.Builder<Face> builder = ImmutableList.builder(); for (Face f : getFaces()) { Vertex v1 = f.getV1().bake(this, animator); Vertex v2 = f.getV2().bake(this, animator); Vertex v3 = f.getV3().bake(this, animator); builder.add(new Face(v1, v2, v3, f.getBrush())); } return builder.build(); }
/** * creates a new triangle facet within the hole incident to h by connecting the tip of h with two * new halfedges and a new vertex. Returns the halfedge of the new edge that is incident to the * new facet and the new vertex. */ public Halfedge<X> addTriangleToBorder(Halfedge h, X point) { if (h.face != null) throw new Error("no border edge"); System.out.println("adding triangle to " + h); Face<X> newFace = new Face<X>(); Vertex<X> newVertex = new Vertex<X>(point); Halfedge<X> hPrev = new Halfedge<X>(); Halfedge<X> hNext = new Halfedge<X>(); Halfedge<X> hPrevOpp = new Halfedge<X>(); Halfedge<X> hNextOpp = new Halfedge<X>(); // setting the new face newFace.setEdge(h); // setting hPrev (halfedge preceding h in the new face) hPrev.setFace(newFace); hPrev.setVertex(h.getOpposite().getVertex()); hPrev.setPrev(hNext); hPrev.setNext(h); hPrev.setOpposite(hPrevOpp); // setting hNext (halfedge following h in the new face) hNext.setFace(newFace); hNext.setVertex(newVertex); hNext.setPrev(h); hNext.setNext(hPrev); hNext.setOpposite(hNextOpp); // setting hPrevOpp (new boundary halfedge) hPrevOpp.setFace(null); hPrevOpp.setVertex(newVertex); hPrevOpp.setPrev(h.getPrev()); hPrevOpp.setNext(hNextOpp); hPrevOpp.setOpposite(hPrev); // setting hNextOpp (the other new boundary halfedge) hNextOpp.setFace(null); hNextOpp.setVertex(h.getVertex()); hNextOpp.setPrev(hPrevOpp); hNextOpp.setNext(h.getNext()); hNextOpp.setOpposite(hNext); // updating old boundary halfedge informations h.setFace(newFace); h.setPrev(hPrev); h.setNext(hNext); // setting newVertex newVertex.setEdge(hPrev); // LCA: a controler si c'est hPrev ou hNext // adding new facet, vertex and the four halfedges this.vertices.add(newVertex); this.facets.add(newFace); this.halfedges.add(hPrev); this.halfedges.add(hNext); this.halfedges.add(hPrevOpp); this.halfedges.add(hNextOpp); return hNext; }
public int mergeAdjacentFace(HalfEdge hedgeAdj, Face[] discarded) { Face oppFace = hedgeAdj.oppositeFace(); int numDiscarded = 0; discarded[numDiscarded++] = oppFace; oppFace.mark = DELETED; HalfEdge hedgeOpp = hedgeAdj.getOpposite(); HalfEdge hedgeAdjPrev = hedgeAdj.prev; HalfEdge hedgeAdjNext = hedgeAdj.next; HalfEdge hedgeOppPrev = hedgeOpp.prev; HalfEdge hedgeOppNext = hedgeOpp.next; while (hedgeAdjPrev.oppositeFace() == oppFace) { hedgeAdjPrev = hedgeAdjPrev.prev; hedgeOppNext = hedgeOppNext.next; } while (hedgeAdjNext.oppositeFace() == oppFace) { hedgeOppPrev = hedgeOppPrev.prev; hedgeAdjNext = hedgeAdjNext.next; } HalfEdge hedge; for (hedge = hedgeOppNext; hedge != hedgeOppPrev.next; hedge = hedge.next) { hedge.face = this; } if (hedgeAdj == he0) { he0 = hedgeAdjNext; } // handle the half edges at the head Face discardedFace; discardedFace = connectHalfEdges(hedgeOppPrev, hedgeAdjNext); if (discardedFace != null) { discarded[numDiscarded++] = discardedFace; } // handle the half edges at the tail discardedFace = connectHalfEdges(hedgeAdjPrev, hedgeOppNext); if (discardedFace != null) { discarded[numDiscarded++] = discardedFace; } computeNormalAndCentroid(); checkConsistency(); return numDiscarded; }
/** * This util method will be used to return an instance of Face for the specified value. * * <p>A null will be return if the specified input is not a valid face value. * * @param value * @return */ public static Face getFace(String value) { for (Face face : Face.values()) { // ignore case if (face.getSymbol().equalsIgnoreCase(value)) { return face; } } return null; }
// ------------------------------------------------------------------------------------------------------------- // // The following should probably be moved into a "mesh" operator object that performs the // clean operation on a mesh. This way we can have lots of operations, without cluttering up basic // mesh functionality. // ------------------------------------------------------------------------------------------------------------- // public void clean() { while (connectAdjacentPaths()) ; // Remove any adjacent duplicates from the list, until none are found] List<Face> cleanedPolyLines = new ArrayList<Face>(); for (Face poly : faces) { while (removeAdjacentDuplicates(poly)) ; if (poly.getVerts().size() > 1) cleanedPolyLines.add(poly); } faces.clear(); faces.addAll(cleanedPolyLines); }
public static Face makeCcw(Face f, Edge e, Vertex p) { int i; Face invisibleFace; if (e.getAdjface(1) == null) { invisibleFace = e.getAdjface(0); } else { if (!e.getAdjface(0).visible) { invisibleFace = e.getAdjface(0); } else { invisibleFace = e.getAdjface(1); } } for (i = 0; invisibleFace.getVertex(i) != e.getEndpt(1); i++) {} if (invisibleFace.getVertex((i + 1) % 3) != e.getEndpt(0)) { f.setVertex(0, e.getEndpt(1)); f.setVertex(1, e.getEndpt(0)); } else { f.setVertex(0, e.getEndpt(0)); f.setVertex(1, e.getEndpt(1)); swap(f.getEdge(1), f.getEdge(2)); } f.setVertex(2, p); return f; }
public void createCenterVertex(Face<X> f) { int degree = f.degree(); Point_[] neighbors = new Point_[degree]; Halfedge<X> e = f.getEdge(); neighbors[0] = e.getVertex().getPoint(); for (int i = 1; i < degree; i++) { e = e.getNext(); neighbors[i] = e.getVertex().getPoint(); } Point_ centerVertex; if (neighbors[0].dimension() == 2) centerVertex = new Point_2(); else if (neighbors[0].dimension() == 3) centerVertex = new Point_3(); else throw new Error("error point dimension"); }
public void render() { if (faces.size() > 0) { Tessellator tessellator = Tessellator.instance; tessellator.startDrawing(glDrawingMode); for (Face face : faces) { face.addFaceForRender(tessellator); } tessellator.draw(); } }
// // Triangulate a single face // // After the edges of a triangle have been split, // we need to connect the new (odd) vertices so each // face is split into four faces. The figure below shows // one step of that process by adding an edge connecting // vertices v1 and v3. Once this is complete we will // update f->e = enew and lather, rinse, repeat. // We're done when e = e->next->next->next; this // condition also prevents us from triangulating a // face that has already been triangulated. // // Interestingly enough, this routine will triangulate // any polygon whether the edges have been split or not. // // * : even vertex (old vertices from before edge splitt // o : odd vertex (created from edge split) // f : original face // e = f->e : edge emanating from even vertex // enew, esym : newly added edge and its symmetric edge // fnew : newly added face // // v2 // * // / \ . avoiding // / \ . backslash // e2 /fnew \ e1 = e->next . as // / esym \ . last // v3 o.........o v1 = e1->v . character // / enew \ . on // e3 / \ e = f->e . line // / f \ . // / \ . // v4 *---------o---------* v0 = e->v // v5 public void triangulate(Face f) { Edge e = E.get(f.e); Edge e1 = E.get(e.next); // check to make sure this face isn't already triangular if (e.i != E.get(E.get(e.next).next).next) { // done when e == e->next->next->next do { Edge e2 = E.get(e1.next); Edge e3 = E.get(e2.next); // Edge = {i, sym, v, f, prev, next} Edge enew = new Edge(); enew.i = E.size(); Edge esym = new Edge(); esym.i = enew.i + 1; // Face = {i, e} Face fnew = new Face(); fnew.i = F.size(); fnew.e = e1.i; // set up esym esym.sym = enew.i; esym.v = e3.v; esym.f = fnew.i; esym.prev = e2.i; esym.next = e1.i; // set up enew enew.sym = esym.i; enew.v = e1.v; enew.f = f.i; enew.prev = e1.prev; enew.next = e2.next; E.add(enew); E.add(esym); F.add(fnew); // clean up loose ends // e1.prev.next, e2.next.prev, e1.prev, e2.next, e1.f, e2.f E.get(e1.prev).next = enew.i; e3.prev = enew.i; e1.prev = esym.i; e2.next = esym.i; e1.f = fnew.i; e2.f = fnew.i; f.e = enew.i; // set e1 and e2 for next step e1 = e3; // e2 = E.get(e3.next); } while (e.i != E.get(E.get(e.next).next).next); } }
public static Face makeStructs(Edge e, Vertex p) { Face new_face = new Face(); Edge[] new_edge = new Edge[2]; for (int i = 0; i < 2; i++) { if (!(e.getEndpt(i).duplicate == null)) { new_edge[i] = Edge.makeEdge(e.getEndpt(i), p); e.getEndpt(i).duplicate = new_edge[i]; } } new_face = Face.makeFace(e, new_edge[0], new_edge[1]); new_face = makeCcw(new_face, e, p); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 3; ++j) { if (new_edge[i] == null || new_edge[i].getAdjface(j) == null) { new_edge[i].setAdjface(j, new_face); break; } } } return new_face; }
public Halfedge<X> fillHole(Halfedge h) { if (h.face != null) throw new Error("error filling hole: h not boundary edge"); Face<X> newFace = new Face<X>(); this.facets.add(newFace); newFace.setEdge(h); Halfedge p = h.next; h.face = newFace; int cont = 1; while (p != h) { p.face = newFace; p = p.next; } return h; }
// 根据人脸中心点坐标从左至右排序 public int compareTo(Face face) { // TODO Auto-generated method stub int result = 0; if (this.getCenterX() > face.getCenterX()) result = 1; else result = -1; return result; }
public void Detach(Face face) { if (face.prev != null || face.next != null) { --nfaces; if (face == root) { root = face.next; root.prev = null; } else { if (face.next == null) { face.prev.next = null; } else { face.prev.next = face.next; face.next.prev = face.prev; } } face.prev = face.next = null; } }
public String facesToString() { String result = "List of faces\n"; Iterator it = this.facets.iterator(); int cont = 0; while (it.hasNext()) { Face<X> f = (Face<X>) it.next(); result = result + "f" + cont + " "; Halfedge<X> e = f.getEdge(); while (e.getNext() != f.getEdge()) { result = result + vertices.indexOf(e.getVertex()) + " "; e = e.getNext(); } result = result + vertices.indexOf(e.getVertex()) + "\n"; cont++; } return result; }
public void showState(int mousex, int mousey) { p = ((double) mousex - (double) getWidth() / (double) 2) / ((double) (getWidth() + 1) / 2.0); d = -((double) mousey - (double) getHeight() / (double) 2) / ((double) (getHeight() + 1) / 2.0); setXY(p, d); face.setEmotion(p, a, d, mousex, mousey); paint(); this.getGraphics().drawLine(mousex - 3, mousey, mousex + 3, mousey); this.getGraphics().drawLine(mousex, mousey - 3, mousex, mousey + 3); }
public void addTexture(Face face, Bitmap bitmap, String id) { if (face == Face.All) { for (int i = 0; i < 6; i++) { faces[i].textures().addById(id); } } else { faces[face.ordinal()].textures().addById(id); } }
public static void buildTetrahedron() { QueueElement<Vertex> v0; QueueElement<Vertex> v3; int volume; // find 3 noncollinear points v0 = ConvexHull.vertices.getFirst(); while (collinear(v0.getElem(), v0.getNext().getElem(), v0.getNext().getNext().getElem())) { v0 = v0.getNext(); if (v0.getNext() == ConvexHull.vertices.getFirst()) { System.err.println("All points are collinear"); System.exit(0); } } // mark vertices as processed v0.getElem().setMark(true); v0.getNext().getElem().setMark(true); v0.getNext().getNext().getElem().setMark(true); Edge e0 = Edge.makeEdge(v0.getElem(), v0.getNext().getElem()); Edge e1 = Edge.makeEdge(v0.getNext().getElem(), v0.getNext().getNext().getElem()); Edge e2 = Edge.makeEdge(v0.getNext().getNext().getElem(), v0.getElem()); Face f = Face.makeFace(e0, e1, e2); f.setVertices(v0.getElem(), v0.getNext().getElem(), v0.getNext().getNext().getElem()); e0.setAdjface(0, f); e1.setAdjface(0, f); e1.setAdjface(0, f); // try to find another noncollinear vertex v3 = v0.getNext().getNext().getNext(); volume = volume(f, v3.getElem()); while (volume == 0) { v3 = v3.getNext(); if (v3 == ConvexHull.vertices.getFirst()) { System.err.println("All points are coplanar"); System.exit(0); } volume = volume(f, v3.getElem()); } v3.getElem().setMark(true); // store vertices in ccw order if (volume < 0) { swap(f.getVertex(1), f.getVertex(2)); swap(f.getEdge(1), f.getEdge(2)); } e0.setAdjface(1, makeStructs(e0, v3.getElem())); e1.setAdjface(1, makeStructs(e1, v3.getElem())); e2.setAdjface(1, makeStructs(e2, v3.getElem())); Cleaning.cleanUp(); }
private void combinePaths(Face dest, Face src, FindResults how) { if (how.flip) src.flip(); // Add them forwards int addAt = 0; for (Vertex v : src.verts) { if (how.before) dest.verts.add(addAt++, v); else dest.verts.add(v); } }
/** * Constructs a triangule Face from vertices v0, v1, and v2. * * @param v0 first vertex * @param v1 second vertex * @param v2 third vertex */ public static Face createTriangle(Vertex v0, Vertex v1, Vertex v2, double minArea) { Face face = new Face(); HalfEdge he0 = new HalfEdge(v0, face); HalfEdge he1 = new HalfEdge(v1, face); HalfEdge he2 = new HalfEdge(v2, face); he0.prev = he2; he0.next = he1; he1.prev = he0; he1.next = he2; he2.prev = he1; he2.next = he0; face.he0 = he0; // compute the normal and offset face.computeNormalAndCentroid(minArea); return face; }
public void mouseMoved(MouseEvent e) { if (isEnabled()) { setXY( ((double) e.getX() - (double) getWidth() / (double) 2) / ((double) (getWidth() + 1) / 2.0), -((double) e.getY() - (double) getHeight() / (double) 2) / ((double) (getHeight() + 1) / 2.0)); face.setEmotion(p, a, d, e.getX(), e.getY()); } paint(); }
public static Face create(Vertex[] vtxArray, int[] indices) { Face face = new Face(); HalfEdge hePrev = null; for (int i = 0; i < indices.length; i++) { HalfEdge he = new HalfEdge(vtxArray[indices[i]], face); if (hePrev != null) { he.setPrev(hePrev); hePrev.setNext(he); } else { face.he0 = he; } hePrev = he; } face.he0.setPrev(hePrev); hePrev.setNext(face.he0); // compute the normal and offset face.computeNormalAndCentroid(); return face; }
public void testDart() { String S = Formatter.testString; // see formatterString.gif Graph G = Graph.getInstance(new Formatter(S)); Vertex V = null; int coupleCount = 0; for (Enumeration E = G.vertexEnumeration(); E.hasMoreElements(); /*--*/ ) { Vertex W = (Vertex) E.nextElement(); coupleCount += W.size(); if (W.size() == 3) V = W; } jassert(V.size() == 3); Face F = V.getAny(); while (F.size() != 5) F = V.next(F, 1); jassert(F.size() == 5); Dart C = new Dart(V, F); Dart[] list = Dart.getDarts(C, G); // compute the expected number of return values; jassert(list.length == coupleCount); jassert(list[0].getV() == C.getV()); jassert(list[0].getF() == C.getF()); // check integrity of each couple. for (int i = 0; i < list.length; i++) { V = list[i].getV(); F = list[i].getF(); jassert(V.next(F, 0) == F); jassert(F.next(V, 0) == V); } // check that all couples are distinct. Hashtable table = new Hashtable(); // { V-> set of F } for (Enumeration E = G.vertexEnumeration(); E.hasMoreElements(); /*--*/ ) { V = (Vertex) E.nextElement(); table.put(V, new HashSet()); } for (int i = 0; i < list.length; i++) { V = list[i].getV(); F = list[i].getF(); HashSet H = (HashSet) table.get(V); jassert(!H.contains(F)); H.add(F); } }
private static int volume(Face f, Vertex p) { double ax = f.getVertex(0).getCoordinate(0) - p.getCoordinate(0); double ay = f.getVertex(0).getCoordinate(1) - p.getCoordinate(1); double az = f.getVertex(0).getCoordinate(2) - p.getCoordinate(2); double bx = f.getVertex(1).getCoordinate(0) - p.getCoordinate(0); double by = f.getVertex(1).getCoordinate(1) - p.getCoordinate(1); double bz = f.getVertex(1).getCoordinate(2) - p.getCoordinate(2); double cx = f.getVertex(2).getCoordinate(0) - p.getCoordinate(0); double cy = f.getVertex(2).getCoordinate(1) - p.getCoordinate(1); double cz = f.getVertex(2).getCoordinate(2) - p.getCoordinate(2); double volume = ax * (by * cz - bz * cy) + ay * (bz * cx - bx * cz) + az * (bx * cy - by * cx); if (volume > 0.5) { return 1; } else if (volume < -0.5) { return -1; } else { return 0; } }
public void triangulate(FaceList newFaces, double minArea) { HalfEdge hedge; if (numVertices() < 4) { return; } Vertex v0 = he0.head(); Face prevFace = null; hedge = he0.next; HalfEdge oppPrev = hedge.opposite; Face face0 = null; for (hedge = hedge.next; hedge != he0.prev; hedge = hedge.next) { Face face = createTriangle(v0, hedge.prev.head(), hedge.head(), minArea); face.he0.next.setOpposite(oppPrev); face.he0.prev.setOpposite(hedge.opposite); oppPrev = face.he0; newFaces.add(face); if (face0 == null) { face0 = face; } } hedge = new HalfEdge(he0.prev.prev.head(), this); hedge.setOpposite(oppPrev); hedge.prev = he0; hedge.prev.next = hedge; hedge.next = he0.prev; hedge.next.prev = hedge; computeNormalAndCentroid(minArea); checkConsistency(); for (Face face = face0; face != null; face = face.next) { face.checkConsistency(); } }