예제 #1
0
  public static boolean checkFaceDirection(
      IVec2[] pts, EdgeCounter edgeCount, int ptIdx1, int ptIdx2, int ptIdx3) {

    // IOut.p("<"+ptIdx1+", "+ptIdx2+", "+ptIdx3+">"); //
    if (edgeCount.isEdgeOnOutline(ptIdx1, ptIdx2)) {
      if (ptIdx2 - ptIdx1 != 1) {
        // to be sequential difference should be 1, if not, it's closing poitn of loop
        int tmp = ptIdx2;
        ptIdx2 = ptIdx1;
        ptIdx1 = tmp;
      }
      if (!isFaceDirectionOnEdgeCorrect(pts[ptIdx1], pts[ptIdx2], pts[ptIdx3])) return false;
    }

    if (edgeCount.isEdgeOnOutline(ptIdx1, ptIdx3)) {
      if (ptIdx3 - ptIdx1 != 1) {
        // to be sequential difference should be 1, if not, it's closing poitn of loop
        int tmp = ptIdx1;
        ptIdx1 = ptIdx3;
        ptIdx3 = tmp;
      }
      if (!isFaceDirectionOnEdgeCorrect(pts[ptIdx1], pts[ptIdx3], pts[ptIdx2])) return false;
    }

    if (edgeCount.isEdgeOnOutline(ptIdx2, ptIdx3)) {
      if (ptIdx3 - ptIdx2 != 1) {
        // to be sequential difference should be 1, if not, it's closing poitn of loop
        int tmp = ptIdx3;
        ptIdx3 = ptIdx2;
        ptIdx2 = tmp;
      }
      if (!isFaceDirectionOnEdgeCorrect(pts[ptIdx2], pts[ptIdx3], pts[ptIdx1])) return false;
    }

    return true;
  }
예제 #2
0
  public static boolean isFaceCrossing(
      IVec2[] pts, EdgeCounter edgeCount, int ptIdx1, int ptIdx2, int ptIdx3) {
    if (edgeCount.hasOneFace(ptIdx1, ptIdx2)) {
      if (isVertexOnSameSide(
          pts[ptIdx1], pts[ptIdx2], pts[ptIdx3], pts[edgeCount.getFaceVertexIndex(ptIdx1, ptIdx2)]))
        return true;
    }

    if (edgeCount.hasOneFace(ptIdx1, ptIdx3)) {
      if (isVertexOnSameSide(
          pts[ptIdx1], pts[ptIdx3], pts[ptIdx2], pts[edgeCount.getFaceVertexIndex(ptIdx1, ptIdx3)]))
        return true;
    }

    if (edgeCount.hasOneFace(ptIdx2, ptIdx3)) {
      if (isVertexOnSameSide(
          pts[ptIdx2], pts[ptIdx3], pts[ptIdx1], pts[edgeCount.getFaceVertexIndex(ptIdx2, ptIdx3)]))
        return true;
    }
    return false;
  }
