line mapping (work in progress)

This commit is contained in:
kwikrick 2012-10-05 12:07:50 +00:00
parent 193b224850
commit eda5689f0a
3 changed files with 72 additions and 9 deletions

View File

@ -13,7 +13,11 @@ Speed: The solver is currently much too slow. The problem is the pattern
- compliled implementation (Psycho/C++/Haskell/???)
Rules: More rewrite rules to increase the problem domain:
- need 3d rule: merge of 2 rigids with 2 shared points (hinge) + hog with angle not on hinge points
- need 2d and 3d rules for merging radial clusters
2D:H+H->H sharing center and 1 point
3D:H+H+H-> sharing center and 3 points, 2 points per pair of hogs
3D:H+H->H sharing center and 2 points (local overconstrained)
- need 3d rule: merge of 2 rigids with 2 shared points (hinge) + hog with angle not on hinge points
- larger subproblems (octahedron, variable radius spheres/cylinders)
- new clusters types (N degrees of freedom)
@ -27,6 +31,8 @@ Extentions:
BUGS:
- prototype based selection doesn't seem to work on line mappings
- stop problem from rotating and jumping around when there are no fixed points. It should
be as close to the prototype as possible;
should have at least have one (2d) or two(3d) edge(s) with the same offset and orientation.
@ -59,3 +65,13 @@ def diamond_3d():
FixConstraint(v2=[-5.0, 5.0, 0.0]) not satisfied
FixConstraint(v1=[0.0, 0.0, 0.0]) not satisfied
- 2D deriveADD accepts this pattern, but fails during execution.
Angle(p3,p2,p4)
Rigid(p1,p2,p4)
Distance(p1,p3)
Note: this pattern can be solved only in 2D. To keep DeriveADD general
(and simple), pattern matching should be more strict, allowing only
patterns where the angle constraint is in the derived triangle.
An extra rule is needed to merge two angles (radial clusters) in 2D.
In 3D, three radial clusters can be merged.

View File

@ -620,8 +620,17 @@ class GeometricSolver (Listener):
dist = Rigid([v,n])
# add add-hoc attributes to rigid, so we can distinguish vertex and normal!
dist.vertex = v
dist.normal = n
# add to mapping
dist.normal = n
# add rigids for created points, needed for prototypes
# NOTE: adding non-problem variables to mapping!
# TODO: clean up after removal of line
vertex_rigid = Rigid([dist.vertex])
self.dr.add(vertex_rigid)
self._map[dist.vertex] = vertex_rigid
normal_rigid = Rigid([dist.normal])
self.dr.add(normal_rigid)
self._map[dist.normal] = normal_rigid
# add line to mapping
self._map[line] = dist
self._map[dist] = line
self.dr.add(dist)
@ -637,6 +646,12 @@ class GeometricSolver (Listener):
# add add-hoc attributes to rigid, so we can distinguish vertex and normal!
dist.vertex = v
dist.normal = n
# add rigids for created points, needed for prototypes
# NOTE: adding non-problem variables to mapping!
# TODO: clean up after removal of line
normal_rigid = Rigid([dist.normal])
self.dr.add(normal_rigid)
self._map[dist.normal] = normal_rigid
# add to mapping
self._map[line] = dist
self._map[dist] = line
@ -878,20 +893,36 @@ class GeometricSolver (Listener):
self.dr.set(cluster, [conf])
def _update_line(self, variable):
cluster = self._map[variable]
proto = self.problem.get_prototype(variable)
line_vertex = cluster.vertex
line_normal = cluster.normal
if self.dimension == 2:
cluster = self._map[variable]
proto = self.problem.get_prototype(variable)
line_vertex = cluster.vertex
line_normal = cluster.normal
# determine vertex and normal prototype coordinates
p1 = proto[0:2]
p2 = proto[2:4]
v = p1
n = perp_2d(p2-p1)
# update prototypes of created point variables
if line_vertex in self._map:
vertex_rigid = self._map[line_vertex]
conf = Configuration({line_vertex: v})
self.dr.set(vertex_rigid, [conf])
diag_print("set "+str(vertex_rigid)+" to "+str(conf),"GeometricSolver")
if line_normal in self._map:
normal_rigid = self._map[line_normal]
conf = Configuration({line_normal: n})
self.dr.set(normal_rigid, [conf])
diag_print("set "+str(normal_rigid)+" to "+str(conf),"GeometricSolver")
# update line configuration
conf = Configuration({line_vertex:v, line_normal:n})
self.dr.set(cluster, [conf])
diag_print("set "+str(cluster)+" to "+str(conf),"GeometricSolver")
elif self.dimension == 3:
raise NotImplementedError
def _update_fix(self):
if self.fixcluster:

View File

@ -99,7 +99,21 @@ def line_problem_2d_2():
problem.add_constraint(DistanceConstraint(Point('p1'), Point('p2'), 5.0))
return problem
def line_problem_2d_3():
def line_problem_2d_3a():
"""A problem with a Line and a 3 CoincicentConstraints"""
problem = GeometricProblem(dimension=2)
problem.add_variable(Point('p1'),vector([3.0, 2.0]))
problem.add_variable(Point('p2'),vector([1.0, 1.0]))
problem.add_variable(Line('l1'),vector([0.0, 0.0, 1.0, 1.0]))
problem.add_constraint(CoincidenceConstraint(Point('p1'), Line('l1')))
problem.add_constraint(CoincidenceConstraint(Point('p2'), Line('l1')))
problem.add_constraint(DistanceConstraint(Point('p1'), Point('p2'), 5.0))
problem.add_variable(Point('p3'),vector([1.0, 0.0]))
problem.add_constraint(CoincidenceConstraint(Point('p3'), Line('l1')))
problem.add_constraint(DistanceConstraint(Point('p3'), Point('p2'), 8.0))
return problem
def line_problem_2d_3b():
"""A problem with a Line and a 3 CoincicentConstraints"""
problem = GeometricProblem(dimension=2)
problem.add_variable(Point('p1'),vector([3.0, 2.0]))
@ -113,6 +127,7 @@ def line_problem_2d_3():
problem.add_constraint(DistanceConstraint(Point('p1'), Point('p3'), 8.0))
return problem
def line_problem_2d_4():
"""A problem with a Line and a 4 CoincicentConstraints"""
problem = GeometricProblem(dimension=2)
@ -136,7 +151,8 @@ def test_line():
#test(line_problem_2d_0())
#test(line_problem_2d_1())
#test(line_problem_2d_2())
test(line_problem_2d_3())
test(line_problem_2d_3a())
#test(line_problem_2d_3b())
#test(line_problem_2d_4())
#test(line_problem_3d_0())