private void _beforeRemoveVertex(int vertex, boolean bChangePathFirst) {
    int vertexlistIndex = m_shape.getUserIndex(vertex, m_userIndexSortedIndexToVertex);
    // _ASSERT(m_sortedVertices.getData(vertexlistIndex) != 0xdeadbeef);
    if (m_nextVertexToProcess == vertexlistIndex) {
      m_nextVertexToProcess = m_sortedVertices.getNext(m_nextVertexToProcess);
    }

    if (m_firstCoincidentVertex == vertexlistIndex)
      m_firstCoincidentVertex = m_sortedVertices.getNext(m_firstCoincidentVertex);

    m_sortedVertices.deleteElement(m_sortedVerticesListIndex, vertexlistIndex);
    _removeAngleSortInfo(vertex);
    if (bChangePathFirst) {
      int path = m_shape.getPathFromVertex(vertex);
      if (path != -1) {
        int first = m_shape.getFirstVertex(path);
        if (first == vertex) {
          int next = m_shape.getNextVertex(vertex);
          if (next != vertex) m_shape.setFirstVertex_(path, next);
          else {
            m_shape.setFirstVertex_(path, -1);
            m_shape.setLastVertex_(path, -1);
          }
        }
      }
    }
  }
  private void _fixOrphanVertices() {
    int pathCount = 0;
    // clean any path info
    for (int node = m_sortedVertices.getFirst(m_sortedVertices.getFirstList());
        node != -1;
        node = m_sortedVertices.getNext(node)) {
      int vertex = m_sortedVertices.getData(node);
      m_shape.setPathToVertex_(vertex, -1);
    }
    int geometrySize = 0;
    for (int path = m_shape.getFirstPath(m_geometry); path != -1; ) {
      int first = m_shape.getFirstVertex(path);
      if (first == -1 || m_shape.getPathFromVertex(first) != -1) {
        int p = path;
        path = m_shape.getNextPath(path);
        m_shape.removePathOnly_(p);
        continue;
      }

      m_shape.setPathToVertex_(first, path);
      int pathSize = 1;
      for (int vertex = m_shape.getNextVertex(first);
          vertex != first;
          vertex = m_shape.getNextVertex(vertex)) {
        // _ASSERT(m_shape.getPathFromVertex(vertex) == -1);
        m_shape.setPathToVertex_(vertex, path);
        // _ASSERT(m_shape.getNextVertex(m_shape.getPrevVertex(vertex))
        // == vertex);
        pathSize++;
      }
      m_shape.setPathSize_(path, pathSize);
      m_shape.setLastVertex_(path, m_shape.getPrevVertex(first));
      geometrySize += pathSize;
      pathCount++;
      path = m_shape.getNextPath(path);
    }

    // produce new paths for the orphan vertices.
    for (int node = m_sortedVertices.getFirst(m_sortedVertices.getFirstList());
        node != -1;
        node = m_sortedVertices.getNext(node)) {
      int vertex = m_sortedVertices.getData(node);
      if (m_shape.getPathFromVertex(vertex) != -1) continue;
      int path = m_shape.insertPath(m_geometry, -1);
      int pathSize = 0;
      int first = vertex;
      while (true) {
        m_shape.setPathToVertex_(vertex, path);
        pathSize++;
        int next = m_shape.getNextVertex(vertex);
        // _ASSERT(m_shape.getNextVertex(m_shape.getPrevVertex(vertex))
        // == vertex);
        if (next == first) break;
        vertex = next;
      }

      m_shape.setClosedPath(path, true);

      m_shape.setPathSize_(path, pathSize);
      m_shape.setFirstVertex_(path, first);
      m_shape.setLastVertex_(path, m_shape.getPrevVertex(first));
      geometrySize += pathSize;
      pathCount++;
    }
    m_shape.setGeometryPathCount_(m_geometry, pathCount);
    int totalPointCount = m_shape.getTotalPointCount() - m_shape.getPointCount(m_geometry);
    m_shape.setGeometryVertexCount_(m_geometry, geometrySize);
    m_shape.setTotalPointCount_(totalPointCount + geometrySize);
  }