private void processSiteEvent(final Event newSite) {
    HalfEdge lBnd = coast.getHalfEdgeToTheLeftOf((newSite));
    HalfEdge rBnd = coast.getHalfEdgeToTheRightOf(lBnd);

    // if this half-edge has no edge,bot = bottom site (whatever that is)
    Site bot = lBnd.getRightReg(bottomSite);
    Edge e = edgeBisector.newEdgeThatBisects(bot, newSite);
    HalfEdge bisector1 = new HalfEdge(e, Edge.LE);
    // insert this new bisector edge between the left and right bounds
    coast.insert(lBnd, bisector1);

    // if the new bisector intersects with the left edge,
    // remove the left edge's vertex, and put in the new one
    Site p = lBnd.intersect(bisector1);
    if (p != null) {
      events.delete(lBnd);
      events.insert(lBnd, p, p.distTo(newSite));
    }

    HalfEdge bisector2 = new HalfEdge(e, Edge.RE);
    // insert the new HE to the right of the original bisector
    coast.insert(bisector1, bisector2);

    // if this new bisector intersects with the new HalfEdge
    p = bisector2.intersect(rBnd);
    if (p != null) {
      // push the HE into the ordered linked list of vertices
      events.insert(bisector2, p, p.distTo(newSite));
    }
  }
Example #2
0
  public void computeNormal(Vector3d normal, double minArea) {
    computeNormal(normal);

    if (area < minArea) {
      System.out.println("area=" + area);
      // make the normal more robust by removing
      // components parallel to the longest edge

      HalfEdge hedgeMax = null;
      double lenSqrMax = 0;
      HalfEdge hedge = he0;
      do {
        double lenSqr = hedge.lengthSquared();
        if (lenSqr > lenSqrMax) {
          hedgeMax = hedge;
          lenSqrMax = lenSqr;
        }
        hedge = hedge.next;
      } while (hedge != he0);

      Point3d p2 = hedgeMax.head().pnt;
      Point3d p1 = hedgeMax.tail().pnt;
      double lenMax = Math.sqrt(lenSqrMax);
      double ux = (p2.x - p1.x) / lenMax;
      double uy = (p2.y - p1.y) / lenMax;
      double uz = (p2.z - p1.z) / lenMax;
      double dot = normal.x * ux + normal.y * uy + normal.z * uz;
      normal.x -= dot * ux;
      normal.y -= dot * uy;
      normal.z -= dot * uz;

      normal.normalize();
    }
  }
Example #3
0
 /** searches for all opposite HalfEdges */
 public void computeOppositeHalfEdges() {
   if (debug) {
     System.out.println("Compute opposite half edges...");
   }
   for (HalfEdge halfEdge : halfEdges) {
     halfEdge.setOpposite(computeOppositeHalfEdge(halfEdge));
   }
 }
Example #4
0
 public void getVertexIndices(int[] idxs) {
   HalfEdge he = he0;
   int i = 0;
   do {
     idxs[i++] = he.head().index;
     he = he.next;
   } while (he != he0);
 }
Example #5
0
 public void computeCentroid(Point3d centroid) {
   centroid.setZero();
   HalfEdge he = he0;
   do {
     centroid.add(he.head().pnt);
     he = he.next;
   } while (he != he0);
   centroid.scale(1 / (double) numVerts);
 }
Example #6
0
 private void checkEdgeRing(EdgeGraph graph, Coordinate p, Coordinate[] dest) {
   HalfEdge e = graph.findEdge(p, dest[0]);
   HalfEdge onext = e;
   int i = 0;
   do {
     assertTrue(onext.dest().equals2D(dest[i++]));
     onext = onext.oNext();
   } while (onext != e);
 }
Example #7
0
 /**
  * Finds the half-edge within this face which has tail <code>vt</code> and head <code>vh</code>.
  *
  * @param vt tail point
  * @param vh head point
  * @return the half-edge, or null if none is found.
  */
 public HalfEdge findEdge(Vertex vt, Vertex vh) {
   HalfEdge he = he0;
   do {
     if (he.head() == vh && he.tail() == vt) {
       return he;
     }
     he = he.next;
   } while (he != he0);
   return null;
 }
Example #8
0
  /**
   * Determine neighbours vertices for the given vertex.
   *
   * @param vertex the vertex to get the neighbour for
   * @return the determined neighbours.
   */
  private ArrayList<Vertex> getNeighboursVertices(Vertex vertex) {
    ArrayList<Vertex> neighbours = new ArrayList<Vertex>();
    HalfEdge first = vertex.getHalfEdge();
    HalfEdge next = first;

    do {
      neighbours.add(next.getOpposite().getStartVertex());
      next = next.getOpposite().getNext();
    } while (next != first);

    return neighbours;
  }
