Commit ff3f178b by David Thompson

### 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