static typename DerivedF::Scalar  add_vertex(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &values,
                                              const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 3> &points,
                                              unsigned int i0,
                                              unsigned int i1,
                                              PointMatrixType &vertices,
                                              int &num_vertices,
                                              MyMap &edge2vertex)
 {
   // find vertex if it has been computed already
   MyMapIterator it = edge2vertex.find(EdgeKey(i0, i1));
   if (it != edge2vertex.end()) 
     return it->second;
   ;
   
   // generate new vertex
   const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p0 = points.row(i0);
   const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> & p1 = points.row(i1);
   
   typename DerivedV::Scalar s0 = fabs(values[i0]);
   typename DerivedV::Scalar s1 = fabs(values[i1]);
   typename DerivedV::Scalar t  = s0 / (s0+s1);
   
   
   num_vertices++;
   if (num_vertices > vertices.rows())
     vertices.conservativeResize(vertices.rows()+10000, Eigen::NoChange);
   
   vertices.row(num_vertices-1)  = (1.0f-t)*p0 + t*p1;
   edge2vertex[EdgeKey(i0, i1)] = num_vertices-1;
   
   return num_vertices-1;
 }
Beispiel #2
0
//----------------------------------------------------------------------------
void PartitionMesh::SplitTriangleMMP (std::vector<int>& negIndices,
    std::vector<int>& posIndices, int v0, int v1, int v2)
{
    int v12 = mEMap[EdgeKey(v1, v2)].second;
    int v20 = mEMap[EdgeKey(v2, v0)].second;
    negIndices.push_back(v0);
    negIndices.push_back(v1);
    negIndices.push_back(v12);
    negIndices.push_back(v0);
    negIndices.push_back(v12);
    negIndices.push_back(v20);
    posIndices.push_back(v2);
    posIndices.push_back(v20);
    posIndices.push_back(v12);
}
Beispiel #3
0
//----------------------------------------------------------------------------
void PartitionMesh::SplitTriangleMPZ (std::vector<int>& negIndices,
    std::vector<int>& posIndices, int v0, int v1, int v2)
{
    int v01 = mEMap[EdgeKey(v0, v1)].second;
    negIndices.push_back(v2);
    negIndices.push_back(v0);
    negIndices.push_back(v01);
    posIndices.push_back(v2);
    posIndices.push_back(v01);
    posIndices.push_back(v1);
}
 void PoissonReconstruction::SetConnectedComponents( const std::vector< std::vector< int > >& polygons , std::vector< std::vector< int > >& components )
 {
     std::vector< int > polygonRoots( polygons.size() );
     for( size_t i=0 ; i<polygons.size() ; i++ ) polygonRoots[i] = int(i);
     hash_map< long long , int > edgeTable;
     for( size_t i=0 ; i<polygons.size() ; i++ )
     {
         int sz = int( polygons[i].size() );
         for( int j=0 ; j<sz ; j++ )
         {
             int j1 = j , j2 = (j+1)%sz;
             int v1 = polygons[i][j1] , v2 = polygons[i][j2];
             long long eKey = EdgeKey( v1 , v2 );
             hash_map< long long , int >::iterator iter = edgeTable.find( eKey );
             if( iter==edgeTable.end() ) edgeTable[ eKey ] = int(i);
             else
             {
                 int p = iter->second;
                 while( polygonRoots[p]!=p )
                 {
                     int temp = polygonRoots[p];
                     polygonRoots[p] = int(i);
                     p = temp;
                 }
                 polygonRoots[p] = int(i);
             }
         }
     }
     for( size_t i=0 ; i<polygonRoots.size() ; i++ )
     {
         int p = int(i);
         while( polygonRoots[p]!=p ) p = polygonRoots[p];
         int root = p;
         p = int(i);
         while( polygonRoots[p]!=p )
         {
             int temp = polygonRoots[p];
             polygonRoots[p] = root;
             p = temp;
         }
     }
     int cCount = 0;
     hash_map< int , int > vMap;
     for( int i= 0 ; i<int(polygonRoots.size()) ; i++ ) if( polygonRoots[i]==i ) vMap[i] = cCount++;
     components.resize( cCount );
     for( int i=0 ; i<int(polygonRoots.size()) ; i++ ) components[ vMap[ polygonRoots[i] ] ].push_back(i);
 }
