private void _resolveOverlapOddEven(
      boolean bDirection1,
      boolean bDirection2,
      int vertexA1,
      int vertexB1,
      int vertexA2,
      int vertexB2) {
    if (bDirection1 != bDirection2) {
      if (bDirection1) {
        // _ASSERT(m_shape.getNextVertex(vertexA1) == vertexB1);
        // _ASSERT(m_shape.getNextVertex(vertexB2) == vertexA2);
        m_shape.setNextVertex_(vertexA1, vertexA2); // B1< B2
        m_shape.setPrevVertex_(vertexA2, vertexA1); // | |
        m_shape.setNextVertex_(vertexB2, vertexB1); // | |
        m_shape.setPrevVertex_(vertexB1, vertexB2); // A1 >A2

        _transferVertexData(vertexA2, vertexA1);
        _beforeRemoveVertex(vertexA2, true);
        m_shape.removeVertexInternal_(vertexA2, true);
        _removeAngleSortInfo(vertexA1);
        _transferVertexData(vertexB2, vertexB1);
        _beforeRemoveVertex(vertexB2, false);
        m_shape.removeVertexInternal_(vertexB2, false);
        _removeAngleSortInfo(vertexB1);
      } else {
        // _ASSERT(m_shape.getNextVertex(vertexB1) == vertexA1);
        // _ASSERT(m_shape.getNextVertex(vertexA2) == vertexB2);
        m_shape.setNextVertex_(vertexA2, vertexA1); // B1 B2<
        m_shape.setPrevVertex_(vertexA1, vertexA2); // | |
        m_shape.setNextVertex_(vertexB1, vertexB2); // | |
        m_shape.setPrevVertex_(vertexB2, vertexB1); // A1< A2

        _transferVertexData(vertexA2, vertexA1);
        _beforeRemoveVertex(vertexA2, false);
        m_shape.removeVertexInternal_(vertexA2, false);
        _removeAngleSortInfo(vertexA1);
        _transferVertexData(vertexB2, vertexB1);
        _beforeRemoveVertex(vertexB2, true);
        m_shape.removeVertexInternal_(vertexB2, true);
        _removeAngleSortInfo(vertexB1);
      }
    } else // bDirection1 == bDirection2
    {
      if (!bDirection1) {
        // _ASSERT(m_shape.getNextVertex(vertexB1) == vertexA1);
        // _ASSERT(m_shape.getNextVertex(vertexB2) == vertexA2);
      } else {
        // _ASSERT(m_shape.getNextVertex(vertexA1) == vertexB1);
        // _ASSERT(m_shape.getNextVertex(vertexA2) == vertexB2);
      }

      // if (m_shape._RingParentageCheckInternal(vertexA1, vertexA2))
      {
        int a1 = bDirection1 ? vertexA1 : vertexB1;
        int a2 = bDirection2 ? vertexA2 : vertexB2;
        int b1 = bDirection1 ? vertexB1 : vertexA1;
        int b2 = bDirection2 ? vertexB2 : vertexA2;

        // m_shape.dbgVerifyIntegrity(a1);//debug
        // m_shape.dbgVerifyIntegrity(a2);//debug

        boolean bVisitedA1 = false;
        m_shape.setNextVertex_(a1, a2); // ^ | <--- ^ \ --.
        m_shape.setNextVertex_(a2, a1); // | | | ^ | |
        m_shape.setPrevVertex_(b1, b2); // | | | | | |
        m_shape.setPrevVertex_(b2, b1); // | | | | | |
        int v = b2; // | | | | =>| |
        while (v != a2) // | | . | | -. |
        { // | <-- | | | ./ | |
          int prev = m_shape.getPrevVertex(v); // | | | | | | | |
          int next = m_shape.getNextVertex(v); // <-+---<--- |
          // <-+---<--- |
          m_shape.setPrevVertex_(v, next); // --------. <--------
          m_shape.setNextVertex_(v, prev);
          bVisitedA1 |= v == a1;
          v = next;
        }

        if (!bVisitedA1) {
          // a case of two rings being merged
          int prev = m_shape.getPrevVertex(a2);
          int next = m_shape.getNextVertex(a2);
          m_shape.setPrevVertex_(a2, next);
          m_shape.setNextVertex_(a2, prev);
        } else {
          // merge happend on the same ring.
        }

        // m_shape.dbgVerifyIntegrity(b1);//debug
        // m_shape.dbgVerifyIntegrity(a1);//debug

        _transferVertexData(a2, a1);
        _beforeRemoveVertex(a2, true);
        m_shape.removeVertexInternal_(a2, false);
        _removeAngleSortInfo(a1);
        _transferVertexData(b2, b1);
        _beforeRemoveVertex(b2, true);
        m_shape.removeVertexInternal_(b2, false);
        _removeAngleSortInfo(b1);

        // m_shape.dbgVerifyIntegrity(b1);//debug
        // m_shape.dbgVerifyIntegrity(a1);//debug
      }
      // else
      // {
      // m_shape._ReverseRingInternal(vertexA2);
      // _ResolveOverlapOddEven(bDirection1, !bDirection2, vertexA1,
      // vertexB1, vertexA2, vertexB2);
      // }
    }
  }
  private boolean _detectAndResolveCrossOver(
      boolean bDirection1,
      boolean bDirection2,
      int vertexB1,
      int vertexA1,
      int vertexC1,
      int vertexB2,
      int vertexA2,
      int vertexC2) {
    // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexB2));
    // _ASSERT(!m_shape.isEqualXY(vertexC1, vertexC2));

    if (vertexA1 == vertexA2) {
      _removeAngleSortInfo(vertexB1);
      _removeAngleSortInfo(vertexB2);
      return false;
    }

    // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexC2));
    // _ASSERT(!m_shape.isEqualXY(vertexB1, vertexC1));
    // _ASSERT(!m_shape.isEqualXY(vertexB2, vertexC2));
    // _ASSERT(!m_shape.isEqualXY(vertexB2, vertexC1));
    // _ASSERT(!m_shape.isEqualXY(vertexA1, vertexB1));
    // _ASSERT(!m_shape.isEqualXY(vertexA1, vertexC1));
    // _ASSERT(!m_shape.isEqualXY(vertexA2, vertexB2));
    // _ASSERT(!m_shape.isEqualXY(vertexA2, vertexC2));

    // _ASSERT(m_shape.isEqualXY(vertexA1, vertexA2));

    // get indices of the vertices for the angle sort.
    int iB1 = m_shape.getUserIndex(vertexB1, m_userIndexSortedAngleIndexToVertex);
    int iC1 = m_shape.getUserIndex(vertexC1, m_userIndexSortedAngleIndexToVertex);
    int iB2 = m_shape.getUserIndex(vertexB2, m_userIndexSortedAngleIndexToVertex);
    int iC2 = m_shape.getUserIndex(vertexC2, m_userIndexSortedAngleIndexToVertex);
    // _ASSERT(iB1 >= 0);
    // _ASSERT(iC1 >= 0);
    // _ASSERT(iB2 >= 0);
    // _ASSERT(iC2 >= 0);
    // Sort the indices to restore the angle-sort order
    int[] ar = new int[8];
    int[] br = new int[4];

    ar[0] = 0;
    br[0] = iB1;
    ar[1] = 0;
    br[1] = iC1;
    ar[2] = 1;
    br[2] = iB2;
    ar[3] = 1;
    br[3] = iC2;
    for (int j = 1; j < 4; j++) // insertion sort
    {
      int key = br[j];
      int data = ar[j];
      int i = j - 1;
      while (i >= 0 && br[i] > key) {
        br[i + 1] = br[i];
        ar[i + 1] = ar[i];
        i--;
      }
      br[i + 1] = key;
      ar[i + 1] = data;
    }

    int detector = 0;
    if (ar[0] != 0) detector |= 1;
    if (ar[1] != 0) detector |= 2;
    if (ar[2] != 0) detector |= 4;
    if (ar[3] != 0) detector |= 8;
    if (detector != 5 && detector != 10) // not an overlap
    return false;

    if (bDirection1 == bDirection2) {
      if (bDirection1) {
        m_shape.setNextVertex_(vertexC2, vertexA1); // B1< >B2
        m_shape.setPrevVertex_(vertexA1, vertexC2); // \ /
        m_shape.setNextVertex_(vertexC1, vertexA2); // A1A2
        m_shape.setPrevVertex_(vertexA2, vertexC1); // / \ //
        // C2> <C1
      } else {
        m_shape.setPrevVertex_(vertexC2, vertexA1); // B1> <B2
        m_shape.setNextVertex_(vertexA1, vertexC2); // \ /
        m_shape.setPrevVertex_(vertexC1, vertexA2); // A1A2
        m_shape.setNextVertex_(vertexA2, vertexC1); // / \ //
        // C2< >C1
      }
    } else {
      if (bDirection1) {
        m_shape.setPrevVertex_(vertexA1, vertexB2); // B1< <B2
        m_shape.setNextVertex_(vertexB2, vertexA1); // \ /
        m_shape.setPrevVertex_(vertexA2, vertexC1); // A1A2
        m_shape.setNextVertex_(vertexC1, vertexA2); // / \ //
        // C2< <C1

      } else {
        m_shape.setNextVertex_(vertexA1, vertexB2); // B1> >B2
        m_shape.setPrevVertex_(vertexB2, vertexA1); // \ /
        m_shape.setNextVertex_(vertexA2, vertexC1); // A1A2
        m_shape.setPrevVertex_(vertexC1, vertexA2); // / \ //
        // C2> >C1

      }
    }

    return true;
  }