Example #9
0
 public String getVertexString() {
   String s = null;
   HalfEdge he = he0;
   do {
     if (s == null) {
       s = "" + he.head().index;
     } else {
       s += " " + he.head().index;
     }
     he = he.next;
   } while (he != he0);
   return s;
 }
Example #10
0
  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;
  }
Example #11
0
  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;
  }
Example #12
0
  /**
   * 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;
  }
Example #13
0
  private double areaSquared(HalfEdge hedge0, HalfEdge hedge1) {
    // return the squared area of the triangle defined
    // by the half edge hedge0 and the point at the
    // head of hedge1.

    Point3d p0 = hedge0.tail().pnt;
    Point3d p1 = hedge0.head().pnt;
    Point3d p2 = hedge1.head().pnt;

    double dx1 = p1.x - p0.x;
    double dy1 = p1.y - p0.y;
    double dz1 = p1.z - p0.z;

    double dx2 = p2.x - p0.x;
    double dy2 = p2.y - p0.y;
    double dz2 = p2.z - p0.z;

    double x = dy1 * dz2 - dz1 * dy2;
    double y = dz1 * dx2 - dx1 * dz2;
    double z = dx1 * dy2 - dy1 * dx2;

    return x * x + y * y + z * z;
  }
Example #14
0
  public void computeNormal(Vector3d normal) {
    HalfEdge he1 = he0.next;
    HalfEdge he2 = he1.next;

    Point3d p0 = he0.head().pnt;
    Point3d p2 = he1.head().pnt;

    double d2x = p2.x - p0.x;
    double d2y = p2.y - p0.y;
    double d2z = p2.z - p0.z;

    normal.setZero();

    numVerts = 2;

    while (he2 != he0) {
      double d1x = d2x;
      double d1y = d2y;
      double d1z = d2z;

      p2 = he2.head().pnt;
      d2x = p2.x - p0.x;
      d2y = p2.y - p0.y;
      d2z = p2.z - p0.z;

      normal.x += d1y * d2z - d1z * d2y;
      normal.y += d1z * d2x - d1x * d2z;
      normal.z += d1x * d2y - d1y * d2x;

      he1 = he2;
      he2 = he2.next;
      numVerts++;
    }
    area = normal.norm();
    normal.scale(1 / area);
  }
Example #15
0
 /**
  * computes opposite halfEdge for the given half edge.
  *
  * @param halfEdge the halfEdge to compute the opposite for.
  * @return the opposite HalfEdge to the given one.
  */
 private HalfEdge computeOppositeHalfEdge(HalfEdge halfEdge) {
   Vertex destination = halfEdge.getNext().getStartVertex();
   for (HalfEdge opposite : halfEdges) {
     if (!halfEdge.equals(opposite) && opposite.getStartVertex().equals(destination)) {
       if (opposite.getNext().getStartVertex().equals(halfEdge.getStartVertex())) {
         return opposite;
       }
     }
   }
   return null;
 }
Example #16
0
 public void computeVertexNormals() {
   for (HalfEdge first : halfEdges) {
     HalfEdge cur = first;
     Vector3 sum = cur.getFacet().getNormal();
     do {
       cur = cur.getOpposite().getNext();
       sum.add(cur.getFacet().getNormal());
     } while (cur != first);
     first.getStartVertex().setNormal(sum.getNormalized());
   }
 }
Example #17
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();
    }
  }
 public void addHalfEdge(HalfEdge halfEdge) {
   this.halfEdges.put(halfEdge.getId(), halfEdge);
 }