//--------------------------------------------------------------------------------------------------
/// Add mesh line indices by analyzing the triangle indices and only adding 'unique' edges
//--------------------------------------------------------------------------------------------------
void StructGridCutPlane::addMeshLineIndices(const uint* triangleIndices, uint triangleCount)
{
    std::vector<int64> edges;
    edges.reserve(3*triangleCount);

    std::vector<int64>::iterator it;

    uint t;
    for (t = 0; t < triangleCount; t++)
    {
        uint i;
        for (i = 0; i < 3; i++)
        {
            const uint vertexIdx1 = triangleIndices[3*t + i];
            const uint vertexIdx2 = (i < 2) ? triangleIndices[3*t + i + 1] : triangleIndices[3*t];

            int64 edgeKeyVal = EdgeKey(vertexIdx1, vertexIdx2).toKeyVal();
            it = find(edges.begin(), edges.end(), edgeKeyVal);
            if (it == edges.end())
            {
                edges.push_back(edgeKeyVal);
            }
            else
            {
                edges.erase(it);
            }
        }
    }

    for (it = edges.begin(); it != edges.end(); ++it)
    {
        EdgeKey ek = EdgeKey::fromkeyVal(*it);
        m_meshLineIndices.push_back(ek.index1());
        m_meshLineIndices.push_back(ek.index2());
    }
}
Beispiel #6
0
void BoxManager<Real>::Initialize ()
{
    // Get the box endpoints.
    int intrSize = (int)mBoxes->size(), endpSize = 2*intrSize;
    mXEndpoints.resize(endpSize);
    mYEndpoints.resize(endpSize);
    mZEndpoints.resize(endpSize);
    int i, j;
    for (i = 0, j = 0; i < intrSize; ++i)
    {
        mXEndpoints[j].Type = 0;
        mXEndpoints[j].Value = (*mBoxes)[i].Min[0];
        mXEndpoints[j].Index = i;
        mYEndpoints[j].Type = 0;
        mYEndpoints[j].Value = (*mBoxes)[i].Min[1];
        mYEndpoints[j].Index = i;
        mZEndpoints[j].Type = 0;
        mZEndpoints[j].Value = (*mBoxes)[i].Min[2];
        mZEndpoints[j].Index = i;
        j++;

        mXEndpoints[j].Type = 1;
        mXEndpoints[j].Value = (*mBoxes)[i].Max[0];
        mXEndpoints[j].Index = i;
        mYEndpoints[j].Type = 1;
        mYEndpoints[j].Value = (*mBoxes)[i].Max[1];
        mYEndpoints[j].Index = i;
        mZEndpoints[j].Type = 1;
        mZEndpoints[j].Value = (*mBoxes)[i].Max[2];
        mZEndpoints[j].Index = i;
        j++;
    }

    // Sort the rectangle endpoints.
    std::sort(mXEndpoints.begin(), mXEndpoints.end());
    std::sort(mYEndpoints.begin(), mYEndpoints.end());
    std::sort(mZEndpoints.begin(), mZEndpoints.end());

    // Create the interval-to-endpoint lookup tables.
    mXLookup.resize(endpSize);
    mYLookup.resize(endpSize);
    mZLookup.resize(endpSize);
    for (j = 0; j < endpSize; ++j)
    {
        mXLookup[2*mXEndpoints[j].Index + mXEndpoints[j].Type] = j;
        mYLookup[2*mYEndpoints[j].Index + mYEndpoints[j].Type] = j;
        mZLookup[2*mZEndpoints[j].Index + mZEndpoints[j].Type] = j;
    }

    // Active set of rectangles (stored by index in array).
    std::set<int> active;

    // set of overlapping rectangles (stored by pairs of indices in array)
    mOverlap.clear();

    // Sweep through the endpoints to determine overlapping x-intervals.
    for (i = 0; i < endpSize; ++i)
    {
        Endpoint& endpoint = mXEndpoints[i];
        int index = endpoint.Index;
        if (endpoint.Type == 0)  // an interval 'begin' value
        {
            // In the 1D problem, the current interval overlaps with all the
            // active intervals.  In 3D this we also need to check for
            // y-overlap and z-overlap.
            std::set<int>::iterator iter = active.begin();
            std::set<int>::iterator end = active.end();
            for (/**/; iter != end; ++iter)
            {
                // Rectangles activeIndex and index overlap in the
                // x-dimension.  Test for overlap in the y-dimension and
                // z-dimension.
                int activeIndex = *iter;
                const AxisAlignedBox3<Real>& b0 = (*mBoxes)[activeIndex];
                const AxisAlignedBox3<Real>& b1 = (*mBoxes)[index];
                if (b0.HasYOverlap(b1) && b0.HasZOverlap(b1))
                {
                    if (activeIndex < index)
                    {
                        mOverlap.insert(EdgeKey(activeIndex, index));
                    }
                    else
                    {
                        mOverlap.insert(EdgeKey(index, activeIndex));
                    }
                }
            }
            active.insert(index);
        }
        else  // an interval 'end' value
        {
            active.erase(index);
        }
    }
}
Beispiel #7
0
void BoxManager<Real>::InsertionSort (std::vector<Endpoint>& endpoint,
    std::vector<int>& lookup)
{
    // Apply an insertion sort.  Under the assumption that the rectangles
    // have not changed much since the last call, the endpoints are nearly
    // sorted.  The insertion sort should be very fast in this case.

    int endpSize = (int)endpoint.size();
    for (int j = 1; j < endpSize; ++j)
    {
        Endpoint key = endpoint[j];
        int i = j - 1;
        while (i >= 0 && key < endpoint[i])
        {
            Endpoint e0 = endpoint[i];
            Endpoint e1 = endpoint[i+1];

            // Update the overlap status.
            if (e0.Type == 0)
            {
                if (e1.Type == 1)
                {
                    // The 'b' of interval E0.mIndex was smaller than the 'e'
                    // of interval E1.mIndex, and the intervals *might have
                    // been* overlapping.  Now 'b' and 'e' are swapped, and
                    // the intervals cannot overlap.  Remove the pair from
                    // the overlap set.  The removal operation needs to find
                    // the pair and erase it if it exists.  Finding the pair
                    // is the expensive part of the operation, so there is no
                    // real time savings in testing for existence first, then
                    // deleting if it does.
                    mOverlap.erase(EdgeKey(e0.Index, e1.Index));
                }
            }
            else
            {
                if (e1.Type == 0)
                {
                    // The 'b' of interval E1.index was larger than the 'e'
                    // of interval E0.index, and the intervals were not
                    // overlapping.  Now 'b' and 'e' are swapped, and the
                    // intervals *might be* overlapping.  Determine if they
                    // are overlapping and then insert.
                    const AxisAlignedBox3<Real>& b0 = (*mBoxes)[e0.Index];
                    const AxisAlignedBox3<Real>& b1 = (*mBoxes)[e1.Index];
                    if (b0.TestIntersection(b1))
                    {
                        mOverlap.insert(EdgeKey(e0.Index, e1.Index));
                    }
                }
            }

            // Reorder the items to maintain the sorted list.
            endpoint[i] = e1;
            endpoint[i+1] = e0;
            lookup[2*e1.Index + e1.Type] = i;
            lookup[2*e0.Index + e0.Type] = i+1;
            i--;
        }
        endpoint[i+1] = key;
        lookup[2*key.Index + key.Type] = i+1;
    }
}
Beispiel #8
0
MinBox3<Real>::MinBox3 (int numPoints, const Vector3<Real>* points,
    Real epsilon, Query::Type queryType)
{
    // Get the convex hull of the points.
    ConvexHull3<Real> kHull(numPoints,(Vector3<Real>*)points, epsilon, false,
        queryType);
    int hullDim = kHull.GetDimension();

    if (hullDim == 0)
    {
        mMinBox.Center = points[0];
        mMinBox.Axis[0] = Vector3<Real>::UNIT_X;
        mMinBox.Axis[1] = Vector3<Real>::UNIT_Y;
        mMinBox.Axis[2] = Vector3<Real>::UNIT_Z;
        mMinBox.Extent[0] = (Real)0;
        mMinBox.Extent[1] = (Real)0;
        mMinBox.Extent[2] = (Real)0;
        return;
    }

    if (hullDim == 1)
    {
        ConvexHull1<Real>* pkHull1 = kHull.GetConvexHull1();
        const int* hullIndices = pkHull1->GetIndices();

        mMinBox.Center =
            ((Real)0.5)*(points[hullIndices[0]] + points[hullIndices[1]]);
        Vector3<Real> diff =
            points[hullIndices[1]] - points[hullIndices[0]];
        mMinBox.Extent[0] = ((Real)0.5)*diff.Normalize();
        mMinBox.Extent[1] = (Real)0;
        mMinBox.Extent[2] = (Real)0;
        mMinBox.Axis[0] = diff;
        Vector3<Real>::GenerateComplementBasis(mMinBox.Axis[1],
            mMinBox.Axis[2], mMinBox.Axis[0]);

        delete0(pkHull1);
        return;
    }

    int i, j;
    Vector3<Real> origin, diff, U, V, W;
    Vector2<Real>* points2;
    Box2<Real> box2;

    if (hullDim == 2)
    {
        // When ConvexHull3 reports that the point set is 2-dimensional, the
        // caller is responsible for projecting the points onto a plane and
        // calling ConvexHull2.  ConvexHull3 does provide information about
        // the plane of the points.  In this application, we need only
        // project the input points onto that plane and call ContMinBox in
        // two dimensions.

        // Get a coordinate system relative to the plane of the points.
        origin = kHull.GetPlaneOrigin();
        W = kHull.GetPlaneDirection(0).Cross(kHull.GetPlaneDirection(1));
        Vector3<Real>::GenerateComplementBasis(U, V, W);

        // Project the input points onto the plane.
        points2 = new1<Vector2<Real> >(numPoints);
        for (i = 0; i < numPoints; ++i)
        {
            diff = points[i] - origin;
            points2[i].X() = U.Dot(diff);
            points2[i].Y() = V.Dot(diff);
        }

        // Compute the minimum area box in 2D.
        box2 = MinBox2<Real>(numPoints, points2, epsilon, queryType, false);
        delete1(points2);

        // Lift the values into 3D.
        mMinBox.Center = origin + box2.Center.X()*U + box2.Center.Y()*V;
        mMinBox.Axis[0] = box2.Axis[0].X()*U + box2.Axis[0].Y()*V;
        mMinBox.Axis[1] = box2.Axis[1].X()*U + box2.Axis[1].Y()*V;
        mMinBox.Axis[2] = W;
        mMinBox.Extent[0] = box2.Extent[0];
        mMinBox.Extent[1] = box2.Extent[1];
        mMinBox.Extent[2] = (Real)0;
        return;
    }

    int hullQuantity = kHull.GetNumSimplices();
    const int* hullIndices = kHull.GetIndices();
    Real volume, minVolume = Math<Real>::MAX_REAL;

    // Create the unique set of hull vertices to minimize the time spent
    // projecting vertices onto planes of the hull faces.
    std::set<int> uniqueIndices;
    for (i = 0; i < 3*hullQuantity; ++i)
    {
        uniqueIndices.insert(hullIndices[i]);
    }

    // Use the rotating calipers method on the projection of the hull onto
    // the plane of each face.  Also project the hull onto the normal line
    // of each face.  The minimum area box in the plane and the height on
    // the line produce a containing box.  If its volume is smaller than the
    // current volume, this box is the new candidate for the minimum volume
    // box.  The unique edges are accumulated into a set for use by a later
    // step in the algorithm.
    const int* currentHullIndex = hullIndices;
    Real height, minHeight, maxHeight;
    std::set<EdgeKey> edges;
    points2 = new1<Vector2<Real> >(uniqueIndices.size());
    for (i = 0; i < hullQuantity; ++i)
    {
        // Get the triangle.
        int v0 = *currentHullIndex++;
        int v1 = *currentHullIndex++;
        int v2 = *currentHullIndex++;

        // Save the edges for later use.
        edges.insert(EdgeKey(v0, v1));
        edges.insert(EdgeKey(v1, v2));
        edges.insert(EdgeKey(v2, v0));

        // Get 3D coordinate system relative to plane of triangle.
        origin = (points[v0] + points[v1] + points[v2])/(Real)3.0;
        Vector3<Real> edge1 = points[v1] - points[v0];
        Vector3<Real> edge2 = points[v2] - points[v0];
        W = edge2.UnitCross(edge1);  // inner-pointing normal
        if (W == Vector3<Real>::ZERO)
        {
            // The triangle is needle-like, so skip it.
            continue;
        }
        Vector3<Real>::GenerateComplementBasis(U, V, W);

        // Project points onto plane of triangle, onto normal line of plane.
        // TO DO.  In theory, minHeight should be zero since W points to the
        // interior of the hull.  However, the snap rounding used in the 3D
        // convex hull finder involves loss of precision, which in turn can
        // cause a hull facet to have the wrong ordering (clockwise instead
        // of counterclockwise when viewed from outside the hull).  The
        // height calculations here trap that problem (the incorrectly ordered
        // face will not affect the minimum volume box calculations).
        minHeight = (Real)0;
        maxHeight = (Real)0;
        j = 0;
        std::set<int>::const_iterator iter = uniqueIndices.begin();
        while (iter != uniqueIndices.end())
        {
            int index = *iter++;
            diff = points[index] - origin;
            points2[j].X() = U.Dot(diff);
            points2[j].Y() = V.Dot(diff);
            height = W.Dot(diff);
            if (height > maxHeight)
            {
                maxHeight = height;
            }
            else if (height < minHeight)
            {
                minHeight = height;
            }

            j++;
        }
        if (-minHeight > maxHeight)
        {
            maxHeight = -minHeight;
        }

        // Compute minimum area box in 2D.
        box2 = MinBox2<Real>((int)uniqueIndices.size(), points2, epsilon,
            queryType, false);

        // Update current minimum-volume box (if necessary).
        volume = maxHeight*box2.Extent[0]*box2.Extent[1];
        if (volume < minVolume)
        {
            minVolume = volume;

            // Lift the values into 3D.
            mMinBox.Extent[0] = box2.Extent[0];
            mMinBox.Extent[1] = box2.Extent[1];
            mMinBox.Extent[2] = ((Real)0.5)*maxHeight;
            mMinBox.Axis[0] = box2.Axis[0].X()*U + box2.Axis[0].Y()*V;
            mMinBox.Axis[1] = box2.Axis[1].X()*U + box2.Axis[1].Y()*V;
            mMinBox.Axis[2] = W;
            mMinBox.Center = origin + box2.Center.X()*U + box2.Center.Y()*V
                + mMinBox.Extent[2]*W;
        }
    }

    // The minimum-volume box can also be supported by three mutually
    // orthogonal edges of the convex hull.  For each triple of orthogonal
    // edges, compute the minimum-volume box for that coordinate frame by
    // projecting the points onto the axes of the frame.
    std::set<EdgeKey>::const_iterator e2iter;
    for (e2iter = edges.begin(); e2iter != edges.end(); e2iter++)
    {
        W = points[e2iter->V[1]] - points[e2iter->V[0]];
        W.Normalize();

        std::set<EdgeKey>::const_iterator e1iter = e2iter;
        for (++e1iter; e1iter != edges.end(); e1iter++)
        {
            V = points[e1iter->V[1]] - points[e1iter->V[0]];
            V.Normalize();
            Real dot = V.Dot(W);
            if (Math<Real>::FAbs(dot) > Math<Real>::ZERO_TOLERANCE)
            {
                continue;
            }

            std::set<EdgeKey>::const_iterator e0iter = e1iter;
            for (++e0iter; e0iter != edges.end(); e0iter++)
            {
                U = points[e0iter->V[1]] - points[e0iter->V[0]];
                U.Normalize();
                dot = U.Dot(V);
                if (Math<Real>::FAbs(dot) > Math<Real>::ZERO_TOLERANCE)
                {
                    continue;
                }
                dot = U.Dot(W);
                if (Math<Real>::FAbs(dot) > Math<Real>::ZERO_TOLERANCE)
                {
                    continue;
                }
    
                // The three edges are mutually orthogonal.  Project the
                // hull points onto the lines containing the edges.  Use
                // hull point zero as the origin.
                Real umin = (Real)0, umax = (Real)0;
                Real vmin = (Real)0, vmax = (Real)0;
                Real wmin = (Real)0, wmax = (Real)0;
                origin = points[hullIndices[0]];

                std::set<int>::const_iterator iter = uniqueIndices.begin();
                while (iter != uniqueIndices.end())
                {
                    int index = *iter++;
                    diff = points[index] - origin;

                    Real fU = U.Dot(diff);
                    if (fU < umin)
                    {
                        umin = fU;
                    }
                    else if (fU > umax)
                    {
                        umax = fU;
                    }

                    Real fV = V.Dot(diff);
                    if (fV < vmin)
                    {
                        vmin = fV;
                    }
                    else if (fV > vmax)
                    {
                        vmax = fV;
                    }

                    Real fW = W.Dot(diff);
                    if (fW < wmin)
                    {
                        wmin = fW;
                    }
                    else if (fW > wmax)
                    {
                        wmax = fW;
                    }
                }

                Real uExtent = ((Real)0.5)*(umax - umin);
                Real vExtent = ((Real)0.5)*(vmax - vmin);
                Real wExtent = ((Real)0.5)*(wmax - wmin);

                // Update current minimum-volume box (if necessary).
                volume = uExtent*vExtent*wExtent;
                if (volume < minVolume)
                {
                    minVolume = volume;

                    mMinBox.Extent[0] = uExtent;
                    mMinBox.Extent[1] = vExtent;
                    mMinBox.Extent[2] = wExtent;
                    mMinBox.Axis[0] = U;
                    mMinBox.Axis[1] = V;
                    mMinBox.Axis[2] = W;
                    mMinBox.Center = origin +
                        ((Real)0.5)*(umin+umax)*U +
                        ((Real)0.5)*(vmin+vmax)*V +
                        ((Real)0.5)*(wmin+wmax)*W;
                }
            }
        }
    }

    delete1(points2);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void OutlineEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const uint* indices, size_t indexCount)
{
    CVF_ASSERT(verticesPerPrimitive > 0);
    CVF_ASSERT(indices);
    CVF_ASSERT(indexCount > 0);

    // Points will never become edges
    if (verticesPerPrimitive < 2)
    {
        return;
    }

    size_t numPrimitives = indexCount/verticesPerPrimitive;

    size_t ip;
    for (ip = 0; ip < numPrimitives; ip++)
    {
        size_t myFaceIndex = m_faceNormals.size();
        size_t firstIdxInPrimitive = ip*verticesPerPrimitive;

        // Normal computation accepts points and lines, but in that case returns a zero vector
        Vec3f faceNormal = computeFaceNormal(&indices[firstIdxInPrimitive], verticesPerPrimitive);
        m_faceNormals.push_back(faceNormal);

        uint i;
        for (i = 0; i < verticesPerPrimitive; i++)
        {
            const uint vertexIdx1 = indices[firstIdxInPrimitive + i];
            const uint vertexIdx2 = (i < verticesPerPrimitive - 1) ? indices[firstIdxInPrimitive + i + 1] : indices[firstIdxInPrimitive];

            // Never add collapsed edges
            if (vertexIdx1 == vertexIdx2)
            {
                continue;
            }

            int64 edgeKeyVal = EdgeKey(vertexIdx1, vertexIdx2).toKeyVal();
            std::map<int64, size_t>::iterator it = m_edgeToFaceIndexMap.find(edgeKeyVal);
            if (it == m_edgeToFaceIndexMap.end())
            {
                // Not found, so add and register face index
                m_edgeToFaceIndexMap[edgeKeyVal] = myFaceIndex;
            }
            else
            {
                size_t otherFaceIdx = it->second;
                if (otherFaceIdx < OEE_MULTIREF_EDGE)
                {
                    // An edge is already there, check angle
                    if (isFaceAngleAboveThreshold(myFaceIndex, otherFaceIdx))
                    {
                        m_edgeToFaceIndexMap[edgeKeyVal] = OEE_OUTLINE_EDGE;
                    }
                    else
                    {
                        m_edgeToFaceIndexMap[edgeKeyVal] = OEE_NON_OUTLINE_EDGE;
                    }
                }
                else
                {
                    // Three or more faces share an edge
                    m_edgeToFaceIndexMap[edgeKeyVal] = OEE_MULTIREF_EDGE;
                }
            }
        }
    }
}
Beispiel #10
0
void IntervalManager<Real>::Initialize ()
{
    // Get the interval endpoints.
    int intrSize = (int)mInterval->size(), endpSize = 2*intrSize;
    mEndpoint.resize(endpSize);
    int i, j;
    for (i = 0, j = 0; i < intrSize; ++i)
    {
        Endpoint& emin = mEndpoint[j++];
        emin.Type = 0;
        emin.Value = (*mInterval)[i][0];
        emin.Index = i;

        Endpoint& emax = mEndpoint[j++];
        emax.Type = 1;
        emax.Value = (*mInterval)[i][1];
        emax.Index = i;
    }

    // Sort the interval endpoints.
    std::sort(mEndpoint.begin(), mEndpoint.end());

    // Create the interval-to-endpoint lookup table.
    mLookup.resize(endpSize);
    for (j = 0; j < endpSize; ++j)
    {
        Endpoint& endpoint = mEndpoint[j];
        mLookup[2*endpoint.Index + endpoint.Type] = j;
    }

    // Active set of intervals (stored by index in array).
    std::set<int> active;

    // Set of overlapping intervals (stored by pairs of indices in array).
    mOverlap.clear();

    // Sweep through the endpoints to determine overlapping intervals.
    for (i = 0; i < endpSize; ++i)
    {
        Endpoint& endpoint = mEndpoint[i];
        int index = endpoint.Index;
        if (endpoint.Type == 0)  // an interval 'begin' value
        {
            std::set<int>::iterator iter = active.begin();
            std::set<int>::iterator end = active.end();
            for (/**/; iter != end; ++iter)
            {
                int activeIndex = *iter;
                if (activeIndex < index)
                {
                    mOverlap.insert(EdgeKey(activeIndex, index));
                }
                else
                {
                    mOverlap.insert(EdgeKey(index, activeIndex));
                }
            }
            active.insert(index);
        }
        else  // an interval 'end' value
        {
            active.erase(index);
        }
    }
}
Beispiel #11
0
void IntervalManager<Real>::Update ()
{
    // Apply an insertion sort.  Under the assumption that the intervals
    // have not changed much since the last call, the end points are nearly
    // sorted.  The insertion sort should be very fast in this case.
    int endpSize = (int)mEndpoint.size();
    for (int j = 1; j < endpSize; ++j)
    {
        Endpoint key = mEndpoint[j];
        int i = j - 1;
        while (i >= 0 && key < mEndpoint[i])
        {
            Endpoint e0 = mEndpoint[i];
            Endpoint e1 = mEndpoint[i+1];

            // Update the overlap status.
            if (e0.Type == 0)
            {
                if (e1.Type == 1)
                {
                    // The 'b' of interval E0.mIndex was smaller than the 'e'
                    // of interval E1.mIndex, and the intervals *might have
                    // been* overlapping.  Now 'b' and 'e' are swapped, and
                    // the intervals cannot overlap.  Remove the pair from
                    // the overlap set.  The removal operation needs to find
                    // the pair and erase it if it exists.  Finding the pair
                    // is the expensive part of the operation, so there is no
                    // time savings in testing for existence first and then
                    // deleting.
                    mOverlap.erase(EdgeKey(e0.Index, e1.Index));
                }
            }
            else
            {
                if (e1.Type == 0)
                {
                    // The 'b' of interval E1.index was larger than the 'e'
                    // of interval E0.index, and the intervals were not
                    // overlapping.  Now 'b' and 'e' are swapped, and the
                    // intervals *might be* overlapping.  Determine if they
                    // are overlapping and then insert.
                    const Vector2<Real>& i0 = (*mInterval)[e0.Index];
                    const Vector2<Real>& i1 = (*mInterval)[e1.Index];
                    if (i0[0] <= i1[1])
                    {
                        mOverlap.insert(EdgeKey(e0.Index, e1.Index));
                    }
                }
            }

            // Reorder the items to maintain the sorted list.
            mEndpoint[i] = e1;
            mEndpoint[i+1] = e0;
            mLookup[2*e1.Index + e1.Type] = i;
            mLookup[2*e0.Index + e0.Type] = i+1;
            i--;
        }
        mEndpoint[i+1] = key;
        mLookup[2*key.Index + key.Type] = i+1;
    }
}
Beispiel #12
0
//----------------------------------------------------------------------------
void PartitionMesh::ClassifyEdges (std::vector<APoint>& clipVertices,
    const std::vector<int>& indices)
{
    const int numTriangles = (int)indices.size()/3;
    int nextIndex = (int)clipVertices.size();
    for (int i = 0; i < numTriangles; ++i)
    {
        int v0 = indices[3*i+0];
        int v1 = indices[3*i+1];
        int v2 = indices[3*i+2];
        float sDist0 = mSignedDistances[v0];
        float sDist1 = mSignedDistances[v1];
        float sDist2 = mSignedDistances[v2];

        EdgeKey key;
        float t;
        APoint intr;
        AVector diff;

        // The change-in-sign tests are structured this way to avoid numerical
        // round-off problems.  For example, sDist0 > 0 and sDist1 < 0, but
        // both are very small and sDist0*sDist1 = 0 due to round-off
        // errors.  The tests also guarantee consistency between this function
        // and ClassifyTriangles, the latter function using sign tests only on
        // the individual sDist values.

        if ((sDist0 > 0.0f && sDist1 < 0.0f)
        ||  (sDist0 < 0.0f && sDist1 > 0.0f))
        {
            key = EdgeKey(v0, v1);
            if (mEMap.find(key) == mEMap.end())
            {
                t = sDist0/(sDist0 - sDist1);
                diff = clipVertices[v1] - clipVertices[v0];
                intr = clipVertices[v0] + t*diff;
                clipVertices.push_back(intr);
                mEMap[key] = std::make_pair(intr, nextIndex);
                ++nextIndex;
            }
        }

        if ((sDist1 > 0.0f && sDist2 < 0.0f)
        ||  (sDist1 < 0.0f && sDist2 > 0.0f))
        {
            key = EdgeKey(v1,v2);
            if (mEMap.find(key) == mEMap.end())
            {
                t = sDist1/(sDist1 - sDist2);
                diff = clipVertices[v2] - clipVertices[v1];
                intr = clipVertices[v1] + t*diff;
                clipVertices.push_back(intr);
                mEMap[key] = std::make_pair(intr, nextIndex);
                ++nextIndex;
            }
        }

        if ((sDist2 > 0.0f && sDist0 < 0.0f)
        ||  (sDist2 < 0.0f && sDist0 > 0.0f))
        {
            key = EdgeKey(v2,v0);
            if (mEMap.find(key) == mEMap.end())
            {
                t = sDist2/(sDist2 - sDist0);
                diff = clipVertices[v0] - clipVertices[v2];
                intr = clipVertices[v2] + t*diff;
                clipVertices.push_back(intr);
                mEMap[key] = std::make_pair(intr, nextIndex);
                ++nextIndex;
            }
        }
    }
}
Beispiel #13
0
void SplitPolygon
	(
	const std::vector< int >& polygon ,
	std::vector< PlyValueVertex< Real > >& vertices , 
	std::vector< std::vector< int > >* ltPolygons , std::vector< std::vector< int > >* gtPolygons ,
	std::vector< bool >* ltFlags , std::vector< bool >* gtFlags ,
	hash_map< long long , int >& vertexTable ,
	Real trimValue
	)
{
	int sz = int( polygon.size() );
	std::vector< bool > gt( sz );
	int gtCount = 0;
	for( int j=0 ; j<sz ; j++ )
	{
		gt[j] = ( vertices[ polygon[j] ].value>trimValue );
		if( gt[j] ) gtCount++;
	}
	if     ( gtCount==sz ){ if( gtPolygons ) gtPolygons->push_back( polygon ) ; if( gtFlags ) gtFlags->push_back( false ); }
	else if( gtCount==0  ){ if( ltPolygons ) ltPolygons->push_back( polygon ) ; if( ltFlags ) ltFlags->push_back( false ); }
	else
	{
		int start;
		for( start=0 ; start<sz ; start++ ) if( gt[start] && !gt[(start+sz-1)%sz] ) break;

		bool gtFlag = true;
		std::vector< int > poly;

		// Add the initial vertex
		{
			int j1 = (start+int(sz)-1)%sz , j2 = start;
			int v1 = polygon[j1] , v2 = polygon[j2];
			int vIdx;
			hash_map< long long , int >::iterator iter = vertexTable.find( EdgeKey( v1 , v2 ) );
			if( iter==vertexTable.end() )
			{
				vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( vertices.size() );
				vertices.push_back( InterpolateVertices( vertices[v1] , vertices[v2] , trimValue ) );
			}
			else vIdx = iter->second;
			poly.push_back( vIdx );
		}

		for( int _j=0  ; _j<=sz ; _j++ )
		{
			int j1 = (_j+start+sz-1)%sz , j2 = (_j+start)%sz;
			int v1 = polygon[j1] , v2 = polygon[j2];
			if( gt[j2]==gtFlag ) poly.push_back( v2 );
			else
			{
				int vIdx;
				hash_map< long long , int >::iterator iter = vertexTable.find( EdgeKey( v1 , v2 ) );
				if( iter==vertexTable.end() )
				{
					vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( vertices.size() );
					vertices.push_back( InterpolateVertices( vertices[v1] , vertices[v2] , trimValue ) );
				}
				else vIdx = iter->second;
				poly.push_back( vIdx );
				if( gtFlag ){ if( gtPolygons ) gtPolygons->push_back( poly ) ; if( ltFlags ) ltFlags->push_back( true ); }
				else        { if( ltPolygons ) ltPolygons->push_back( poly ) ; if( gtFlags ) gtFlags->push_back( true ); }
				poly.clear() , poly.push_back( vIdx ) , poly.push_back( v2 );
				gtFlag = !gtFlag;
			}
		}
	}
}