Ejemplo n.º 1
0
  /**
   * Calculates Delaunay triangles out of array of 2D points
   *
   * @param innerPts points inside edges defined by edgePts
   * @param edgePts points on the edge (the edge should be naked having only one triangle touching);
   *     order of edge points needs to be counter clockwise for outer trim loop, clockwise for inner
   *     hole trim loop.
   * @return array of triangles, which consist of array of 3 points of IVec2
   */
  public static IVec2[][] getTriangles(IVec2[] innerPts, IVec2[][] edgePts) {

    int innerPtsNum = 0;
    int edgePtsNum = 0;
    if (innerPts != null) innerPtsNum = innerPts.length;
    if (edgePts != null) {
      for (int i = 0; i < edgePts.length; i++) edgePtsNum += edgePts[i].length;
    }

    IVec2[] pts = new IVec2[innerPtsNum + edgePtsNum];
    if (innerPts != null) {
      for (int i = 0; i < innerPts.length; i++) {
        pts[i] = innerPts[i];
        // IOut.p("pts["+i+"] is innerPts "+innerPts[i]); //
      }
    }

    int[][] edgePtIdx = null;
    if (edgePts != null) {
      edgePtIdx = new int[edgePts.length][];
      int ptIdx = innerPtsNum;
      for (int i = 0; i < edgePts.length; i++) {
        edgePtIdx[i] = new int[edgePts[i].length];
        for (int j = 0; j < edgePts[i].length; j++) {
          // IOut.p("ptIdx="+ptIdx+" / pts.length="+pts.length); //
          // IOut.p("pts["+ptIdx+"] is edgePts "+edgePts[i][j]); //
          pts[ptIdx] = edgePts[i][j];
          edgePtIdx[i][j] = ptIdx;
          ptIdx++;
        }
      }
    }

    if (pts.length == 3) {
      if (isClockwise(pts[0], pts[1], pts[2]))
        return new IVec2[][] {new IVec2[] {pts[0], pts[2], pts[1]}};
      return new IVec2[][] {new IVec2[] {pts[0], pts[1], pts[2]}};
    }

    ArrayList<IVec2[]> triangles = new ArrayList<IVec2[]>();

    ArrayList<FaceIndex> triangleIndex = new ArrayList<FaceIndex>();

    // IOut.p("pts.length = "+pts.length); //
    // for(int i=0; i<pts.length; i++) IOut.p("pts["+i+"] = "+ pts[i]); //

    EdgeCounter edgeCount = new EdgeCounter(pts.length);

    for (int i = 0; i < edgePtIdx.length; i++) {
      for (int j = 0; j < edgePtIdx[i].length; j++) {
        edgeCount.addEdge(edgePtIdx[i][j], edgePtIdx[i][(j + 1) % edgePtIdx[i].length]);
      }
    }

    // in case a point on edges are on other loop's edge
    for (int i = 0; i < edgePtIdx.length; i++) {
      for (int j = 0; j < edgePtIdx[i].length; j++) {
        int ept1 = edgePtIdx[i][j];
        int ept2 = edgePtIdx[i][(j + 1) % edgePtIdx[i].length];
        for (int k = 0; k < edgePtIdx.length; k++) {
          if (k != i) {
            for (int l = 0; l < edgePtIdx[k].length; l++) {
              if (pts[edgePtIdx[k][l]].isStraight(pts[ept1], pts[ept2])
                  && pts[edgePtIdx[k][l]].isBetween(pts[ept1], pts[ept2])) {
                edgeCount.addEdge(ept1, edgePtIdx[k][l]);
                edgeCount.addEdge(ept2, edgePtIdx[k][l]);
              }
            }
          }
        }
      }
    }

    for (int i = 0; i < pts.length - 2; i++) {

      // IOut.p((i+1)+"/"+(pts.length-2)); //

      for (int j = i + 1; j < pts.length - 1; j++) {

        for (int k = j + 1; k < pts.length && edgeCount.isEdgeOpen(i, j); k++) {
          boolean anyInside = false;

          // IOut.p("<"+i+","+j+","+k+">"); //
          // IOut.p("isFaceCrossing = "+ isFaceCrossing(pts, edgeCount, i, j, k));
          // IOut.p("checkDirectionOnEdgePoints =
          // "+checkDirectionOnEdgePoints(pts,edgePts,i,j,k,innerPtsNum) );
          // IOut.p("isStraight = "+pts[i].isStraight(pts[j],pts[k])); //

          if (edgeCount.isEdgeOpen(i, k)
              && edgeCount.isEdgeOpen(j, k)
              && !isFaceCrossing(pts, edgeCount, i, j, k)
              // && checkFaceDirection(pts, edgeCount, i, j, k)
              && checkDirectionOnEdgePoints(pts, edgePts, i, j, k, innerPtsNum) // added
              && !pts[i].isStraight(pts[j], pts[k]) // added
          ) {

            for (int l = 0; l < pts.length && !anyInside; l++)
              if (l != i && l != j && l != k) {
                // IOut.p("<"+i+","+j+","+k+","+l+">"); //

                if (isInsideCircumcircle(pts[l], pts[i], pts[j], pts[k])) {

                  // check if case pts[l] is crossing edge of trim lines

                  if (checkDirectionOfInnerCircumcirclePoint(
                      pts, edgePts, i, j, k, l, innerPtsNum)) {
                    anyInside = true;
                    // IOut.p(pts[l] + " is inside <"+pts[i]+", "+pts[j]+", "+pts[k]+">"); //
                    // IOut.p("pt["+l+"] is INside pt["+i+"], pt["+j+"], pt["+k+"]"); //
                  }
                  // else; // when pts[l] is crossing the edge of trim

                } else {
                  // IOut.p(pts[l] + " is outside <"+pts[i]+", "+pts[j]+", "+pts[k]+">"); //
                  // IOut.p("pt["+l+"] is OUTside pt["+i+"], pt["+j+"], pt["+k+"]"); //
                }
              }
            if (!anyInside) { // nothing is inside
              // IOut.p("<"+i+","+j+","+k+">: triangle is added at "+triangles.size()); //
              if (isClockwise(pts[i], pts[j], pts[k])) {
                triangles.add(new IVec2[] {pts[i], pts[k], pts[j]});
                triangleIndex.add(new FaceIndex(i, k, j));
              } else {
                triangles.add(new IVec2[] {pts[i], pts[j], pts[k]});
                triangleIndex.add(new FaceIndex(i, j, k));
              }

              /*
                 if(i==0&&j==1&&k==4){
              new IGCurve(new IVec[]{ new IVec(pts[i]),
              			  new IVec(pts[j]),
              			  new IVec(pts[k])});
                 }
                 */

              edgeCount.addFace(i, j, k);

              // IOut.p("edgeCount.isEdgeOnOutline("+i+","+j+") = "+edgeCount.isEdgeOnOutline(i,j));
              // IOut.p("edgeCount.getEdgeNum("+i+","+j+") = "+edgeCount.getEdgeNum(i,j));
              // IOut.p("edgeCount.getFaceVertexIndex("+i+","+j+") =
              // "+edgeCount.getFaceVertexIndex(i,j));

              // edgeCount.addEdge(i,j);
              // edgeCount.addEdge(i,k);
              // edgeCount.addEdge(j,k);
            }
            // else IOut.p("pt out"); //
          }
        }
      }
    }

    // filling holes
    checkNakedEdge(pts, triangleIndex, triangles, edgeCount);

    // IOut.p("trinangles.size()="+triangles.size()); //

    return triangles.toArray(new IVec2[triangles.size()][]);
  }