geosolver/test/test_3d.py
2012-08-23 20:01:49 +00:00

376 lines
17 KiB
Python

#!/usr/bin/env python
"""This module provides some tests for the GeoSolver.
These tests are concerned with 3D solving.
The tests are also simple examples of how to use of the GeomSolver API"""
import random
import math
from test_generic import test
from geosolver.geometric import GeometricProblem, GeometricSolver, DistanceConstraint,AngleConstraint, FixConstraint,RightHandedConstraint
from geosolver.vector import vector
from geosolver.randomproblem import random_triangular_problem_3D, random_distance_problem_3D
from geosolver.diagnostic import diag_select, diag_print
from geosolver.intersections import distance_2p, angle_3p
# ---------- 3D problems -----
def fix3_problem_3d():
"""A problem with a fix constraint"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.0, 0.0, 1.0]))
#problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
#problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
#problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(FixConstraint('v1', vector([0.0,0.0,0.0])))
problem.add_constraint(FixConstraint('v2', vector([10.0,0.0,0.0])))
problem.add_constraint(FixConstraint('v3', vector([5.0,5.0,0.0])))
return problem
def fix2_problem_3d():
"""A problem with a fix constraint"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.0, 0.0, 1.0]))
#problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(FixConstraint('v1', vector([0.0,0.0,0.0])))
problem.add_constraint(FixConstraint('v2', vector([10.0,0.0,0.0])))
return problem
def fix1_problem_3d():
"""A problem with a fix constraint"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.0, 0.0, 1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(FixConstraint('v1', vector([0.0,0.0,0.0])))
return problem
def double_banana_problem():
"""The double banana problem"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
problem.add_point('w1', vector([0.0, 0.0, 0.0]))
problem.add_point('w2', vector([1.0, 0.0, 0.0]))
problem.add_point('w3', vector([0.0, 1.0, 0.0]))
problem.add_constraint(DistanceConstraint('w1', 'w2', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'w3', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'w3', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('w3', 'v5', 10.0))
return problem
def double_banana_plus_one_problem():
"""The double banana problem, plus one constraint (well-constrained)"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
problem.add_point('w1', vector([0.0, 0.0, 0.0]))
problem.add_point('w2', vector([1.0, 0.0, 0.0]))
problem.add_point('w3', vector([0.0, 1.0, 0.0]))
problem.add_constraint(DistanceConstraint('w1', 'w2', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'w3', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'w3', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('w1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('w2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('w3', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'w1', 10.0))
return problem
def double_tetrahedron_problem():
"""The double tetrahedron problem"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
return problem
def dad_tetrahedron_problem():
"""The double tetrahedron problem with an angle"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(AngleConstraint('v2', 'v1','v3', 60.0*math.pi/180.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
return problem
def ada_tetrahedron_problem():
"""The double tetrahedron problem with an angle"""
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(AngleConstraint('v3', 'v1','v2', 60.0*math.pi/180.0))
problem.add_constraint(AngleConstraint('v1', 'v2','v3', 60.0*math.pi/180.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
return problem
def ada_3d_problem():
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([random.random() for i in [1,2]]))
problem.add_point('v2', vector([random.random() for i in [1,2]]))
problem.add_point('v3', vector([random.random() for i in [1,2]]))
problem.add_constraint(DistanceConstraint('v1','v2',distance_2p(problem.get_point('v1'), problem.get_point('v2'))))
problem.add_constraint(AngleConstraint('v3', 'v1', 'v2',
angle_3p(problem.get_point('v3'), problem.get_point('v1'), problem.get_point('v2'))
))
problem.add_constraint(AngleConstraint('v1', 'v2', 'v3',
angle_3p(problem.get_point('v1'), problem.get_point('v2'), problem.get_point('v3'))
))
return problem
def overconstrained_tetra():
problem = GeometricProblem(dimension=3)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
# overconstrain me!
problem.add_constraint(AngleConstraint('v1', 'v2', 'v3', math.pi/3))
#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, use_prototype=False) # no prototype based selection
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))
return problem
# ----------- 3d tests ----------
def test_ada_3d():
problem = ada_3d_problem()
diag_select("nothing")
print "problem:"
print problem
solver = GeometricSolver(problem)
print "drplan:"
print solver.dr
print "number of top-level rigids:",len(solver.dr.top_level())
result = solver.get_result()
print "result:"
print result
print "result is",result.flag, "with", len(result.solutions),"solutions"
check = True
if len(result.solutions) == 0:
check = False
diag_select(".*")
for sol in result.solutions:
print "solution:",sol
check = check and problem.verify(sol)
diag_select("nothing")
if check:
print "all solutions valid"
else:
print "INVALID"
def selection_test():
problem = GeometricProblem(dimension=3,use_prototype=False)
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
s1 = RightHandedConstraint('v1','v2','v4','v5')
# add selection con
problem.add_constraint(s1)
# solve
solver = GeometricSolver(problem)
print len(solver.get_solutions()), "solutions"
# remove and add constraint
print "removing selection-constraint"
problem.rem_constraint(s1)
# solve again
print len(solver.get_solutions()), "solutions"
# remove and add constraint
print "re-adding selection constraint"
problem.add_constraint(s1)
# solve again
print len(solver.get_solutions()), "solutions"
# remove distance
print "removing and re-adding distance v1-v5"
problem.rem_constraint(problem.get_distance("v1","v5"))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
# solve again
print len(solver.get_solutions()), "solutions"
def selection_problem():
"""The double tetrahedron problem with selection constraints"""
problem = GeometricProblem(dimension=3, use_prototype=False) # no prototype based selection
problem.add_point('v1', vector([0.0, 0.0, 0.0]))
problem.add_point('v2', vector([1.0, 0.0, 0.0]))
problem.add_point('v3', vector([0.0, 1.0, 0.0]))
problem.add_point('v4', vector([0.5, 0.5, 1.0]))
problem.add_point('v5', vector([0.5, 0.5,-1.0]))
problem.add_constraint(DistanceConstraint('v1', 'v2', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v3', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v4', 10.0))
problem.add_constraint(DistanceConstraint('v1', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v2', 'v5', 10.0))
problem.add_constraint(DistanceConstraint('v3', 'v5', 10.0))
#problem.add_constraint(SelectionConstraint(is_right_handed, ['v1','v2','v4','v5']))
problem.add_constraint(RightHandedConstraint('v1','v2','v4','v5'))
return problem
def test3d():
#diag_select("clsolver")
test(double_tetrahedron_problem())
test(ada_tetrahedron_problem())
test(double_banana_problem())
test(double_banana_plus_one_problem())
test(random_triangular_problem_3D(10,10.0,0.0,0.5))
test(random_distance_problem_3D(10,1.0,0.0))
test(fix1_problem_3d())
test(fix2_problem_3d())
test(fix3_problem_3d())
test(selection_problem())
selection_test()
test(overconstrained_tetra())
test(diamond_3d())
if __name__ == "__main__":
test3d()