Exemple #1
0
  _TMESH_TMPL_TYPE
  VOID _TMESH_TMPL_DECL::GetFacetVertices(iFACET facetIndex, eCOORD coord, REAL coordVal, iVERTEX v[2])
  {

    cHALF_EDGE* facetHes[2] = { NULL, NULL };
    BOOL verticesAreNew[2] = { false, false };

    cHALF_EDGE *startingHe = Facet(facetIndex)->FindMinHalfEdge(coord);
    cHALF_EDGE *currHe = startingHe;

    INT i = 0;
    do {
      cPOINT3 tailPoint = currHe->Tail()->Point();
      cPOINT3 headPoint = currHe->Head()->Point();

      REAL heTailCoord = tailPoint[coord];
      REAL heHeadCoord = headPoint[coord];

      REAL diff1 = coordVal - heTailCoord;
      REAL diff2 = heHeadCoord - coordVal;

      if(fabs(diff2) < cLIMITS::Tolerance()) {
	currHe = currHe->Next();
	continue;
      }

      if(fabs(diff1) < cLIMITS::Tolerance())
	v[i++] = currHe->Tail()->Index();
      else if(diff1 * diff2 > 0.0) {
	cPOINT3 newPoint = ((tailPoint*diff2) + (headPoint*diff1))/(diff1+diff2);
	v[i++] = NewVertex(newPoint);
	facetHes[i-1] = currHe;
	verticesAreNew[i-1] = true;
      }

      if(i == 2) break;

      currHe = currHe->Next();
    } while( currHe != startingHe);

    if(verticesAreNew[0])
      SplitEdge(v[0], facetHes[0]->Tail()->Index(),
		facetHes[0]->Head()->Index());

    if(verticesAreNew[1])
      SplitEdge(v[1], facetHes[1]->Tail()->Index(),
		facetHes[1]->Head()->Index());
  }
