Commit c326ab7a authored by David Thompson's avatar David Thompson
Browse files

Progress on the sweepline algorithm.

parent 087c3b5d
......@@ -37,6 +37,7 @@ namespace smtk {
typedef smtk::shared_ptr<face> FacePtr;
typedef long long Coord;
typedef typename boost::polygon::high_precision_type<Coord>::type HighPrecisionCoord;
typedef smtk::common::UUID Id;
typedef boost::polygon::point_data<Coord> Point;
typedef boost::polygon::segment_data<Coord> Segment;
......
......@@ -42,6 +42,19 @@ public:
PointSeq::const_reverse_iterator pointsREnd() const { return this->m_points.rend(); }
PointSeq::reverse_iterator pointsREnd() { return this->m_points.rend(); }
bool pointsOfSegment(ssize_t idx, Point& lo, Point& hi) const
{
if (idx < 0 || idx >= this->m_points.size())
return false;
PointSeq::const_iterator it = this->pointsBegin();
for (ssize_t i = 0; i <= idx && it != this->pointsEnd(); ++i, ++it, lo = hi)
hi = *it;
hi = *it;
return true;
}
protected:
edge() { }
......
......@@ -332,6 +332,35 @@ bool pmodel::splitModelEdgeAtModelVertex(smtk::model::ManagerPtr mgr, const Id&
typedef std::vector<std::pair<size_t, Segment> > SegmentSplitsT;
void DumpSegSplits(const char* msg, SegmentSplitsT::iterator a, SegmentSplitsT::iterator b)
{
if (msg)
std::cout << msg << "\n";
SegmentSplitsT::iterator ii;
for (ii = a; ii != b; ++ii)
{
std::cout << " " << ii->first
<< " : " << ii->second.low().x() << " " << ii->second.low().y()
<< " -- " << ii->second.high().x() << " " << ii->second.high().y()
<< "\n";
}
}
void DumpPointSeq(const char* msg, PointSeq::const_iterator a, PointSeq::const_iterator b, PointSeq::const_iterator loc)
{
if (msg)
std::cout << msg << "\n";
PointSeq::const_iterator ii;
for (ii = a; ii != b; ++ii)
{
std::cout
<< " " << ii->x() << " " << ii->y()
<< (ii == loc ? " *\n" : "\n");
}
}
bool pmodel::splitModelEdgeAtModelVertex(
smtk::model::ManagerPtr mgr, edge::Ptr edgeToSplit, vertex::Ptr splitPoint, PointSeq::const_iterator location)
{
......@@ -344,18 +373,48 @@ bool pmodel::splitModelEdgeAtModelVertex(
*location == *edgeToSplit->pointsRBegin())
return false;
DumpPointSeq("Split Edge", edgeToSplit->pointsBegin(), edgeToSplit->pointsEnd(), location);
PointSeq::const_iterator it;
size_t n = 0;
if (
*edgeToSplit->pointsBegin() == *edgeToSplit->pointsRBegin() && // edge is periodic
this->m_vertices.find(*edgeToSplit->pointsBegin()) == this->m_vertices.end()) // edge has no model vertices (those must be at start+end)
{
// Edge had no model vertices and we are being asked to split it at a
// point interior to its sequence; reorder the sequence so the split
// point is at the beginning+end of the sequence.
//
// Note that this is kinda futzy becase periodic edges repeat one point
// at their beginning and end... we have to remove the duplicate before
// splicing and then add a duplicate of the new start point to the end
// of the list.
std::cout << "Edge is periodic, split is interior!!!!\n";
it = edgeToSplit->pointsEnd();
--it;
edgeToSplit->m_points.erase(it);
it = edgeToSplit->pointsBegin();
edgeToSplit->m_points.splice(it, edgeToSplit->m_points, location, edgeToSplit->pointsEnd());
edgeToSplit->m_points.insert(edgeToSplit->pointsEnd(), *location);
// Regenerate the tessellation for the edge with the new point order:
//mgr->erase(edgeToSplit->id(), smtk::model::SESSION_TESSELLATION);
smtk::model::Edge modelEdge(mgr, edgeToSplit->id());
this->addEdgeTessellation(modelEdge, edgeToSplit);
return true;
}
SegmentSplitsT segs;
SegmentSplitsT::iterator segSplit;
segs.reserve(npts - 1); // Preallocation to prevent vector from reallocating and invalidating segSplit iterator.
PointSeq::const_iterator prev = edgeToSplit->pointsBegin();
size_t n = 0;
PointSeq::const_iterator it = prev;
for (++it; it != edgeToSplit->pointsEnd(); ++it, ++n, prev = it)
segs.reserve(npts - 1); // Preallocation to prevent vector from reallocating and invalidating segSplit iterator.
it = prev;
for (++it; it != edgeToSplit->pointsEnd(); ++it, ++n)
{
segs.push_back(std::pair<size_t,Segment>(n, Segment(*prev, *it)));
if (prev == location)
segSplit = segs.begin() + n;
prev = it;
}
DumpSegSplits("Pre-split: ", segs.begin(), segs.end());
// Remove edgeToSplit from its endpoint vertices so that creation
// of new edges can succeed (otherwise it will fail when trying
......@@ -363,9 +422,15 @@ bool pmodel::splitModelEdgeAtModelVertex(
std::pair<Id,Id> adjacentFaces = this->removeModelEdgeFromEndpoints(mgr, edgeToSplit);
(void)adjacentFaces;
DumpSegSplits("Split A: ", segs.begin(), segSplit);
DumpSegSplits("Split B: ", segSplit, segs.end());
smtk::model::Edge aboutToDie(mgr, edgeToSplit->id());
smtk::model::Model xxx = aboutToDie.owningModel();
mgr->erase(edgeToSplit->id());
// Now we can create the new model edges.
this->createModelEdgeFromSegments(mgr, segs.begin(), segSplit);
this->createModelEdgeFromSegments(mgr, segSplit, segs.end());
smtk::model::Edge eA = this->createModelEdgeFromSegments(mgr, segs.begin(), segSplit);
smtk::model::Edge eB = this->createModelEdgeFromSegments(mgr, segSplit, segs.end());
std::cout << "Split into " << eA.name() << " " << eB.name() << "\n";
// TODO: Fix face adjacency information (face relations and at all 3 vertices)
// Fix face loops by replacing old edge with new edges.
......
......@@ -12,10 +12,32 @@
#include "smtk/bridge/polygon/Operator.h"
#include "smtk/common/UnionFind.h"
#include <map>
#include <set>
#include <vector>
namespace smtk {
namespace bridge {
namespace polygon {
struct EdgeFragmentComparator;
struct EdgeFragment;
struct Neighborhood;
struct Region;
struct SweepEvent;
struct SweeplinePosition;
typedef size_t FragmentId;
typedef std::set<SweepEvent> SweepEventSet;
typedef std::vector<SweepEvent> SweepEventArray;
typedef std::set<FragmentId, EdgeFragmentComparator> ActiveSegmentTree;
typedef std::vector<EdgeFragment> FragmentArray;
typedef int RegionId;
typedef smtk::common::UnionFind<RegionId> RegionIdSet;
typedef std::map<RegionId, Region> RegionDefinitions;
/**\brief Create a face given a set of point coordinates or edges (but not both).
*
*/
......@@ -29,6 +51,29 @@ public:
protected:
virtual smtk::model::OperatorResult operateInternal();
void processNeighborhood(
Neighborhood& n,
RegionDefinitions& regions,
RegionIdSet& regionIds);
void processSegmentStart(
const SweepEvent& event,
FragmentArray& fragments,
SweeplinePosition& sweepPosn,
ActiveSegmentTree& activeEdges,
SweepEventArray& edgesToInsertAfterAdvance,
Neighborhood& n);
void processSegmentEnd(
const SweepEvent& event,
FragmentArray& fragments,
Neighborhood& n);
void processSegmentCross(
const SweepEvent& event,
FragmentArray& fragments,
SweeplinePosition& sweepPosn,
ActiveSegmentTree& activeEdges,
SweepEventArray& edgesToInsertAfterAdvance,
Neighborhood& n);
};
} // namespace polygon
......
......@@ -109,7 +109,7 @@ class TestPolygonCreation(smtk.testing.TestCase):
# Test self-intersecting edges.
# Test periodic edges with non-model-vertex at first point.
edgeTestVerts = [[0,0], [1,1], [0,1], [1,0], [3,0], [3,3], [4,3], [2,0], [3,0], [10,10]]
edgeTestOffsets = [0, 4, 9, 9, 12]; # Only first 2 edges are valid
edgeTestOffsets = [0, 4, 9, 9, 12]; # Only first 3 edges are valid
elist = CreateEdge(edgeTestVerts, offsets=edgeTestOffsets, model=mod)
# Make sure that warnings are generated for invalid edge offsets.
res = GetLastResult()
......@@ -140,7 +140,7 @@ class TestPolygonCreation(smtk.testing.TestCase):
arf = SplitEdge(elist, [2, 4])
#smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/poly.json')
smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/poly.json')
flist = CreateFaces(mod)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment