several bug-fixes.
added some assertions to prevent user errors. test.py: added problematic diamond_3d problem
This commit is contained in:
parent
e758e3c225
commit
b3189bac28
62
TODO.txt
62
TODO.txt
|
@ -2,23 +2,59 @@ TODO/WISH LIST
|
|||
--------------
|
||||
|
||||
Code: Some bits of the code are ugly:
|
||||
- vector module, matpy module and Numpy package, all offer similar functionality.
|
||||
Use only one, get rid of two.
|
||||
- more documentation!
|
||||
- vector module, matpy module and Numpy package, all offer similar
|
||||
functionality. Use only one, get rid of two.
|
||||
- more documentation!
|
||||
|
||||
Speed: The solver is currently much too slow. The problem is the pattern matching algorithms that is used to find
|
||||
combinations of clusters that can be rewritten/merged. Solutions:
|
||||
- hand-coded matching algorithms per merge rule (labourous and error prone)
|
||||
- incremental pattern matching system (work in progress)
|
||||
- compliled implementation (Psycho/C++/Haskell/???)
|
||||
Speed: The solver is currently much too slow. The problem is the pattern
|
||||
matching algorithms that is used to find combinations of clusters that
|
||||
can be rewritten/merged. Solutions:
|
||||
- incremental pattern matching system (work in progress)
|
||||
- compliled implementation (Psycho/C++/Haskell/???)
|
||||
|
||||
Rules: More rewrite rules to increase the problem domain:
|
||||
- larger subproblems (octahedron, variable radius spheres/cylinders)
|
||||
- new clusters types (N degrees of freedom)
|
||||
- larger subproblems (octahedron, variable radius spheres/cylinders)
|
||||
- new clusters types (N degrees of freedom)
|
||||
|
||||
Extentions:
|
||||
- implement geometry: lines, planes, spheres, cylinders, tori (mappings to cluster)
|
||||
- constraints on parameters (equality, algebraic constraints)
|
||||
- different variable domains (integers, reals, n-dimensional points, surfaces, volumes, logic variables, lists)
|
||||
- implement geometry: lines, planes, spheres, cylinders, tori (mappings to
|
||||
cluster)
|
||||
- constraints on parameters (equality, algebraic constraints)
|
||||
- different variable domains (integers, reals, n-dimensional points,
|
||||
surfaces, volumes, logic variables, lists)
|
||||
|
||||
Easy of use:
|
||||
- move use_prototype flag to GeometricProblem (instead of in
|
||||
GeometricSolver)
|
||||
- check dimension of prototype points when adding to problem
|
||||
|
||||
|
||||
BUGS:
|
||||
|
||||
- following should be well-constraint, gives underconstrained (need extra rule/pattern)
|
||||
def diamond_3d():
|
||||
"""creates a diamond shape with point 'v1'...'v4' in 3D with one solution"""
|
||||
L=10.0
|
||||
problem = GeometricProblem(dimension=3)
|
||||
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
|
||||
problem.add_point('v2', vector([-5.0, 5.0, 0.0]))
|
||||
problem.add_point('v3', vector([5.0, 5.0, 0.0]))
|
||||
problem.add_point('v4', vector([0.0, 10.0, 0.0]))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'v2', L))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'v3', L))
|
||||
problem.add_constraint(DistanceConstraint('v2', 'v3', L))
|
||||
problem.add_constraint(DistanceConstraint('v2', 'v4', L))
|
||||
problem.add_constraint(DistanceConstraint('v3', 'v4', L))
|
||||
# this bit of code constrains the points v1...v4 in a plane with point p above v1
|
||||
problem.add_point('p', vector([0.0, 0.0, 1.0]))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'p', 1.0))
|
||||
problem.add_constraint(AngleConstraint('v2','v1','p', math.pi/2))
|
||||
problem.add_constraint(AngleConstraint('v3','v1','p', math.pi/2))
|
||||
problem.add_constraint(AngleConstraint('v4','v1','p', math.pi/2))
|
||||
|
||||
- when fixed (by swapping v1 and v3 in last bit of code)
|
||||
sometimes raises:
|
||||
StandardError: more than one candidate prototype cluster for variable v2
|
||||
or:
|
||||
FixConstraint(v2=[-5.0, 5.0, 0.0]) not satisfied
|
||||
FixConstraint(v1=[0.0, 0.0, 0.0]) not satisfied
|
||||
|
|
|
@ -280,8 +280,10 @@ class ClusterSolver(Notifier):
|
|||
clusters = self._graph.outgoing_vertices(var)
|
||||
clusters = filter(lambda c: isinstance(c, Rigid), clusters)
|
||||
clusters = filter(lambda c: len(c.vars) == 1, clusters)
|
||||
if len(clusters) != 1:
|
||||
raise StandardError, "no prototype cluster for variable "+str(v)
|
||||
if len(clusters) < 1:
|
||||
raise StandardError, "no prototype cluster for variable "+str(var)
|
||||
elif len(clusters) > 1:
|
||||
raise StandardError, "more than one candidate prototype cluster for variable "+str(var)
|
||||
selclusters.append(clusters[0])
|
||||
outcluster = incluster.copy()
|
||||
selector = PrototypeMethod(incluster, selclusters, outcluster, constraints, self._prototype_selection_var)
|
||||
|
@ -357,7 +359,7 @@ class ClusterSolver(Notifier):
|
|||
if len(self._applicable_methods) > 0:
|
||||
method = iter(self._applicable_methods).next()
|
||||
#print "applicable methods:", map(str, self._applicable_methods)
|
||||
print "incremental search found:", method
|
||||
diag_print("incremental search found:"+str(method),"clsolver._process_new")
|
||||
self._add_method_complete(method)
|
||||
else:
|
||||
newobject = self._new.pop()
|
||||
|
|
|
@ -14,7 +14,9 @@ from notify import Notifier, Listener
|
|||
from tolerance import tol_eq
|
||||
from intersections import angle_3p, distance_2p
|
||||
from selconstr import SelectionConstraint
|
||||
from geosolver.intersections import is_left_handed, is_right_handed, transform_point, make_hcs_3d
|
||||
from geosolver.intersections import is_left_handed, is_right_handed
|
||||
from geosolver.intersections import is_clockwise, is_counterclockwise
|
||||
from geosolver.intersections import transform_point, make_hcs_3d
|
||||
|
||||
# ----------- GeometricProblem -------------
|
||||
|
||||
|
@ -50,6 +52,7 @@ class GeometricProblem (Notifier, Listener):
|
|||
def add_point(self, variable,pos):
|
||||
"""add a point variable with a prototype position"""
|
||||
position = vector.vector(pos)
|
||||
assert len(position) == self.dimension
|
||||
if variable not in self.prototype:
|
||||
self.prototype[variable] = position
|
||||
self.cg.add_variable(variable)
|
||||
|
@ -881,19 +884,28 @@ class RigidConstraint(ParametricConstraint):
|
|||
def __str__(self):
|
||||
return "RigidConstraint("+str(self._variables)+")"
|
||||
|
||||
class ClockwiseConstraint (SelectionConstraint):
|
||||
"""A selection constraint for 3 points to have a clockwise orientation (not co-linear!)"""
|
||||
def __init__(self, v1, v2, v3):
|
||||
SelectionConstraint.__init__(self, is_clockwise, [v1,v2,v3])
|
||||
|
||||
class CounterClockwiseConstraint (SelectionConstraint):
|
||||
"""A selection constraint for 3 points to have a counter-clockwise orientation (not co-linear!)"""
|
||||
def __init__(self, v1, v2, v3):
|
||||
SelectionConstraint.__init__(self, is_counterclockwise, [v1,v2,v3])
|
||||
|
||||
class RightHandedConstraint (SelectionConstraint):
|
||||
"""A selection constraint for 4 points to have a right-handed orientation"""
|
||||
"""A selection constraint for 4 points to have a right-handed orientation (not co-planar!)"""
|
||||
def __init__(self, v1, v2, v3, v4):
|
||||
SelectionConstraint.__init__(self, is_right_handed, [v1,v2,v3,v4])
|
||||
|
||||
class LeftHandedConstraint (SelectionConstraint):
|
||||
"""A selection constraint for 4 points to have a left-handed orientation"""
|
||||
"""A selection constraint for 4 points to have a left-handed orientation (not co-planar!)"""
|
||||
def __init__(self, v1, v2, v3, v4):
|
||||
SelectionConstraint.__init__(self, is_left_handed, [v1,v2,v3,v4])
|
||||
|
||||
class NotRightHandedConstraint (SelectionConstraint):
|
||||
"""A selection constraint for 4 points to not have a rigth-handed orientation, i.e. left-handed or co-planar"""
|
||||
"""A selection constraint for 4 points to not have a right-handed orientation, i.e. left-handed or co-planar"""
|
||||
def __init__(self, v1, v2, v3, v4):
|
||||
SelectionConstraint.__init__(self, fnot(is_right_handed), [v1,v2,v3,v4])
|
||||
|
||||
|
|
|
@ -227,13 +227,19 @@ def distance_2p(p1, p2):
|
|||
|
||||
def is_clockwise(p1,p2,p3):
|
||||
""" returns True iff triangle p1,p2,p3 is clockwise oriented"""
|
||||
assert len(p1)==2
|
||||
assert len(p1)==len(p2)
|
||||
assert len(p2)==len(p3)
|
||||
u = p2 - p1
|
||||
v = p3 - p2;
|
||||
v = p3 - p2
|
||||
perp_u = vector.vector([-u[1], u[0]])
|
||||
return tol_lt(vector.dot(perp_u,v),0)
|
||||
|
||||
def is_counterclockwise(p1,p2,p3):
|
||||
""" returns True iff triangle p1,p2,p3 is counterclockwise oriented"""
|
||||
assert len(p1)==2
|
||||
assert len(p1)==len(p2)
|
||||
assert len(p2)==len(p3)
|
||||
u = p2 - p1
|
||||
v = p3 - p2;
|
||||
perp_u = vector.vector([-u[1], u[0]])
|
||||
|
@ -241,6 +247,10 @@ def is_counterclockwise(p1,p2,p3):
|
|||
|
||||
def is_colinear(p1,p2,p3):
|
||||
""" returns True iff triangle p1,p2,p3 is colinear (neither clockwise of counterclockwise oriented)"""
|
||||
assert len(p1)==2
|
||||
assert len(p1)==len(p2)
|
||||
assert len(p2)==len(p3)
|
||||
|
||||
u = p2 - p1
|
||||
v = p3 - p2;
|
||||
perp_u = vector.vector([-u[1], u[0]])
|
||||
|
|
21
test/test.py
21
test/test.py
|
@ -225,6 +225,27 @@ def overconstrained_tetra():
|
|||
#problem.add_constraint(AngleConstraint('v1', 'v2', 'v3', math.pi/4))
|
||||
return problem
|
||||
|
||||
def diamond_3d():
|
||||
"""creates a diamond shape with point 'v1'...'v4' in 3D with one solution"""
|
||||
# Following should be well-constraint, gives underconstrained (need extra rule/pattern)
|
||||
L=10.0
|
||||
problem = GeometricProblem(dimension=3)
|
||||
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
|
||||
problem.add_point('v2', vector([-5.0, 5.0, 0.0]))
|
||||
problem.add_point('v3', vector([5.0, 5.0, 0.0]))
|
||||
problem.add_point('v4', vector([0.0, 10.0, 0.0]))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'v2', L))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'v3', L))
|
||||
problem.add_constraint(DistanceConstraint('v2', 'v3', L))
|
||||
problem.add_constraint(DistanceConstraint('v2', 'v4', L))
|
||||
problem.add_constraint(DistanceConstraint('v3', 'v4', L))
|
||||
# this bit of code constrains the points v1...v4 in a plane with point p above it
|
||||
problem.add_point('p', vector([0.0, 0.0, 1.0]))
|
||||
problem.add_constraint(DistanceConstraint('v1', 'p', 1.0))
|
||||
problem.add_constraint(AngleConstraint('v2','v1','p', math.pi/2))
|
||||
problem.add_constraint(AngleConstraint('v3','v1','p', math.pi/2))
|
||||
problem.add_constraint(AngleConstraint('v4','v1','p', math.pi/2))
|
||||
|
||||
# -------- 2D problems
|
||||
|
||||
def ddd_problem():
|
||||
|
|
Loading…
Reference in New Issue
Block a user