vector<SplitEdge> split(const vector<SplitEdge> &g, int u, int v, int s, int delta, historyIndex &h)
{
	vector<SplitEdge> GHat = g;
	bool addedWeight = false;
	bool subtractedU = false;
	bool subtractedV = false;
	//cout << endl;
	for (unsigned i = 0; i < GHat.size(); i++)
	{
		if (connects(GHat[i], u, v))
		{
			//cout << "Increasing the weight from " << u << " to " << v << " from " << GHat[i].weight << " to " << GHat[i].weight + delta << endl;
			GHat[i].weight += delta;
			addedWeight = true;
		}
		if (connects(GHat[i], u, s) && !subtractedU)
		{
			//cout << "Decreasing the weight from " << u << " to " << s << " from " << GHat[i].weight << " to " << GHat[i].weight - delta << endl;
			GHat[i].weight -= delta;
			subtractedU = true;
		}
		if (connects(GHat[i], s, v) && !subtractedV)
		{
			//cout << "Decreasing the weight from " << v << " to " << s << " from " << GHat[i].weight << " to " << GHat[i].weight - delta << endl;
			GHat[i].weight -= delta;
			subtractedV = true;
		}
	}
	if (!addedWeight)
	{
		SplitEdge e = SplitEdge(u, v, delta, u, v);
		//cout << "Creating edge from " << u << " to " << v << " with weight " << delta << endl;
		GHat.push_back(e);
	}
	if (!subtractedU)
	{
		cout << "Error: Couldn't find weight from " << u << " to " << s << " to subtract." << endl;
		throw logic_error("");
	}
	if (!subtractedV)
	{
		cout << "Error: Couldn't find weight from " << v << " to " << s << " to subtract." << endl;
		throw logic_error("");
	}
	//cout << endl;
	GHat = removeZeroWeighted(GHat);
	logSplit(h, s, u, v, delta);
	return GHat;
}
Exemple #3
0
void IntersectionProcessor::ProcessIntersection(
    const OpsDoublePoint &intersectionPt, WingedEdgeArray &edges)
{
    // loop through the edges generating an EdgeRecord for each of them

    m_nEdgeRecs = 0;

    for (int i = 0; i < edges.GetNEdges(); i++) {
        // if the intersection point is one of the edge endpoints, then
        // just add it

        if (intersectionPt == *edges[i]->m_vert[0])
            AddEdgeRecord(edges[i], 0);
        else if (intersectionPt == *edges[i]->m_vert[1])
            AddEdgeRecord(edges[i], 1);

        // else split the edge and add the two resulting edges

        else {
            WingedEdge *newEdge;
            SplitEdge(intersectionPt, edges[i], newEdge);
            AddEdgeRecord(edges[i], 0);
            AddEdgeRecord(newEdge, 1);
        }
    }

    // if more than two edge records, or the edges are coincident then sort
    // them into polar order before joining them about the intersection point

    if (m_nEdgeRecs > 2 || EdgesCoincident(edges[0], edges[1])) {
        SortEdges();
        JoinEdges(intersectionPt);
    }

    // else must have two non-coincident edges joined at a common endpoint -
    // handle this case directly since it occurs frequently

    else
        edges[0]->Join(edges[1], &intersectionPt);

#if defined _DEBUG
    if (traceFile != NULL)
        TraceIntersection(intersectionPt);
#endif

} // end: ProcessIntersection()
Exemple #4
0
_Use_decl_annotations_
void KdTreeCompiler2::SplitTriangle(uint32_t triangle, uint32_t axis, float value, uint32_t* front, uint32_t* back)
{
    KdCompilerTriangle* t = &_compilerTriangles[triangle];

    // Make copies since if we grow the StaticGeometryVertex list while processing, we don't want to end up with bunk pointers
    StaticGeometryVertex v0 = _vertices[t->Indices[0]];
    StaticGeometryVertex v1 = _vertices[t->Indices[1]];
    StaticGeometryVertex v2 = _vertices[t->Indices[2]];

    // are any of the points on the plane
    float d0 = *(&v0.Position.x + axis) - value;
    float d1 = *(&v1.Position.x + axis) - value;
    float d2 = *(&v2.Position.x + axis) - value;

    if (fabsf(d0) < epsilon)
    {
        // v0 is on plane, split v1-v2 edge
        StaticGeometryVertex vNew;
        SplitEdge(v1, v2, axis, value, &vNew);

        uint32_t iNew = (uint32_t)_vertices.size();
        _vertices.push_back(vNew);

        uint32_t t1 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], t->Indices[1], iNew);
        uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], iNew, t->Indices[2]);

        if (d1 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else if (fabsf(d1) < epsilon)
    {
        // v1 is on plane
        StaticGeometryVertex vNew;
        SplitEdge(v0, v2, axis, value, &vNew);

        uint32_t iNew = (uint32_t)_vertices.size();
        _vertices.push_back(vNew);

        uint32_t t1 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], t->Indices[1], iNew);
        uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[1], t->Indices[2], iNew);

        if (d0 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else if (fabsf(d2) < epsilon)
    {
        // v2 is on plane
        StaticGeometryVertex vNew;
        SplitEdge(v0, v1, axis, value, &vNew);

        uint32_t iNew = (uint32_t)_vertices.size();
        _vertices.push_back(vNew);

        uint32_t t1 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], iNew, t->Indices[2]);
        uint32_t t2 = AllocCompilerTriangle(_vertices.data(), iNew, t->Indices[1], t->Indices[2]);

        if (d0 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else
    {
        // none are on the plane, do a 1-2 split
        if (d0 > -epsilon) // v0 is in front of plane
        {
            if (d1 > -epsilon) // v1 is in front of plane
            {
                // v2 is by itself
                StaticGeometryVertex vNew1, vNew2;
                SplitEdge(v2, v0, axis, value, &vNew1);
                SplitEdge(v2, v1, axis, value, &vNew2);

                uint32_t iNew1 = (uint32_t)_vertices.size();
                _vertices.push_back(vNew1);

                uint32_t iNew2 = (uint32_t)_vertices.size();
                _vertices.push_back(vNew2);

                uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[2]);
                uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], t->Indices[1], iNew2);
                uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], iNew2, iNew1);

                PUSH(front, t2);
                PUSH(front, t3);
                PUSH(back, t1);
            }
            else // v1 is behind plane
            {
                if (d2 > -epsilon)  // v2 is in front
                {
                    // v1 is by itself
                    StaticGeometryVertex vNew1, vNew2;
                    SplitEdge(v1, v2, axis, value, &vNew1);
                    SplitEdge(v1, v0, axis, value, &vNew2);

                    uint32_t iNew1 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew1);

                    uint32_t iNew2 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew2);

                    uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[1]);
                    uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[2], t->Indices[0], iNew2);
                    uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[2], iNew2, iNew1);

                    PUSH(front, t2);
                    PUSH(front, t3);
                    PUSH(back, t1);
                }
                else // v2 is behind
                {
                    // v0 is by itself
                    StaticGeometryVertex vNew1, vNew2;
                    SplitEdge(v0, v1, axis, value, &vNew1);
                    SplitEdge(v0, v2, axis, value, &vNew2);

                    uint32_t iNew1 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew1);

                    uint32_t iNew2 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew2);

                    uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[0]);
                    uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[1], t->Indices[2], iNew2);
                    uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[1], iNew2, iNew1);

                    PUSH(back, t2);
                    PUSH(back, t3);
                    PUSH(front, t1);
                }
            }
        }
        else // v0 is behind plane
        {
            if (d1 < epsilon)  // v1 is behind
            {
                // v2 is by itself
                StaticGeometryVertex vNew1, vNew2;
                SplitEdge(v2, v0, axis, value, &vNew1);
                SplitEdge(v2, v1, axis, value, &vNew2);

                uint32_t iNew1 = (uint32_t)_vertices.size();
                _vertices.push_back(vNew1);

                uint32_t iNew2 = (uint32_t)_vertices.size();
                _vertices.push_back(vNew2);

                uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[2]);
                uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], t->Indices[1], iNew2);
                uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[0], iNew2, iNew1);

                PUSH(back, t2);
                PUSH(back, t3);
                PUSH(front, t1);
            }
            else // v1 is in front
            {
                if (d2 < epsilon) // v2 is behind
                {
                    // v1 is by itself
                    StaticGeometryVertex vNew1, vNew2;
                    SplitEdge(v1, v2, axis, value, &vNew1);
                    SplitEdge(v1, v0, axis, value, &vNew2);

                    uint32_t iNew1 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew1);

                    uint32_t iNew2 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew2);

                    uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[1]);
                    uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[2], t->Indices[0], iNew2);
                    uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[2], iNew2, iNew1);

                    PUSH(back, t2);
                    PUSH(back, t3);
                    PUSH(front, t1);
                }
                else
                {
                    // v0 is by itself
                    StaticGeometryVertex vNew1, vNew2;
                    SplitEdge(v0, v1, axis, value, &vNew1);
                    SplitEdge(v0, v2, axis, value, &vNew2);

                    uint32_t iNew1 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew1);

                    uint32_t iNew2 = (uint32_t)_vertices.size();
                    _vertices.push_back(vNew2);

                    uint32_t t1 = AllocCompilerTriangle(_vertices.data(), iNew1, iNew2, t->Indices[0]);
                    uint32_t t2 = AllocCompilerTriangle(_vertices.data(), t->Indices[1], t->Indices[2], iNew2);
                    uint32_t t3 = AllocCompilerTriangle(_vertices.data(), t->Indices[1], iNew2, iNew1);

                    PUSH(front, t2);
                    PUSH(front, t3);
                    PUSH(back, t1);
                }
            }
        }
    }
}
_Use_decl_annotations_
void BspCompiler::SplitTriangle(const Triangle* t, const XMFLOAT4& plane, Triangle** front, Triangle** back)
{
    // are any of the points on the plane
    float d0 = DistToPlane(plane, t->v0.Position);
    float d1 = DistToPlane(plane, t->v1.Position);
    float d2 = DistToPlane(plane, t->v2.Position);

    if (ABS(d0) < epsilon)
    {
        // v0 is on plane, split v1-v2 edge
        Vertex vNew;
        SplitEdge(t->v1, t->v2, plane, &vNew);

        Triangle* t1 = new Triangle(t->v0, t->v1, vNew);
        Triangle* t2 = new Triangle(t->v0, vNew, t->v2);

        if (d1 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else if (ABS(d1) < epsilon)
    {
        // v1 is on plane
        Vertex vNew;
        SplitEdge(t->v0, t->v2, plane, &vNew);

        Triangle* t1 = new Triangle(t->v0, t->v1, vNew);
        Triangle* t2 = new Triangle(t->v1, t->v2, vNew);

        if (d0 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else if (ABS(d2) < epsilon)
    {
        // v2 is on plane
        Vertex vNew;
        SplitEdge(t->v0, t->v1, plane, &vNew);

        Triangle* t1 = new Triangle(t->v0, vNew, t->v2);
        Triangle* t2 = new Triangle(vNew, t->v1, t->v2);

        if (d0 > 0)
        {
            PUSH(front, t1);
            PUSH(back, t2);
        }
        else
        {
            PUSH(back, t1);
            PUSH(front, t2);
        }
    }
    else
    {
        // none are on the plane, do a 1-2 split
        if (d0 > -epsilon) // v0 is in front of plane
        {
            if (d1 > -epsilon) // v1 is in front of plane
            {
                // v2 is by itself
                Vertex vNew1, vNew2;
                SplitEdge(t->v2, t->v0, plane, &vNew1);
                SplitEdge(t->v2, t->v1, plane, &vNew2);

                Triangle* t1 = new Triangle(vNew1, vNew2, t->v2);
                Triangle* t2 = new Triangle(t->v0, t->v1, vNew2);
                Triangle* t3 = new Triangle(t->v0, vNew2, vNew1);

                PUSH(front, t2);
                PUSH(front, t3);
                PUSH(back, t1);
            }
            else // v1 is behind plane
            {
                if (d2 > -epsilon)  // v2 is in front
                {
                    // v1 is by itself
                    Vertex vNew1, vNew2;
                    SplitEdge(t->v1, t->v2, plane, &vNew1);
                    SplitEdge(t->v1, t->v0, plane, &vNew2);

                    Triangle* t1 = new Triangle(vNew1, vNew2, t->v1);
                    Triangle* t2 = new Triangle(t->v2, t->v0, vNew2);
                    Triangle* t3 = new Triangle(t->v2, vNew2, vNew1);

                    PUSH(front, t2);
                    PUSH(front, t3);
                    PUSH(back, t1);
                }
                else // v2 is behind
                {
                    // v0 is by itself
                    Vertex vNew1, vNew2;
                    SplitEdge(t->v0, t->v1, plane, &vNew1);
                    SplitEdge(t->v0, t->v2, plane, &vNew2);

                    Triangle* t1 = new Triangle(vNew1, vNew2, t->v0);
                    Triangle* t2 = new Triangle(t->v1, t->v2, vNew2);
                    Triangle* t3 = new Triangle(t->v1, vNew2, vNew1);

                    PUSH(back, t2);
                    PUSH(back, t3);
                    PUSH(front, t1);
                }
            }
        }
        else // v0 is behind plane
        {
            if (d1 < epsilon)  // v1 is behind
            {
                // v2 is by itself
                Vertex vNew1, vNew2;
                SplitEdge(t->v2, t->v0, plane, &vNew1);
                SplitEdge(t->v2, t->v1, plane, &vNew2);

                Triangle* t1 = new Triangle(vNew1, vNew2, t->v2);
                Triangle* t2 = new Triangle(t->v0, t->v1, vNew2);
                Triangle* t3 = new Triangle(t->v0, vNew2, vNew1);

                PUSH(back, t2);
                PUSH(back, t3);
                PUSH(front, t1);
            }
            else // v1 is in front
            {
                if (d2 < epsilon) // v2 is behind
                {
                    // v1 is by itself
                    Vertex vNew1, vNew2;
                    SplitEdge(t->v1, t->v2, plane, &vNew1);
                    SplitEdge(t->v1, t->v0, plane, &vNew2);

                    Triangle* t1 = new Triangle(vNew1, vNew2, t->v1);
                    Triangle* t2 = new Triangle(t->v2, t->v0, vNew2);
                    Triangle* t3 = new Triangle(t->v2, vNew2, vNew1);

                    PUSH(back, t2);
                    PUSH(back, t3);
                    PUSH(front, t1);
                }
                else
                {
                    // v0 is by itself
                    Vertex vNew1, vNew2;
                    SplitEdge(t->v0, t->v1, plane, &vNew1);
                    SplitEdge(t->v0, t->v2, plane, &vNew2);

                    Triangle* t1 = new Triangle(vNew1, vNew2, t->v0);
                    Triangle* t2 = new Triangle(t->v1, t->v2, vNew2);
                    Triangle* t3 = new Triangle(t->v1, vNew2, vNew1);

                    PUSH(front, t2);
                    PUSH(front, t3);
                    PUSH(back, t1);
                }
            }
        }
    }
}
Exemple #6
0
  _TMESH_TMPL_TYPE
  iFACET _TMESH_TMPL_DECL::Clip(iFACET facetIndex, const cSEGMENT3 &cut)
  {
    cFACET* facet = Facet(facetIndex);

    if(facet == NULL || facet->IsDeleted())
      return INVALID_IFACET;

    iVERTEX cutVertices[2] = { INVALID_IVERTEX, INVALID_IVERTEX };
    BOOL insertCutVertices[2] = { false, false };
    cPOINT3 points[2];
    cEDGE splitEdges[2];

    const cPOINT3 &cutTail = cut.Source();
    const cPOINT3 &cutHead = cut.Target();

    typename cFACET::half_edge_circulator currFacetHe = facet->HalfEdgesBegin();
    typename cFACET::half_edge_circulator lastFacetHe = facet->HalfEdgesEnd();

    INT numCuts = 0;
    for( ; currFacetHe != lastFacetHe ; currFacetHe++) {
      cSEGMENT3 heSegment = currFacetHe->Segment();

      if(heSegment.HasOn(cutTail)) {
        if(!(heSegment.Target() == cutTail)) {
          if(heSegment.Source() == cutTail) {
            cutVertices[numCuts++] = currFacetHe->Tail()->Index();
          }
          else {
            insertCutVertices[numCuts] = true;

            splitEdges[numCuts].v1 = currFacetHe->Tail()->Index();
            splitEdges[numCuts].v2 = currFacetHe->Head()->Index();

            points[numCuts] = cutTail;
            numCuts++;
          }
        }
      }

      if(heSegment.HasOn(cutHead)) {
        if(!(heSegment.Target() == cutHead)) {
          if(heSegment.Source() == cutHead) {
            cutVertices[numCuts++] = currFacetHe->Tail()->Index();
          }
          else {
            insertCutVertices[numCuts] = true;

            splitEdges[numCuts].v1 = currFacetHe->Tail()->Index();
            splitEdges[numCuts].v2 = currFacetHe->Head()->Index();

            points[numCuts] = cutHead;
            numCuts++;
          }
        }
      }

      if(numCuts == 2)
        break;
    }

    //Cuts found.
    assert(numCuts == 2);
    if(numCuts != 2)
      return INVALID_IFACET;

    if(insertCutVertices[0]) {
      cutVertices[0] = NewVertex(points[0]);
      SplitEdge(cutVertices[0], splitEdges[0].v1, splitEdges[0].v2);
    }

    if(insertCutVertices[1]) {
      cutVertices[1] = NewVertex(points[1]);
      SplitEdge(cutVertices[1], splitEdges[1].v1, splitEdges[1].v2);
    }

    return InsertDiagonal(facetIndex, cutVertices[0], cutVertices[1]);
  }
Exemple #7
0
std::vector<c_vector<unsigned, 5> > MutableMesh<ELEMENT_DIM, SPACE_DIM>::SplitLongEdges(double cutoffLength)
{
    assert(ELEMENT_DIM == 2);
    assert(SPACE_DIM == 3);

    std::vector<c_vector<unsigned, 5> > history;


    bool long_edge_exists = true;

    while(long_edge_exists)
    {
        std::set<std::pair<unsigned, unsigned> > long_edges;

        // Loop over elements to check for Long edges
        for (typename AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>::ElementIterator elem_iter = this->GetElementIteratorBegin();
             elem_iter != this->GetElementIteratorEnd();
             ++elem_iter)
        {
            unsigned num_nodes = ELEMENT_DIM+1;

            // Loop over element vertices
            for (unsigned local_index=0; local_index<num_nodes; local_index++)
            {
                // Find locations of current node (node a) and anticlockwise node (node b)
                Node<SPACE_DIM>* p_node_a = elem_iter->GetNode(local_index);
                unsigned local_index_plus_one = (local_index+1)%num_nodes; /// \todo use iterators to tidy this up
                Node<SPACE_DIM>* p_node_b = elem_iter->GetNode(local_index_plus_one);

                // Find distance between nodes
                double distance_between_nodes = this->GetDistanceBetweenNodes(p_node_a->GetIndex(), p_node_b->GetIndex());

                if (distance_between_nodes > cutoffLength)
                {
                    if (p_node_a->GetIndex() < p_node_b->GetIndex())
                    {
                        std::pair<unsigned, unsigned> long_edge(p_node_a->GetIndex(),p_node_b->GetIndex());
                        long_edges.insert(long_edge);
                    }
                    else
                    {
                        std::pair<unsigned, unsigned> long_edge(p_node_b->GetIndex(),p_node_a->GetIndex());
                        long_edges.insert(long_edge);
                    }
                }
            }
        }

        if (long_edges.size() > 0) //Split the edges in decreasing order.
        {
            while (long_edges.size() > 0)
            {
                double longest_edge = 0.0;
                std::set<std::pair<unsigned, unsigned> >::iterator longest_edge_iter;

                //Find the longest edge in the set and split it
                for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = long_edges.begin();
                         edge_iter != long_edges.end();
                         ++edge_iter)
                {
                    unsigned node_a_global_index = edge_iter->first;
                    unsigned node_b_global_index = edge_iter->second;

                    double distance_between_nodes = this->GetDistanceBetweenNodes(node_a_global_index, node_b_global_index);

                    if (distance_between_nodes > longest_edge)
                    {
                        longest_edge = distance_between_nodes;
                        longest_edge_iter = edge_iter;
                    }
                }
                assert(longest_edge >0);

                c_vector<unsigned, 3> new_node_index = SplitEdge(this->GetNode(longest_edge_iter->first), this->GetNode(longest_edge_iter->second));

                c_vector<unsigned, 5> node_set;
                node_set(0) = new_node_index[0];
                node_set(1) = longest_edge_iter->first;
                node_set(2) = longest_edge_iter->second;
                node_set(3) = new_node_index[1];
                node_set(4) = new_node_index[2];
                history.push_back(node_set);

                // Delete pair from set
                long_edges.erase(*longest_edge_iter);
            }
        }
        else
        {
            long_edge_exists = false;
        }
    }

    return history;
}
huReturn hookUp(const vector<SplitEdge> &g, int s, vector<SplitEdge> &bIn, int k, vector<vector<int>> &Y, historyIndex &h)
{
	if (cG(s, g) != 0)
	{
		cout << "cG(s) problem in hookup" << endl;
		throw logic_error("");
	}
	vector<SplitEdge> H = g;
	vector<SplitEdge> G1 = g; 
	vector<SplitEdge> B = bIn;
	vector<SplitEdge> B1;
	vector<vector<int>> XS;
	int maxNodeInd = getMaxNodeInd(G1);
	for (int i = 0; i < maxNodeInd; i++)
		XS.push_back(vector<int>());
	for (int i = 0; i < maxNodeInd; i++)
		XS[i].push_back(i);
	//cout << "About to enter while loop" << endl;
	while (getNumUsedNodes(H) >= 4)
	{
		vector<int> ma = maOrderingHeap(H, s);
		int v = ma[ma.size() - 2];
		int w = ma[ma.size() - 1];
		if (v == s || w == s)
			throw logic_error("SET WAS V - S, S FOUND");
		vector<int> X1;
		H = combineVertices(H, v, w);
		H = compress(H);
		XS[v] = setUnion(XS[v], XS[w]);
		if (XS[w].size() == 0)
		{
			cout << "Error: W, " << w << " was merged twice. Quitting" << endl;
			throw logic_error("");
		}
		XS[w] = vector<int>();
		if (cG(v, H) < k)
		{
			int numToGet = (int)ceil(.5*(double(k) - double(cG(G1, XS[v]))));
			vector<SplitEdge> GX = inducedSubgraph(G1, XS[v]);
			vector<SplitEdge> delB;
			int added = 0;
			for (unsigned i = 0; i < GX.size(); i++)
			{
				SplitEdge e = SplitEdge(GX[i].end0, GX[i].end1, GX[i].weight, GX[i].orig0, GX[i].orig1);
				if (isMem(e, B))
				{
					int bW = B[indexOfEdge(B, e.end0, e.end1)].weight;
					if (bW < e.weight)
						e.weight = bW;
					if (e.weight > (numToGet - added))
					{
						e.weight = numToGet - added;
					}
					added += e.weight;
					delB.push_back(e);
				}
				if (added == numToGet)
					break;
			}
			if (added != numToGet)
			{
				cout << "Error: GX did not contain " << numToGet << " entries in B. Quitting." << endl;
				throw logic_error("");
			}
			if (!isSubset(delB, B))
			{
				cout << "ERROR: delB is not a subset of B." << endl;
				cout << "B:" << endl;
				output(B);
				cout << "delB:" << endl;
				output(delB);
				cout << "This was the GX to choose from:" << endl;
				output(GX);
				cout << "V: " << v << endl;
				cout << "W: " << w << endl;
				cout << "S: " << s << endl;
				throw logic_error("");
			}
			B = setRemove(delB, B);
			B = removeZeroWeighted(B);
			B1 = setUnion(delB, B1);
			H = removeZeroWeighted(H);
			G1 = hookUpHelper(s, G1, delB, h);
			G1 = removeZeroWeighted(G1);
			H = removeZeroWeighted(H);
			bool addedFromXSinH = false;
			numToGet *= 2;
			for (unsigned i = 0; i < H.size(); i++)
			{
				SplitEdge tester = SplitEdge(s, v, 0, 0, 0);
				if (equals(tester, H[i]))
				{
					//cout << "Increasing weight in hookUp in H between " << H[i].end0 << " and " << H[i].end1 << "from " << H[i].weight << " to " << H[i].weight + numToGet << endl;
					H[i].weight += numToGet;
					addedFromXSinH = true;
					break;
				}
			}
			if (!addedFromXSinH && numToGet != 0)
			{
				//cout << "Creating edge in hookUp in H between " << s << " and " << v << " with weight " << numToGet << endl;
				SplitEdge e(s, v, numToGet, s, v);
				H.push_back(e);
			}
			vector<vector<int>> newY;
			for (unsigned i = 0; i < Y.size(); i++)
			{
				if (!isProperSubset(Y[i], XS[v]))
					newY.push_back(Y[i]);
			}
			bool foundX1inY = false;
			for (unsigned i = 0; i < newY.size(); i++)
			{
				if (setsEqual(newY[i], XS[v]))
					foundX1inY = true;
			}
			if (!foundX1inY)
				newY.push_back(XS[v]);
			Y = newY;
		}
	}
	huReturn ret;
	ret.BP = B1;
	ret.G1 = G1;
	ret.Y = Y;
	return ret;
}
bool ON_Brep::SplitKinkyEdge( 
  int edge_index, 
  double kink_tol_radians
  )
{
  // Default kink_tol_radians MUST BE ON_PI/180.0.
  //
  // The default kink tol must be kept in sync with the default for 
  // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace().
  // See comments in TL_Brep::SplitKinkyFace() for more details.

  bool rc = true;
  if (kink_tol_radians < ON_ZERO_TOLERANCE) 
    kink_tol_radians = ON_ZERO_TOLERANCE;
  else if (kink_tol_radians > ON_PI - ON_ZERO_TOLERANCE) 
    kink_tol_radians = ON_PI - ON_ZERO_TOLERANCE;
  double atol = cos(kink_tol_radians);
  if (edge_index < 0 || edge_index >= m_E.Count()) 
    return false;
  ON_BrepEdge& E = m_E[edge_index];
  if (E.m_c3i < 0) 
    return false;
  ON_SimpleArray<double> split_t(4);
  double t0 = E.Domain()[0];
  int hint = 0;
  ON_Curve* curve = m_C3[E.m_c3i];
  if (!curve) return false;
  int scount = curve->SpanCount();
  while (split_t.Count() < scount){
    double t;
    if (!E.GetNextDiscontinuity(ON::G1_continuous, t0, E.Domain()[1], 
      &t, &hint, NULL, atol)) break;
    split_t.Append(t);
    t0 = t;
  }
  if (split_t.Count() >= scount) 
    return false;

  if (split_t.Count() == 0) 
    return true;//no kinks

  split_t.Reverse();
  for (int i=0; i<split_t.Count(); i++){
    //if split parameter is near start or end, just adjust domain.
    double t0, t1;
    m_E[edge_index].GetDomain(&t0, &t1);
    if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) continue;

    //6 Dec 2002 Dale Lear:
    //   I added the relative edge_split_s and trm_split_s tests to detect
    //   attempts to trim a nano-gnats-wisker of the end of a trim.

    // set to true if edge should be trimmed instead of split.
    bool bTrimEdgeEnd = false; 

    double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]);
    double trim_split_s = 0.5;

    if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON )
    {
      continue;
    }
    if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON)
    {
      continue;
    }

    // trim_t[] = corresponding trim parameters
    ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count());


    if ( !bTrimEdgeEnd )
    {
      for (int j=0; j<m_E[edge_index].m_ti.Count(); j++)
      {
        double t;
        if (!GetTrimParameter(m_E[edge_index].m_ti[j], split_t[i], &t)){
          rc = false;
          continue;
        }
        trim_t.Append(t);
        const ON_BrepTrim& trim = m_T[m_E[edge_index].m_ti[j]];
        ON_Interval trim_domain = trim.Domain();
        trim_split_s = trim_domain.NormalizedParameterAt(t);
        if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE )
        {
          bTrimEdgeEnd = true;
          break;
        }
        if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE )
        {
          bTrimEdgeEnd = true;
          break;
        }
      }
    }

    if ( bTrimEdgeEnd )
    {
      // if we get here, a split parameter we got was too close to
      // the end of the edge or a trim for us to split it.
      if ( edge_split_s <= 0.01 )
      {
        if ( t0 < split_t[i] )
          m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(split_t[i], t1));
      }
      else if ( edge_split_s >= 0.99 )
      {
        if ( split_t[i] < t1 )
          m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(t0, split_t[i]));
      }
      else
      {
        // no decent agreement between trims and edges - continue
        // with other parameters but this is basically the same
        // thing as having SplitEdge() fail.
        rc = false;
      }

      continue;
    }

    if (!SplitEdge(edge_index, split_t[i], trim_t)){
      rc = false;
      continue;
    }
    ON_Curve* new_curve0 = m_E[edge_index].DuplicateCurve();
    if (new_curve0){
      m_E[edge_index].m_c3i = AddEdgeCurve(new_curve0);
      m_E[edge_index].SetProxyCurve(new_curve0);
    }
    ON_Curve* new_curve1 = m_E.Last()->DuplicateCurve();
    if (new_curve1){
      m_E.Last()->m_c3i = AddEdgeCurve(new_curve1);
      m_E.Last()->SetProxyCurve(new_curve1);
    }
  }

  return rc;
}
int ON_Brep::SplitEdgeAtParameters(
  int edge_index,
  int edge_t_count,
  const double* edge_t
  )
{
  // Default kink_tol_radians MUST BE ON_PI/180.0.
  //
  // The default kink tol must be kept in sync with the default for 
  // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace().
  // See comments in TL_Brep::SplitKinkyFace() for more details.

  if (0 == edge_t_count)
    return 0;
  if (0 == edge_t)
    return 0;
  if (edge_index < 0 || edge_index >= m_E.Count()) 
    return 0;
  ON_BrepEdge& E = m_E[edge_index];
  if (E.m_c3i < 0) 
    return 0;
  ON_Curve* curve = m_C3[E.m_c3i];
  if (!curve) 
    return 0;

  ON_Interval Edomain;
  if ( !E.GetDomain(&Edomain.m_t[0],&Edomain.m_t[1]) )
    return 0;
  if ( !Edomain.IsIncreasing() )
    return 0;

  // get a list of unique and valid splitting parameters
  ON_SimpleArray<double> split_t(edge_t_count);
  {
    for (int i = 0; i < edge_t_count; i++)
    {
      double e = edge_t[i];
      if ( !ON_IsValid(e) )
      {
        ON_ERROR("Invalid edge_t[] value");
        continue;
      }
      if ( e <= Edomain.m_t[0] )
      {
        ON_ERROR("edge_t[] <= start of edge domain");
        continue;
      }
      if ( e >= Edomain.m_t[1] )
      {
        ON_ERROR("edge_t[] >= end of edge domain");
        continue;
      }
      split_t.Append(e);
    }
    if ( split_t.Count() > 1 )
    {
      // sort split_t[] and remove duplicates
      ON_SortDoubleArray( ON::heap_sort, split_t.Array(), split_t.Count() );
      int count = 1;
      for ( int i = 1; i < split_t.Count(); i++ )
      {
        if ( split_t[i] > split_t[count-1] )
        {
          if ( i > count )
            split_t[count] = split_t[i];
          count++;
        }
      }
      split_t.SetCount(count);
    }
  }

  if (split_t.Count() <= 0) 
    return 0;

  // Reverse split_t[] so the starting segment of the original
  // edge m_E[edge_index] is the one at m_E[edge_index].
  split_t.Reverse();

  ON_Curve* new_curve = TuneupSplitteeHelper(m_E[edge_index].ProxyCurve());
  if ( 0 != new_curve )
  {
    m_E[edge_index].m_c3i = AddEdgeCurve(new_curve);
    m_E[edge_index].SetProxyCurve(new_curve);
    new_curve = 0;
  }

  int eti, ti;
  int successful_split_count = 0;
  for (int i=0; i<split_t.Count(); i++)
  {
    double t0, t1;
    m_E[edge_index].GetDomain(&t0, &t1);
    if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) 
      break;

    //6 Dec 2002 Dale Lear:
    //   I added the relative edge_split_s and trm_split_s tests to detect
    //   attempts to trim a nano-gnats-wisker off the end of a trim.
    double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]);
    double trim_split_s = 0.5;

    if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON )
    {
      // this split is not possible
      continue;
    }
    
    if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON)
    {
      // this split is not possible
      continue;
    }

    // trim_t[] = corresponding trim parameters
    ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count());

    for ( eti = 0; eti < m_E[edge_index].m_ti.Count(); eti++)
    {
      ti = m_E[edge_index].m_ti[eti];
      if ( ti < 0 || ti >= m_T.Count() )
        continue;
      ON_BrepTrim& trim = m_T[ti];
      if ( 0 == i )
      {
        // On the first split, make sure the trim curve is up to snuff.
        new_curve = TuneupSplitteeHelper(trim.ProxyCurve());
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
          new_curve = 0;
        }
      }
      double t = ON_UNSET_VALUE;
      if (!GetTrimParameter(ti, split_t[i], &t) || !ON_IsValid(t))
        break;
      trim_t.Append(t);
      const ON_Interval trim_domain = trim.Domain();
      trim_split_s = trim_domain.NormalizedParameterAt(t);
      if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE )
        break;

      if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE )
        break;
    }

    if ( trim_t.Count() != m_E[edge_index].m_ti.Count() )
      continue;

    if (!SplitEdge(edge_index, split_t[i], trim_t))
    {
      continue;
    }

    // SplitEdge generally adjusts proxy domains instead
    // of trimming the orginal curve. These DuplicateCurve()
    // calls make a new curve whose domain exactly matches
    // the edge.
    for ( int epart = 0; epart < 2; epart++ )
    {
      ON_BrepEdge* newE = (0 == epart) ? &m_E[edge_index] : m_E.Last();
      if ( 0 == newE )
        continue;
      new_curve = TuneupEdgeOrTrimRealCurve(*newE,true);
      if (new_curve)
      {
        newE->m_c3i = AddEdgeCurve(new_curve);
        newE->SetProxyCurve(new_curve);
      }
      for ( eti = 0; eti < newE->m_ti.Count(); eti++ )
      {
        ti = newE->m_ti[eti];
        if ( ti < 0 || ti >= m_T.Count() )
          continue;
        ON_BrepTrim& trim = m_T[ti];
        new_curve = TuneupEdgeOrTrimRealCurve(trim,false);
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
        }
      }
    }

    successful_split_count++;
  }

  return successful_split_count;
}