예제 #1
0
  /**
   * 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;
  }
예제 #2
0
  public int vertexDegree(Vertex v) {
    int result = 0;
    Halfedge e = v.getHalfedge();

    Halfedge pEdge = e.getNext().getOpposite();
    while (pEdge != e) {
      pEdge = pEdge.getNext().getOpposite();
      result++;
    }

    return result + 1;
  }
예제 #3
0
  public Halfedge<X> makeHole(Halfedge h) {
    if (h == null || h.face == null) throw new Error("error making hole: h or h.face null");
    this.facets.remove(h.getFace());

    Halfedge p = h.next;
    h.face = null;
    int cont = 1;
    while (p != h) {
      p.face = null;
      p = p.next;
    }
    return h;
  }
예제 #4
0
  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");
  }
예제 #5
0
  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;
  }
예제 #6
0
 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;
 }
예제 #7
0
  /**
   * a triangle with border edges is added to the polyhedral surface. Returns a non-border halfedge
   * of the triangle.
   */
  public Halfedge<X> makeTriangle(X p1, X p2, X p3) {
    Face<X> newFace = new Face<X>();
    Vertex<X> newVertex1 = new Vertex<X>(p1);
    Vertex<X> newVertex2 = new Vertex<X>(p2);
    Vertex<X> newVertex3 = new Vertex<X>(p3);
    Halfedge<X> e1 = new Halfedge<X>();
    Halfedge<X> e2 = new Halfedge<X>();
    Halfedge<X> e3 = new Halfedge<X>();
    Halfedge<X> e1Opp = new Halfedge<X>();
    Halfedge<X> e2Opp = new Halfedge<X>();
    Halfedge<X> e3Opp = new Halfedge<X>();

    // setting the new face
    newFace.setEdge(e1);
    // setting the new vertices (LCA: a' controler)
    newVertex1.setEdge(e2);
    newVertex2.setEdge(e3);
    newVertex3.setEdge(e1);
    // setting e1
    e1.setFace(newFace);
    e1.setVertex(newVertex1);
    e1.setPrev(e3);
    e1.setNext(e2);
    e1.setOpposite(e1Opp);
    // setting e2
    e2.setFace(newFace);
    e2.setVertex(newVertex2);
    e2.setPrev(e1);
    e2.setNext(e3);
    e2.setOpposite(e2Opp);
    // setting e3
    e3.setFace(newFace);
    e3.setVertex(newVertex3);
    e3.setPrev(e2);
    e3.setNext(e1);
    e3.setOpposite(e3Opp);
    // setting e1Opp (boundary halfedge opposite to e1)
    e1Opp.setFace(null);
    e1Opp.setVertex(newVertex3);
    e1Opp.setPrev(e2Opp);
    e1Opp.setNext(e3Opp);
    e1Opp.setOpposite(e1);
    // setting e2Opp (boundary halfedge opposite to e2)
    e2Opp.setFace(null);
    e2Opp.setVertex(newVertex1);
    e2Opp.setPrev(e3Opp);
    e2Opp.setNext(e1Opp);
    e2Opp.setOpposite(e2);
    // setting e3Opp (boundary halfedge opposite to e3)
    e3Opp.setFace(null);
    e3Opp.setVertex(newVertex2);
    e3Opp.setPrev(e1Opp);
    e3Opp.setNext(e2Opp);
    e3Opp.setOpposite(e3);

    this.facets.add(newFace);
    this.vertices.add(newVertex1);
    this.vertices.add(newVertex2);
    this.vertices.add(newVertex3);
    this.halfedges.add(e1);
    this.halfedges.add(e1Opp);
    this.halfedges.add(e2);
    this.halfedges.add(e2Opp);
    this.halfedges.add(e3);
    this.halfedges.add(e3Opp);

    return e1;
  }