예제 #3
0
  public static void checkNakedEdge(
      IVec2[] pts,
      ArrayList<FaceIndex> faceIdx,
      ArrayList<IVec2[]> triangles,
      EdgeCounter edgeCount) {

    for (int i = 0; i < pts.length - 1; i++) {
      // IOut.p(i+"/"+pts.length); //
      for (int j = i + 1; j < pts.length; j++) {

        if (edgeCount.getEdgeNum(i, j) == 1) {
          boolean added = false;
          // for(int k=j+1; k<pts.length && !added; k++){
          for (int k = 0; k < pts.length && !added; k++) {

            // fill triangle at the edge or, fill triangle in an obvious triangular hole
            // not filling when 3 edges already form a triangle
            FaceIndex fidx = null;

            boolean addFace = false;

            if (k != i && k != j) {
              int idx1 = i;
              int idx2 = j;
              int idx3 = k;

              // re-order
              if (k < i) {
                idx1 = k;
                idx2 = i;
                idx3 = j;
              } else if (k < j) {
                idx1 = i;
                idx2 = k;
                idx3 = j;
              }

              /*
              IOut.p("checking <"+i+","+j+","+k+">"); //
              IOut.p("isEdgeOnOutline("+idx1+","+idx2+") = "+
               edgeCount.isEdgeOnOutline(idx1,idx2));
              IOut.p("isEdgeOnOutline("+idx1+","+idx3+") = "+
               edgeCount.isEdgeOnOutline(idx1,idx3));
              IOut.p("isEdgeOnOutline("+idx2+","+idx3+") = "+
               edgeCount.isEdgeOnOutline(idx2,idx3));
              IOut.p("isFaceDirectionOnEdgeCorrect("+idx1+","+idx2+","+idx3+") = "+
               isFaceDirectionOnEdgeCorrect(pts[idx1],pts[idx2],pts[idx3]));
              IOut.p("isFaceDirectionOnEdgeCorrect("+idx1+","+idx3+","+idx2+") = "+
               isFaceDirectionOnEdgeCorrect(pts[idx1],pts[idx3],pts[idx2]));
              IOut.p("isFaceDirectionOnEdgeCorrect("+idx2+","+idx3+","+idx1+") = "+
               isFaceDirectionOnEdgeCorrect(pts[idx2],pts[idx3],pts[idx1]));
              IOut.p("isEdgeOpen("+idx1+","+idx2+") = "+
               edgeCount.isEdgeOpen(idx1,idx2));
              IOut.p("isEdgeOpen("+idx1+","+idx3+") = "+
               edgeCount.isEdgeOpen(idx1,idx3));
              IOut.p("isEdgeOpen("+idx2+","+idx3+") = "+
               edgeCount.isEdgeOpen(idx2,idx3));
              */

              if (edgeCount.isEdgeOnOutline(idx1, idx2)
                  && edgeCount.isEdgeOnOutline(idx2, idx3)
                  && edgeCount.hasOneFace(idx1, idx3)
                  &&
                  // isFaceDirectionOnEdgeCorrect(pts[idx1],pts[idx2],pts[idx3])){
                  // if idx1==0, idx2 is last point on outline and order should be idx2->idx1
                  isFaceDirectionOnEdgeCorrect(
                      pts[idx1 == 0 ? idx2 : idx1], pts[idx1 == 0 ? idx1 : idx2], pts[idx3])) {

                // IOut.p("addFace 4"); //
                addFace = true;
              } else if (edgeCount.isEdgeOnOutline(idx1, idx3)
                  && edgeCount.isEdgeOnOutline(idx2, idx3)
                  && edgeCount.hasOneFace(idx1, idx2)
                  &&
                  // isFaceDirectionOnEdgeCorrect(pts[idx1],pts[idx3],pts[idx2])){
                  isFaceDirectionOnEdgeCorrect(
                      pts[idx1 == 0 ? idx3 : idx1], pts[idx1 == 0 ? idx1 : idx3], pts[idx2])) {
                // IOut.p("addFace 5"); //
                addFace = true;
              } else if (edgeCount.isEdgeOnOutline(idx1, idx3)
                  && edgeCount.isEdgeOnOutline(idx1, idx2)
                  && edgeCount.hasOneFace(idx2, idx3)
                  &&
                  // isFaceDirectionOnEdgeCorrect(pts[idx2],pts[idx3],pts[idx1])){
                  isFaceDirectionOnEdgeCorrect(
                      pts[idx2 == 0 ? idx3 : idx2], pts[idx2 == 0 ? idx2 : idx3], pts[idx1])) {
                // IOut.p("addFace 6"); //
                addFace = true;
              } else if (edgeCount.isEdgeOnOutline(idx1, idx2)
                  &&
                  // (edgeCount.isEdgeOpen(idx1,idx3) || edgeCount.isEdgeOpen(idx2,idx3))){
                  edgeCount.isEdgeOpen(idx1, idx3)
                  && edgeCount.isEdgeOpen(idx2, idx3)) {
                if (isFaceDirectionOnEdgeCorrect(
                        pts[idx1 == 0 ? idx2 : idx1], pts[idx1 == 0 ? idx1 : idx2], pts[idx3])
                    && !isFaceCrossing(pts, edgeCount, idx1, idx2, idx3)) {
                  // IOut.p("addFace 1"); //
                  addFace = true;
                }
              } else if (edgeCount.isEdgeOnOutline(idx1, idx3)
                  &&
                  // (edgeCount.isEdgeOpen(idx1,idx2)||edgeCount.isEdgeOpen(idx2,idx3))){
                  edgeCount.isEdgeOpen(idx1, idx2)
                  && edgeCount.isEdgeOpen(idx2, idx3)) {
                if (isFaceDirectionOnEdgeCorrect(
                        pts[idx1 == 0 ? idx3 : idx1], pts[idx1 == 0 ? idx1 : idx3], pts[idx2])
                    && !isFaceCrossing(pts, edgeCount, idx1, idx2, idx3)) {
                  // IOut.p("addFace 2"); //
                  addFace = true;
                }
              } else if (edgeCount.isEdgeOnOutline(idx2, idx3)
                  &&
                  // (edgeCount.isEdgeOpen(idx1,idx2)||edgeCount.isEdgeOpen(idx1,idx3))){
                  edgeCount.isEdgeOpen(idx1, idx2)
                  && edgeCount.isEdgeOpen(idx1, idx3)) {
                // IOut.p("isFaceCrossing("+idx1+","+idx2+","+idx3+") = "+isFaceCrossing(pts,
                // edgeCount, idx1, idx2, idx3)); //

                if (isFaceDirectionOnEdgeCorrect(
                        pts[idx2 == 0 ? idx3 : idx2], pts[idx2 == 0 ? idx2 : idx3], pts[idx1])
                    && !isFaceCrossing(pts, edgeCount, idx1, idx2, idx3)) {
                  // IOut.p("addFace 3 <"+idx2+","+idx3+","+idx1+">"); //
                  addFace = true;
                }
              } else if ((edgeCount.getEdgeNum(idx1, idx2) == 1
                  && edgeCount.getEdgeNum(idx1, idx3) == 1
                  && edgeCount.getEdgeNum(idx2, idx3) == 1
                  && edgeCount.getFaceVertexIndex(idx1, idx2) != -1
                  && edgeCount.getFaceVertexIndex(idx1, idx3) != -1
                  && edgeCount.getFaceVertexIndex(idx2, idx3) != -1
                  && ((fidx = findTriangleIndexWithEdge(faceIdx, idx1, idx2)) == null
                      || fidx.getOtherIndex(idx1, idx2) != idx3))) {
                // IOut.p("addFace 7"); //
                addFace = true;
              }

              if (addFace) {
                // IOut.p("face added at <"+i+","+j+","+k+">"); //
                // edgeCount.addFace(i,j,k);
                // triangles.add(new IVec2[]{ pts[i],pts[j],pts[k]});
                // faceIdx.add(new FaceIndex(i,j,k));

                // IOut.p("face added at <"+idx1+","+idx2+","+idx3+">"); //
                edgeCount.addFace(idx1, idx2, idx3);
                triangles.add(new IVec2[] {pts[idx1], pts[idx2], pts[idx3]});
                faceIdx.add(new FaceIndex(idx1, idx2, idx3));
                added = true;
              }
            }

            /*
            if((edgeCount.getEdgeNum(i,k)==1&&edgeCount.getEdgeNum(j,k)==1 ||
                edgeCount.getEdgeNum(i,k)==1&&edgeCount.getEdgeNum(j,k)==0 ||
                edgeCount.getEdgeNum(i,k)==0&&edgeCount.getEdgeNum(j,k)==1 ) &&
               (edgeCount.getFaceVertexIndex(i,j)==-1 ||
                edgeCount.getFaceVertexIndex(i,k)==-1 ||
                edgeCount.getFaceVertexIndex(j,k)==-1 )
               ||
               ( edgeCount.getEdgeNum(i,k)==1&&edgeCount.getEdgeNum(j,k)==1 &&
                 edgeCount.getFaceVertexIndex(i,j)!=-1 &&
                 edgeCount.getFaceVertexIndex(i,k)!=-1 &&
                 edgeCount.getFaceVertexIndex(j,k)!=-1 &&
                 ((fidx = findTriangleIndexWithEdge(faceIdx, i, j)) ==null ||
                  fidx.getOtherIndex(i,j) != k))
               ){

                IOut.p("face added at <"+i+","+j+","+k+">"); //

                edgeCount.addFace(i,j,k);
                triangles.add(new IVec2[]{ pts[i],pts[j],pts[k]});
                faceIdx.add(new FaceIndex(i,j,k));
                added=true;
            }
            */
          }
        }
      }
    }

    // remove triangles which have naked edge but not on the outline
    // (likely to be inside of inner holes or outside of outer trim
    for (int i = 0; i < pts.length - 1; i++) {
      for (int j = i + 1; j < pts.length; j++) {
        if (edgeCount.getEdgeNum(i, j) == 1 && edgeCount.getFaceVertexIndex(i, j) != -1) {
          // IOut.p("naked edge found at <"+i+","+j+">"); //
          FaceIndex fidx = findTriangleIndexWithEdge(faceIdx, i, j);
          if (fidx != null) {
            int k = fidx.getOtherIndex(i, j);
            IVec2[] tr = findTriangleWithIndex(pts, triangles, i, j, k);
            if (tr != null) {
              triangles.remove(tr);
              // IOut.p("face removed at <"+i+","+j+","+k+">"); //
            }
          }
        }
      }
    }
  }
예제 #4
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()][]);
  }