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

Fix vertex canInsertEdge test.

+ The precision was not high enough to prevent overflow.
+ The new logic is much simpler (and horked from the face-creation logic).
+ The polygonForceCreateFace test now exercises this implementation.
parent 25b9664a
......@@ -65,32 +65,16 @@ bool vertex::canInsertEdge(const Point& neighborhood, incident_edges::iterator*
currPt.y() - this->m_coords.y()
);
bool inside;
Coord axb = pa.x() * pb.y() - pb.x() * pa.y();
if (axb < 0)
{ // CCW angle between pa and pb is < 180 degrees
Coord axt = pa.x() * pt.y() - pt.x() * pa.y();
if (axt < 0)
inside = false; // vectors pa->pb don't bracket pt CCW
long double mb = sqrt(pb.x() * pb.x() + pb.y() * pb.y());
long double mt = sqrt(pt.x() * pt.x() + pt.y() * pt.y());
if (axt * mb < axb * mt)
{ // pa->pb brackets pt CCW.
inside = true;
}
}
else
{ // CCW angle between pa and pb is >= 180 degrees
Coord bxt = pb.x() * pt.y() - pt.x() * pb.y();
inside = (bxt < 0);
if (!inside)
{
Coord bxa = -axb;
long double ma = sqrt(pa.x() * pa.x() + pa.y() * pa.y());
long double mt = sqrt(pt.x() * pt.x() + pt.y() * pt.y());
inside = (bxt * ma > bxa * mt);
}
}
// Test whether "t" is in the CCW range between "a" and "b":
// (Done using signs of cross-products to check angle relationships.)
HighPrecisionCoord axb = HighPrecisionCoord(pa.x()) * pb.y() - HighPrecisionCoord(pb.x()) * pa.y();
HighPrecisionCoord axt = HighPrecisionCoord(pa.x()) * pt.y() - HighPrecisionCoord(pt.x()) * pa.y();
HighPrecisionCoord txb = HighPrecisionCoord(pt.x()) * pb.y() - HighPrecisionCoord(pb.x()) * pt.y();
bool inside =
(axb > 0 && axt > 0 && txb > 0) || // A->B < 180 degrees => A->T and T->B also < 180 degrees
(axb < 0 && !(axt < 0 && txb < 0)) || // A->B > 180 degrees => if B->T and T->A < 180 degrees, T outside A->B
(axb == 0 && axt < 0 && txb < 0); // A->B = 180 degrees => A->T and T->B also < 180 degrees
if (inside)
{
if (!it->m_adjacentFace)
......
......@@ -15,6 +15,15 @@ import smtk
from smtk.simple import *
import smtk.testing
def computeOffsets(point_arrays):
point_seq = []
point_offsets = []
point_offsets.append(len(point_seq))
for edge in point_arrays:
[point_seq.append(x) for x in edge]
point_offsets.append(len(point_seq))
return (point_seq, point_offsets)
class TestPolygonCreation(smtk.testing.TestCase):
def setUp(self):
......@@ -46,7 +55,10 @@ class TestPolygonCreation(smtk.testing.TestCase):
self.startRenderTest()
mod = smtk.model.Model(mod)
[mod.addCell(x) for x in self.mgr.findEntitiesOfType(smtk.model.CELL_ENTITY, False)]
# Assign one color (black) to all edges and vertices (since this tests face creation):
[v.setFloatProperty('color', [0,0,0,1]) for v in self.mgr.findEntitiesOfType(smtk.model.VERTEX, True)]
[e.setFloatProperty('color', [0,0,0,1]) for e in self.mgr.findEntitiesOfType(smtk.model.EDGE, True)]
#[mod.addCell(x) for x in self.mgr.findEntitiesOfType(smtk.model.CELL_ENTITY, False)]
ms, vs, mp, ac = self.addModelToScene(mod)
ac.GetProperty().SetLineWidth(2)
ac.GetProperty().SetPointSize(6)
......@@ -55,6 +67,7 @@ class TestPolygonCreation(smtk.testing.TestCase):
cam.SetFocalPoint(5,5,0)
cam.SetPosition(5,5,5)
cam.SetViewUp(0,1,0)
self.renderer.SetBackground(1,1,1)
self.renderer.ResetCamera()
self.renderWindow.Render()
......@@ -98,45 +111,68 @@ class TestPolygonCreation(smtk.testing.TestCase):
fop.findAsInt('coordinates').setValue(0, 2)
res = fop.operate()
PrintResultLog(res)
created = res.findModelEntity('created')
faceColors = [[0.9, 1.0, 0.9, 1.0], [0.9, 0.9, 1.0, 1.0]]
for i in range(created.numberOfValues()):
print ' face: ', created.value(i).name()
created.value(i).setFloatProperty('color', faceColors[i])
self.mgr.assignDefaultNames()
smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/forcepoly.json')
#self.mgr.assignDefaultNames()
#smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/forcepoly.json')
self.renderTestModel(mod, ['baselines', 'polygon', 'forceCreateFaces.png'])
def createEdges(self, mod, point_arrays):
(point_seq, point_offsets) = computeOffsets(point_arrays)
return CreateEdge(point_seq, offsets=point_offsets, model=mod)
def testCreationFromEdges(self):
print 'testCreationFromEdges'
# Create a default model (in the x-y plane)
mod = CreateModel()
# Create edges that will compose face:
weirdPoints = [ \
# Outer
[0.0,0.0], [5.0,0.0], \
[5.0,5.0], [5.0,0.0], \
[5.0,5.0], [0.0,5.0], [0.0,0.0], \
# Create some edges
elist = self.createEdges(mod, [ \
# Face 1 Outer
[[0.0,0.0], [5.0,0.0]], \
[[5.0,5.0], [5.0,0.0]], \
[[5.0,5.0], [0.0,5.0], [0.0,0.0]], \
\
# Inner
[1.0,1.0], [1.5,2.5], [1.0,4.0], [2.0,4.0], [2.0,1.0], [1.0,1.0], \
[3.0,2.0], [2.7,2.5], [3.0,3.0], [4.0,3.0], [3.7,2.5], [4.0,2.0], [3.0,2.0], \
]
weirdOffsets = [0, 2, 4, 7, 13,]
elist = CreateEdge(weirdPoints, offsets=weirdOffsets, model=mod)
# Face 1 Inner
[[1.0,1.0], [1.5,2.5], [1.0,4.0], [2.0,4.0], [2.0,1.0], [1.0,1.0]], \
[[3.0,2.0], [2.7,2.5], [3.0,3.0], [4.0,3.0], [3.7,2.5], [4.0,2.0], [3.0,2.0]], \
\
# Face 2 Outer
[[5.0,0.0], [7.0,0.0], [8.0,6.0], [5.0,5.0]],
])
# Create the face from edges we specify
fop = GetActiveSession().op('force create face')
for e in elist:
fop.associateEntity(e)
fcount = [ 3,2, 1, 1, 2,0, ]
floops = [ 0, 1, 2, 3, 4, 1, 5] # indices into elist of edges that form loops
forint = [+1, -1, +1, +1, +1, +1, +1] # orientation of each edge in floops
aelist = [elist[e] for e in floops] # de-referenced version of floops
fop.findAsInt('construction method').setDiscreteIndex(1)
SetVectorValue(fop.findAsInt('counts'), [3, 2, 1, 1])
SetVectorValue(fop.findAsInt('orientations'), [+1, -1, +1, +1, +1])
# NB: Cannot use fop.associateEntity(X) here when the same edge is repeated with different orientations
# because Attribute::associateEntity(X) checks that X is not already associated before appending X
# to the list of entities. Instead, we get the ModelEntityItem used to hold associations and add to
# it manually:
SetVectorValue(fop.specification().associations(), aelist)
SetVectorValue(fop.findAsInt('counts'), fcount)
SetVectorValue(fop.findAsInt('orientations'), forint)
res = fop.operate()
PrintResultLog(res)
print ' outcome: ', res.findInt('outcome').value(0)
created = res.findModelEntity('created')
faceColors = [[0.9, 1.0, 0.9, 1.0], [0.9, 0.9, 1.0, 1.0]]
for i in range(created.numberOfValues()):
print ' face: ', created.value(i).name()
created.value(i).setFloatProperty('color', faceColors[i])
self.mgr.assignDefaultNames()
smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/forcepoly2.json')
#self.mgr.assignDefaultNames()
#smtk.io.ExportJSON.fromModelManagerToFile(self.mgr, '/tmp/forcepoly2.json')
self.renderTestModel(mod, ['baselines', 'polygon', 'forceCreateFaces.png'])
self.renderTestModel(mod, ['baselines', 'polygon', 'forceCreateFacesFromEdges.png'])
if __name__ == '__main__':
......
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