예제 #8
0
  /**
   * 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;
  }
예제 #9
0
  /**
   * returns true if the polyhedral surface is combinatorially consistent. If borders==true
   * normalization of the border edges is checked too. This method checks that each facet is at
   * least a triangle and that the two incident facets of a non-border edge are distinct.
   */
  public boolean isValid(boolean borders) {
    boolean valid = true;
    System.out.print("Checking Polyhedron...");
    int n = this.vertices.size();
    int e = this.halfedges.size();
    int f = this.facets.size();

    for (int i = 0; i < this.halfedges.size(); i++) {
      Halfedge<X> pedge = this.halfedges.get(i);
      if (pedge.getOpposite() == null) {
        System.out.print("error opposite: " + i);
        valid = false;
        // Face face=pedge.getFace();
        // int[] ind=face.getVertexIndices(this);
        // System.out.println(" "+ind[0]+" "+ind[1]+" "+ind[2]);
      }
      if (pedge.getNext() == null) {
        System.out.println("error next_edge: " + i);
        valid = false;
      }
      if (pedge.getPrev() == null) {
        System.out.println("error prev_edge: " + i);
        valid = false;
      }
      if (pedge.getVertex() == null) {
        System.out.println("error vertex: " + i);
        valid = false;
      }
      if (pedge.opposite != null && pedge.face == pedge.getOpposite().face) {
        System.out.println("error edge: " + i);
        valid = false;
      }
    }
    for (int i = 0; i < this.facets.size(); i++) {
      Face<X> pface = this.facets.get(i);
      if (pface == null) {
        System.out.println("error face pointer");
        valid = false;
      }
      if (pface.halfedge == null) {
        System.out.println("error face.halfedge");
        valid = false;
      }
      if (pface.degree() < 3) {
        System.out.println("error face degree");
        return valid = false;
      }
    }
    for (int i = 0; i < this.vertices.size(); i++) {
      Vertex<X> pvertex = this.vertices.get(i);
      // System.out.println(""+pvertex.toString());
      if (pvertex == null) {
        System.out.println("error vertex pointer:" + i);
        valid = false;
      }
      if (pvertex.halfedge == null) {
        System.out.println("error vertex.halfedge: " + i);
        valid = false;
      }
      if (pvertex.getPoint() == null) {
        System.out.println("error vertex.point: " + i);
        valid = false;
      }
    }

    if (valid == true) System.out.println("ok");
    else System.out.println("not valid");

    System.out.print("n: " + n + "  e: " + e / 2 + "  f: " + f + " - ");
    int g = -(n - e / 2 + f - 2) / 2;
    System.out.println("genus: " + g);

    return valid;
  }
