public IntersectPoint[] findCrossing() {
    double[] edge1 = new double[8];
    double[] edge2 = new double[8];
    double[] points = new double[6];
    double[] params = new double[6];
    double[] mp1 = new double[2];
    double[] cp1 = new double[2];
    double[] mp2 = new double[2];
    double[] cp2 = new double[2];
    int rule1, rule2, endIndex1, endIndex2;
    int ipCount = 0;

    for (int i = 0; i < rulesSizes[0]; i++) {
      rule1 = rules[0][i];
      endIndex1 = getCurrentEdge(0, i, edge1, mp1, cp1);
      for (int j = 0; j < rulesSizes[1]; j++) {
        ipCount = 0;
        rule2 = rules[1][j];
        endIndex2 = getCurrentEdge(1, j, edge2, mp2, cp2);
        if (((rule1 == PathIterator.SEG_LINETO) || (rule1 == PathIterator.SEG_CLOSE))
            && ((rule2 == PathIterator.SEG_LINETO) || (rule2 == PathIterator.SEG_CLOSE))) {

          ipCount =
              GeometryUtil.intersectLinesWithParams(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge2[0], edge2[1], edge2[2], edge2[3],
                  params);

          if (ipCount != 0) {
            points[0] = GeometryUtil.line(params[0], edge1[0], edge1[2]);
            points[1] = GeometryUtil.line(params[0], edge1[1], edge1[3]);
          }
        } else if (((rule1 == PathIterator.SEG_LINETO) || (rule1 == PathIterator.SEG_CLOSE))
            && (rule2 == PathIterator.SEG_QUADTO)) {
          ipCount =
              GeometryUtil.intersectLineAndQuad(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge2[0], edge2[1], edge2[2], edge2[3],
                  edge2[4], edge2[5], params);
          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.line(params[2 * k], edge1[0], edge1[2]);
            points[2 * k + 1] = GeometryUtil.line(params[2 * k], edge1[1], edge1[3]);
          }
        } else if (rule1 == PathIterator.SEG_QUADTO
            && (rule2 == PathIterator.SEG_LINETO || rule2 == PathIterator.SEG_CLOSE)) {
          ipCount =
              GeometryUtil.intersectLineAndQuad(
                  edge2[0], edge2[1], edge2[2], edge2[3], edge1[0], edge1[1], edge1[2], edge1[3],
                  edge1[4], edge1[5], params);
          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.line(params[2 * k + 1], edge2[0], edge2[2]);
            points[2 * k + 1] = GeometryUtil.line(params[2 * k + 1], edge2[1], edge2[3]);
          }
        } else if ((rule1 == PathIterator.SEG_CUBICTO)
            && ((rule2 == PathIterator.SEG_LINETO) || (rule2 == PathIterator.SEG_CLOSE))) {
          ipCount =
              GeometryUtil.intersectLineAndCubic(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge1[6], edge1[7],
                  edge2[0], edge2[1], edge2[2], edge2[3], params);

          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.line(params[2 * k + 1], edge2[0], edge2[2]);
            points[2 * k + 1] = GeometryUtil.line(params[2 * k + 1], edge2[1], edge2[3]);
          }
        } else if (((rule1 == PathIterator.SEG_LINETO) || (rule1 == PathIterator.SEG_CLOSE))
            && (rule2 == PathIterator.SEG_CUBICTO)) {
          ipCount =
              GeometryUtil.intersectLineAndCubic(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge2[0], edge2[1], edge2[2], edge2[3],
                  edge2[4], edge2[5], edge2[6], edge2[7], params);

          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.line(params[2 * k], edge1[0], edge1[2]);
            points[2 * k + 1] = GeometryUtil.line(params[2 * k], edge1[1], edge1[3]);
          }
        } else if ((rule1 == PathIterator.SEG_QUADTO) && (rule2 == PathIterator.SEG_QUADTO)) {
          ipCount =
              GeometryUtil.intersectQuads(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge2[0], edge2[1],
                  edge2[2], edge2[3], edge2[4], edge2[5], params);
          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.quad(params[2 * k], edge1[0], edge1[2], edge1[4]);
            points[2 * k + 1] = GeometryUtil.quad(params[2 * k], edge1[1], edge1[3], edge1[5]);
          }
        } else if ((rule1 == PathIterator.SEG_QUADTO) && (rule2 == PathIterator.SEG_CUBICTO)) {
          ipCount =
              GeometryUtil.intersectQuadAndCubic(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge2[0], edge2[1],
                  edge2[2], edge2[3], edge2[4], edge2[5], edge2[6], edge2[7], params);

          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.quad(params[2 * k], edge1[0], edge1[2], edge1[4]);
            points[2 * k + 1] = GeometryUtil.quad(params[2 * k], edge1[1], edge1[3], edge1[5]);
          }
        } else if ((rule1 == PathIterator.SEG_CUBICTO) && (rule2 == PathIterator.SEG_QUADTO)) {
          ipCount =
              GeometryUtil.intersectQuadAndCubic(
                  edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5], edge1[0], edge1[1],
                  edge1[2], edge1[3], edge1[4], edge1[5], edge2[6], edge2[7], params);

          for (int k = 0; k < ipCount; k++) {
            points[2 * k] = GeometryUtil.quad(params[2 * k + 1], edge2[0], edge2[2], edge2[4]);
            points[2 * k + 1] = GeometryUtil.quad(params[2 * k + 1], edge2[1], edge2[3], edge2[5]);
          }
        } else if ((rule1 == PathIterator.SEG_CUBICTO) && (rule2 == PathIterator.SEG_CUBICTO)) {
          ipCount =
              GeometryUtil.intersectCubics(
                  edge1[0], edge1[1], edge1[2], edge1[3], edge1[4], edge1[5], edge1[6], edge1[7],
                  edge2[0], edge2[1], edge2[2], edge2[3], edge2[4], edge2[5], edge2[6], edge2[7],
                  params);

          for (int k = 0; k < ipCount; k++) {
            points[2 * k] =
                GeometryUtil.cubic(params[2 * k], edge1[0], edge1[2], edge1[4], edge1[6]);
            points[2 * k + 1] =
                GeometryUtil.cubic(params[2 * k], edge1[1], edge1[3], edge1[5], edge1[7]);
          }
        }

        endIndex1 = i;
        endIndex2 = j;
        int begIndex1 = i - 1;
        int begIndex2 = j - 1;

        for (int k = 0; k < ipCount; k++) {
          IntersectPoint ip = null;
          if (!containsPoint(points[2 * k], points[2 * k + 1])) {
            for (Iterator<IntersectPoint> iter = isectPoints.iterator(); iter.hasNext(); ) {
              ip = iter.next();
              if ((begIndex1 == ip.getBegIndex(true)) && (endIndex1 == ip.getEndIndex(true))) {

                if (ip.getParam(true) > params[2 * k]) {
                  endIndex1 = -(isectPoints.indexOf(ip) + 1);
                  ip.setBegIndex1(-(isectPoints.size() + 1));
                } else {
                  begIndex1 = -(isectPoints.indexOf(ip) + 1);
                  ip.setEndIndex1(-(isectPoints.size() + 1));
                }
              }

              if ((begIndex2 == ip.getBegIndex(false)) && (endIndex2 == ip.getEndIndex(false))) {

                if (ip.getParam(false) > params[2 * k + 1]) {
                  endIndex2 = -(isectPoints.indexOf(ip) + 1);
                  ip.setBegIndex2(-(isectPoints.size() + 1));
                } else {
                  begIndex2 = -(isectPoints.indexOf(ip) + 1);
                  ip.setEndIndex2(-(isectPoints.size() + 1));
                }
              }
            }

            if (rule1 == PathIterator.SEG_CLOSE) {
              rule1 = PathIterator.SEG_LINETO;
            }

            if (rule2 == PathIterator.SEG_CLOSE) {
              rule2 = PathIterator.SEG_LINETO;
            }

            isectPoints.add(
                new IntersectPoint(
                    begIndex1,
                    endIndex1,
                    rule1,
                    i,
                    begIndex2,
                    endIndex2,
                    rule2,
                    j,
                    points[2 * k],
                    points[2 * k + 1],
                    params[2 * k],
                    params[2 * k + 1]));
          }
        }
      }
    }
    return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
  }