Example #19
0
  void checkConsistency() {
    // do a sanity check on the face
    HalfEdge hedge = he0;
    double maxd = 0;
    int numv = 0;

    if (numVerts < 3) {
      throw new InternalErrorException("degenerate face: " + getVertexString());
    }
    do {
      HalfEdge hedgeOpp = hedge.getOpposite();
      if (hedgeOpp == null) {
        throw new InternalErrorException(
            "face "
                + getVertexString()
                + ": "
                + "unreflected half edge "
                + hedge.getVertexString());
      } else if (hedgeOpp.getOpposite() != hedge) {
        throw new InternalErrorException(
            "face "
                + getVertexString()
                + ": "
                + "opposite half edge "
                + hedgeOpp.getVertexString()
                + " has opposite "
                + hedgeOpp.getOpposite().getVertexString());
      }
      if (hedgeOpp.head() != hedge.tail() || hedge.head() != hedgeOpp.tail()) {
        throw new InternalErrorException(
            "face "
                + getVertexString()
                + ": "
                + "half edge "
                + hedge.getVertexString()
                + " reflected by "
                + hedgeOpp.getVertexString());
      }
      Face oppFace = hedgeOpp.face;
      if (oppFace == null) {
        throw new InternalErrorException(
            "face "
                + getVertexString()
                + ": "
                + "no face on half edge "
                + hedgeOpp.getVertexString());
      } else if (oppFace.mark == DELETED) {
        throw new InternalErrorException(
            "face "
                + getVertexString()
                + ": "
                + "opposite face "
                + oppFace.getVertexString()
                + " not on hull");
      }
      double d = Math.abs(distanceToPlane(hedge.head().pnt));
      if (d > maxd) {
        maxd = d;
      }
      numv++;
      hedge = hedge.next;
    } while (hedge != he0);

    if (numv != numVerts) {
      throw new InternalErrorException(
          "face " + getVertexString() + " numVerts=" + numVerts + " should be " + numv);
    }
  }
  private void processCircleEvent() {

    // pop the HalfEdge with the lowest vector off the ordered list
    // of vectors
    HalfEdge lBnd = events.extractMin();
    // get the HalfEdge to the left of the above HE
    HalfEdge llBnd = coast.getHalfEdgeToTheLeftOf(lBnd);
    // get the HalfEdge to the right of the above HE
    HalfEdge rBnd = coast.getHalfEdgeToTheRightOf(lBnd);
    // get the HalfEdge to the right of the HE to the right of the
    // lowest HE
    HalfEdge rrBnd = coast.getHalfEdgeToTheRightOf(rBnd);
    // get the Site to the left of the left HE which it bisects
    Site bot = lBnd.getLeftReg(bottomSite);
    // get the Site to the right of the right HE which it bisects
    Site top = rBnd.getRightReg(bottomSite);

    Site v = lBnd.vertex; // get the vertex that caused this event
    // set the vertex number - couldn't do this
    // earlier since we didn't know when it would be processed
    v.sitenbr = nextVertexNbr++;

    endpoint(lBnd.edge, lBnd.side, v);
    // set the endpoint of
    // the left HalfEdge to be this vector
    endpoint(rBnd.edge, rBnd.side, v);
    // set the endpoint of the right HalfEdge to be this vector
    coast.delete(lBnd);
    events.delete(rBnd);
    // remove all vertex events to do with the right HE
    coast.delete(rBnd); // mark the right HE for
    // deletion - can't delete yet because there might be pointers
    // to it in Hash Map
    int pm = Edge.LE; // set the pm variable to zero

    if (bot.y > top.y) {
      // if the site to the left of the event is higher than the
      // Site
      // to the right of it, then swap them and set the 'pm'
      // variable to 1
      Site temp = bot;
      bot = top;
      top = temp;
      pm = Edge.RE;
    }
    Edge e = edgeBisector.newEdgeThatBisects(bot, top); // create an Edge (or
    // line)
    // that is between the two Sites. This creates the formula of
    // the line, and assigns a line number to it
    HalfEdge bisector = new HalfEdge(e, pm); // create a HE from the Edge
    // 'e',
    // and make it point to that edge
    // with its ELedge field
    coast.insert(llBnd, bisector); // insert the new bisector to the
    // right of the left HE
    endpoint(e, Edge.RE - pm, v); // set one endpoint to the new edge
    // to be the vector point 'v'.
    // If the site to the left of this bisector is higher than the
    // right Site, then this endpoint
    // is put in position 0; otherwise in pos 1

    // if left HE and the new bisector intersect, then delete
    // the left HE, and reinsert it
    Site p = llBnd.intersect(bisector);
    if (p != null) {
      events.delete(llBnd);
      events.insert(llBnd, p, p.distTo(bot));
    }

    // if right HE and the new bisector intersect, then
    // reinsert it
    p = bisector.intersect(rrBnd);
    if (p != null) {
      events.insert(bisector, p, p.distTo(bot));
    }
  }
Example #21
0
  private Face connectHalfEdges(HalfEdge hedgePrev, HalfEdge hedge) {
    Face discardedFace = null;

    if (hedgePrev.oppositeFace()
        == hedge.oppositeFace()) { // then there is a redundant edge that we can get rid off

      Face oppFace = hedge.oppositeFace();
      HalfEdge hedgeOpp;

      if (hedgePrev == he0) {
        he0 = hedge;
      }
      if (oppFace.numVertices() == 3) { // then we can get rid of the opposite face altogether
        hedgeOpp = hedge.getOpposite().prev.getOpposite();

        oppFace.mark = DELETED;
        discardedFace = oppFace;
      } else {
        hedgeOpp = hedge.getOpposite().next;

        if (oppFace.he0 == hedgeOpp.prev) {
          oppFace.he0 = hedgeOpp;
        }
        hedgeOpp.prev = hedgeOpp.prev.prev;
        hedgeOpp.prev.next = hedgeOpp;
      }
      hedge.prev = hedgePrev.prev;
      hedge.prev.next = hedge;

      hedge.opposite = hedgeOpp;
      hedgeOpp.opposite = hedge;

      // oppFace was modified, so need to recompute
      oppFace.computeNormalAndCentroid();
    } else {
      hedgePrev.next = hedge;
      hedge.prev = hedgePrev;
    }
    return discardedFace;
  }