예제 #10
0
  private void fortunesAlgorithm() {
    Site newSite, bottomSite, topSite, tempSite;
    Vertex v, vertex;
    Point newintstar = null;
    LR leftRight;
    Halfedge lbnd, rbnd, llbnd, rrbnd, bisector;
    Edge edge;

    Rectangle dataBounds = _sites.getSitesBounds();

    int sqrt_nsites = (int) Math.sqrt(_sites.get_length() + 4);
    HalfedgePriorityQueue heap =
        new HalfedgePriorityQueue(dataBounds.y, dataBounds.height, sqrt_nsites);
    EdgeList edgeList = new EdgeList(dataBounds.x, dataBounds.width, sqrt_nsites);
    ArrayList<Halfedge> halfEdges = new ArrayList();
    ArrayList<Vertex> vertices = new ArrayList();

    Site bottomMostSite = _sites.next();
    newSite = _sites.next();

    for (; ; ) {
      if (heap.empty() == false) {
        newintstar = heap.min();
      }

      if (newSite != null && (heap.empty() || compareByYThenX(newSite, newintstar) < 0)) {
        /* new site is smallest */
        // trace("smallest: new site " + newSite);

        // Step 8:
        lbnd =
            edgeList.edgeListLeftNeighbor(
                newSite.get_coord()); // the Halfedge just to the left of newSite
        // trace("lbnd: " + lbnd);
        rbnd = lbnd.edgeListRightNeighbor; // the Halfedge just to the right
        // trace("rbnd: " + rbnd);
        bottomSite = rightRegion(lbnd, bottomMostSite); // this is the same as leftRegion(rbnd)
        // this Site determines the region containing the new site
        // trace("new Site is in region of existing site: " + bottomSite);

        // Step 9:
        edge = Edge.createBisectingEdge(bottomSite, newSite);
        // trace("new edge: " + edge);
        _edges.add(edge);

        bisector = Halfedge.create(edge, LR.LEFT);
        halfEdges.add(bisector);
        // inserting two Halfedges into edgeList constitutes Step 10:
        // insert bisector to the right of lbnd:
        edgeList.insert(lbnd, bisector);

        // first half of Step 11:
        if ((vertex = Vertex.intersect(lbnd, bisector)) != null) {
          vertices.add(vertex);
          heap.remove(lbnd);
          lbnd.vertex = vertex;
          lbnd.ystar = vertex.get_y() + newSite.dist(vertex);
          heap.insert(lbnd);
        }

        lbnd = bisector;
        bisector = Halfedge.create(edge, LR.RIGHT);
        halfEdges.add(bisector);
        // second Halfedge for Step 10:
        // insert bisector to the right of lbnd:
        edgeList.insert(lbnd, bisector);

        // second half of Step 11:
        if ((vertex = Vertex.intersect(bisector, rbnd)) != null) {
          vertices.add(vertex);
          bisector.vertex = vertex;
          bisector.ystar = vertex.get_y() + newSite.dist(vertex);
          heap.insert(bisector);
        }

        newSite = _sites.next();
      } else if (heap.empty() == false) {
        /* intersection is smallest */
        lbnd = heap.extractMin();
        llbnd = lbnd.edgeListLeftNeighbor;
        rbnd = lbnd.edgeListRightNeighbor;
        rrbnd = rbnd.edgeListRightNeighbor;
        bottomSite = leftRegion(lbnd, bottomMostSite);
        topSite = rightRegion(rbnd, bottomMostSite);
        // these three sites define a Delaunay triangle
        // (not actually using these for anything...)
        // _triangles.push(new Triangle(bottomSite, topSite, rightRegion(lbnd)));

        v = lbnd.vertex;
        v.setIndex();
        lbnd.edge.setVertex(lbnd.leftRight, v);
        rbnd.edge.setVertex(rbnd.leftRight, v);
        edgeList.remove(lbnd);
        heap.remove(rbnd);
        edgeList.remove(rbnd);
        leftRight = LR.LEFT;
        if (bottomSite.get_y() > topSite.get_y()) {
          tempSite = bottomSite;
          bottomSite = topSite;
          topSite = tempSite;
          leftRight = LR.RIGHT;
        }
        edge = Edge.createBisectingEdge(bottomSite, topSite);
        _edges.add(edge);
        bisector = Halfedge.create(edge, leftRight);
        halfEdges.add(bisector);
        edgeList.insert(llbnd, bisector);
        edge.setVertex(LR.other(leftRight), v);
        if ((vertex = Vertex.intersect(llbnd, bisector)) != null) {
          vertices.add(vertex);
          heap.remove(llbnd);
          llbnd.vertex = vertex;
          llbnd.ystar = vertex.get_y() + bottomSite.dist(vertex);
          heap.insert(llbnd);
        }
        if ((vertex = Vertex.intersect(bisector, rrbnd)) != null) {
          vertices.add(vertex);
          bisector.vertex = vertex;
          bisector.ystar = vertex.get_y() + bottomSite.dist(vertex);
          heap.insert(bisector);
        }
      } else {
        break;
      }
    }

    // heap should be empty now
    heap.dispose();
    edgeList.dispose();

    for (Halfedge halfEdge : halfEdges) {
      halfEdge.reallyDispose();
    }
    halfEdges.clear();

    // we need the vertices to clip the edges
    for (Edge e : _edges) {
      e.clipVertices(_plotBounds);
    }
    // but we don't actually ever use them again!
    for (Vertex v0 : vertices) {
      v0.dispose();
    }
    vertices.clear();
  }