예제 #1
0
    def solve_shape(self, layers):
        for layer in layers:
            print("Solving shape ", layer.id)

            pt0 = layer.named_pairs[0][0]
            pt1 = layer.named_pairs[1][0]
            pt2 = layer.named_pairs[2][0]
            for i, point in enumerate(layer.named_pairs):
                # Add initial points
                self.problem.add_variable(point[0],
                                          vector([point[1], point[2], 0]))

                # Lock them together
                if i > 0:
                    self.problem.add_constraint(
                        DistanceConstraint(
                            pt0, point[0],
                            distance_2p(self.problem.get_point(pt0),
                                        self.problem.get_point(point[0]))))
                if i > 1:
                    self.problem.add_constraint(
                        AngleConstraint(
                            pt0, pt1, point[0],
                            angle_3p(self.problem.get_point(pt0),
                                     self.problem.get_point(pt1),
                                     self.problem.get_point(point[0]))))
                if i > 2:
                    self.problem.add_constraint(
                        AngleConstraint(
                            pt0, pt2, point[0],
                            angle_3p(self.problem.get_point(pt0),
                                     self.problem.get_point(pt2),
                                     self.problem.get_point(point[0]))))
예제 #2
0
def balloon_problem():
    """test angle propagation via balloon"""
    problem = GeometricProblem(dimension=2)
    problem.add_point('A', vector([0.0, 0.0]))
    problem.add_point('B', vector([1.0, -1.0]))
    problem.add_point('C', vector([1.0, +1.0]))
    problem.add_point('D', vector([2.0, 0.0]))
    problem.add_constraint(
        AngleConstraint(
            'B', 'A', 'C',
            angle_3p(problem.get_point('B'), problem.get_point('A'),
                     problem.get_point('C'))))
    problem.add_constraint(
        AngleConstraint(
            'A', 'B', 'C',
            angle_3p(problem.get_point('A'), problem.get_point('B'),
                     problem.get_point('C'))))
    problem.add_constraint(
        AngleConstraint(
            'B', 'C', 'D',
            angle_3p(problem.get_point('B'), problem.get_point('C'),
                     problem.get_point('D'))))
    problem.add_constraint(
        AngleConstraint(
            'C', 'D', 'B',
            angle_3p(problem.get_point('C'), problem.get_point('D'),
                     problem.get_point('B'))))
    problem.add_constraint(DistanceConstraint('A', 'D', 6.0))
    return problem
예제 #3
0
def balloons():
    # for testing angle propagation via balloon
    problem = GeometricProblem(dimension=2)
    problem.add_point('A', vector([0.0, 0.0]))
    problem.add_point('B', vector([0.0, 1.0]))
    problem.add_point('C', vector([1.0, 1.0]))
    problem.add_point('D', vector([2.0, 1.0]))
    problem.add_constraint(AngleConstraint('B', 'A', 'C', math.pi / 8))
    problem.add_constraint(AngleConstraint('A', 'B', 'C', math.pi / 8))
    problem.add_constraint(AngleConstraint('B', 'C', 'D', math.pi / 8))
    problem.add_constraint(AngleConstraint('C', 'D', 'B', math.pi / 8))
    problem.add_constraint(DistanceConstraint('A', 'D', 6.0))
    return problem
예제 #4
0
def hog1():
    # double triangle with inter-angle (needs angle propagation)
    problem = GeometricProblem(dimension=2)
    problem.add_point('A', vector([0.0, 0.0]))
    problem.add_point('B', vector([1.0, 0.0]))
    problem.add_point('C', vector([1.0, 1.0]))
    problem.add_point('D', vector([0.0, 1.0]))
    problem.add_constraint(DistanceConstraint('A', 'B', 10.0))
    problem.add_constraint(DistanceConstraint('B', 'C', 10.0))
    problem.add_constraint(DistanceConstraint('C', 'D', 10.0))
    problem.add_constraint(AngleConstraint('B', 'A', 'C', math.pi / 8))
    problem.add_constraint(AngleConstraint('B', 'A', 'D', math.pi / 4))
    return problem
예제 #5
0
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
예제 #6
0
def twoscisors():
    problem = GeometricProblem(dimension=2)
    problem.add_point('A', vector([0.0, 0.0]))
    problem.add_point('B', vector([0.0, 1.0]))
    problem.add_point('C', vector([1.0, 1.0]))
    problem.add_point('D', vector([2.0, 1.0]))
    problem.add_constraint(AngleConstraint('B', 'A', 'C', math.pi / 8))
    problem.add_constraint(AngleConstraint('B', 'D', 'C', math.pi / 8))
    problem.add_constraint(DistanceConstraint('A', 'B', 6.0))
    problem.add_constraint(DistanceConstraint('A', 'C', 6.0))
    problem.add_constraint(DistanceConstraint('D', 'B', 6.0))
    problem.add_constraint(DistanceConstraint('D', 'C', 6.0))
    return problem
예제 #7
0
def add_random_constraint(problem, ratio):
    """add a random constraint to a problem, with a given ratio angles/distances"""
    if random.random() < ratio:
        # add angle
        pointvars = list(problem.cg.variables())
        random.shuffle(pointvars)
        v1 = pointvars[0]
        v2 = pointvars[1]
        v3 = pointvars[2]
        p1 = problem.get_point(v1)
        p2 = problem.get_point(v2)
        p3 = problem.get_point(v3)
        angle = angle_3p(p1, p2, p3)
        con = AngleConstraint(v1, v2, v3, angle)
        diag_print("**Add constraint:" + str(con), "drplan")
        problem.add_constraint(con)
    else:
        # add distance
        pointvars = list(problem.cg.variables())
        random.shuffle(pointvars)
        v1 = pointvars[0]
        v2 = pointvars[1]
        p1 = problem.get_point(v1)
        p2 = problem.get_point(v2)
        dist = distance_2p(p1, p2)
        con = DistanceConstraint(v1, v2, dist)
        diag_print("**Add constraint:" + str(con), "drplan")
        problem.add_constraint(con)
    return
예제 #8
0
def random_triangular_problem_3D(npoints, radius, roundoff, pangle):
    problem = random_distance_problem_3D(npoints, radius, roundoff)
    points = list(problem.cg.variables())
    triangles = []
    for i1 in range(len(points)):
        for i2 in range(i1 + 1, len(points)):
            for i3 in range(i2 + 1, len(points)):
                p1 = points[i1]
                p2 = points[i2]
                p3 = points[i3]
                if (problem.get_distance(p1, p2)
                        and problem.get_distance(p1, p3)
                        and problem.get_distance(p2, p3)):
                    triangles.append((p1, p2, p3))
    for tri in triangles:
        for i in range(2):
            p = tri[i]
            pl = tri[(i + 1) % 3]
            pr = tri[(i + 2) % 3]
            if problem.get_distance(pl, pr) and random.random() < pangle:
                problem.rem_constraint(problem.get_distance(pl, pr))
                angle = angle_3p(problem.get_point(pl), problem.get_point(p),
                                 problem.get_point(pr))
                problem.add_constraint(AngleConstraint(pl, p, pr, angle))
    return problem
예제 #9
0
def buggy1():
    problem = GeometricProblem(dimension=2)
    p0 = "P0"
    p1 = "P1"
    p2 = "P2"
    p3 = "P3"
    problem.add_point(p2, vector([4.2516273494524803, -9.510959969336783]))
    problem.add_point(p3, vector([0.96994030830283862, -3.6416260233938491]))
    problem.add_point(p0, vector([6.6635607149389386, -8.5894325593219882]))
    problem.add_point(p1, vector([-0.06750282559988996, 6.6760454282229134]))
    problem.add_constraint(AngleConstraint(p1, p3, p0, 2.38643631762))
    problem.add_constraint(DistanceConstraint(p2, p0, 2.58198282856))
    problem.add_constraint(AngleConstraint(p1, p0, p2, -1.52046205861))
    problem.add_constraint(DistanceConstraint(p3, p1, 10.3696977989))
    problem.add_constraint(AngleConstraint(p3, p0, p1, 0.440080782652))
    return problem
예제 #10
0
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
예제 #11
0
def randomize_hedgehogs(problem):
    """combine adjacent angles to hedgehogs and replace with different angles.
       modifies problem
    """
    assert problem.dimension == 2
    angles = filter(lambda c: isinstance(c, AngleConstraint),
                    problem.cg.constraints())
    hogs = set()
    # make hogs from angles
    for angle in angles:
        vars = angle.variables()
        hog = (vars[1], frozenset([vars[0], vars[2]]))
        hogs.add(hog)
        # REMOVE CONSTRAINT
        problem.rem_constraint(angle)

    # combine hogs
    queue = list(hogs)
    while len(queue) > 0:
        hog1 = queue.pop()
        if hog1 not in hogs:
            continue
        cvar1 = hog1[0]
        xvars1 = hog1[1]
        for hog2 in hogs:
            if hog1 == hog2:
                continue
            cvar2 = hog2[0]
            xvars2 = hog2[1]
            if cvar1 == cvar2:
                shared = xvars1.intersection(xvars2)
                if len(shared) > 0:
                    hogs.remove(hog1)
                    hogs.remove(hog2)
                    newhog = (cvar1, xvars1.union(xvars2))
                    hogs.add(newhog)
                    queue.append(newhog)
                    break

    # rewrite hogs
    for hog in hogs:
        cvar = hog[0]
        xvars = hog[1]
        varlist = list(xvars)
        random.shuffle(varlist)
        for i in range(1, len(varlist)):
            v1 = varlist[i - 1]
            v2 = cvar
            v3 = varlist[i]
            # ADD CONSTRAINT
            problem.add_constraint(
                AngleConstraint(
                    v1, v2, v3,
                    angle_3p(problem.get_point(v1), problem.get_point(v2),
                             problem.get_point(v3))))

    return problem
예제 #12
0
def hog2():
    # several triangles with inter-angles (needs angle propagation)
    problem = GeometricProblem(dimension=2)
    problem.add_point('M', vector([0.0, 0.0]))
    problem.add_point('A', vector([0.0, 1.0]))
    problem.add_point('B', vector([1.0, 1.0]))
    problem.add_point('C', vector([2.0, 1.0]))
    problem.add_point('D', vector([3.0, 1.0]))
    problem.add_point('E', vector([4.0, 1.0]))
    problem.add_constraint(DistanceConstraint('A', 'M', 10.0))
    problem.add_constraint(DistanceConstraint('A', 'E', 10.0))
    problem.add_constraint(DistanceConstraint('B', 'E', 7.0))
    problem.add_constraint(DistanceConstraint('C', 'E', 6.0))
    problem.add_constraint(DistanceConstraint('D', 'E', 5.0))
    problem.add_constraint(AngleConstraint('A', 'M', 'B', math.pi / 20))
    problem.add_constraint(AngleConstraint('B', 'M', 'C', math.pi / 20))
    problem.add_constraint(AngleConstraint('D', 'M', 'C', math.pi / 20))
    problem.add_constraint(AngleConstraint('D', 'M', 'E', math.pi / 20))
    return problem
예제 #13
0
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
예제 #14
0
def test_mergehogs():
    diag_select(".")
    problem = GeometricProblem(dimension=2)
    problem.add_point('x', vector([0.0, 0.0]))
    problem.add_point('a', vector([1.0, 0.0]))
    problem.add_point('b', vector([0.0, 1.0]))
    problem.add_point('c', vector([-1.0, 0.0]))
    problem.add_point('d', vector([0.0, -1.0]))
    problem.add_constraint(AngleConstraint('a', 'x', 'b',
                                           30.0 / 180 * math.pi))
    problem.add_constraint(AngleConstraint('b', 'x', 'c',
                                           30.0 / 180 * math.pi))
    problem.add_constraint(AngleConstraint('c', 'x', 'd',
                                           30.0 / 180 * math.pi))
    solver = GeometricSolver(problem)
    print solver.dr
    for hog in solver.dr.hedgehogs():
        conf = list(solver.mg.get(hog))[0]
        print hog
        print conf
        print problem.verify(conf.map)
예제 #15
0
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
예제 #16
0
def _constraint_group(problem, group, dependend, angleratio):
    """Add constraints to problem to constrain given group of points. 
       Group may be optionally dependend on pair of points.
       Creates angle constraints with a given chance."""

    diag_print(
        "_constraint_group(group=" + str(group.keys()) + ",dep=" +
        str(dependend) + ")", "geometric._constraint_group")
    if len(group) == 2:
        if dependend == None:
            v1 = group.keys()[0]
            v2 = group.keys()[1]
            p1 = group[v1]
            p2 = group[v2]
            dist = distance_2p(p1, p2)
            con = DistanceConstraint(v1, v2, dist)
            diag_print("**Add constraint:" + str(con),
                       "geometric._constraint_group")
            problem.add_constraint(con)
    elif len(group) >= 3:
        # pick three points
        keys = group.keys()
        if dependend == None:
            v1 = random.choice(keys)
        else:
            v1 = dependend[0]
        keys.remove(v1)
        if dependend == None:
            v2 = random.choice(keys)
        else:
            v2 = dependend[1]
        keys.remove(v2)
        v3 = random.choice(keys)
        keys.remove(v3)
        # create three groups
        g = [{}, {}, {}]
        g[0][v1] = group[v1]
        g[0][v2] = group[v2]
        g[1][v1] = group[v1]
        g[1][v3] = group[v3]
        g[2][v2] = group[v2]
        g[2][v3] = group[v3]
        # distribute remaining points over groups
        while (len(keys) > 0):
            k = keys.pop()
            if dependend == None:
                i = random.randint(0, 2)
            else:
                i = random.randint(1, 2)
            g[i][k] = group[k]
        # compute facts from prototype
        p1 = group[v1]
        p2 = group[v2]
        p3 = group[v3]
        # group 0: if independend, add at least one independent group
        if dependend == None:
            _constraint_group(problem, g[0], None, angleratio)
        # group 1: random: angle constraint or independend group
        if random.random() > angleratio:
            _constraint_group(problem, g[1], None, angleratio)
        else:
            angle = angle_3p(p1, p2, p3)
            con = AngleConstraint(v1, v2, v3, angle)
            diag_print("**Add constraint:" + str(con),
                       "geometric._constraint_group")
            problem.add_constraint(con)
            _constraint_group(problem, g[1], [v1, v3], angleratio)
        # group 2: random: angle constraint, two configuratins, or independend group
        if random.random() > angleratio:
            _constraint_group(problem, g[2], None, angleratio)
        elif random.random() < 0.5:
            angle = angle_3p(p2, p1, p3)
            con = AngleConstraint(v2, v1, v3, angle)
            diag_print("**Add constraint:" + str(con),
                       "geometric._constraint_group")
            problem.add_constraint(con)
            _constraint_group(problem, g[2], [v2, v3], angleratio)
        else:
            angle = angle_3p(p2, p3, p1)
            con = AngleConstraint(v2, v3, v1, angle)
            diag_print("**Add constraint:" + str(con),
                       "geometric._constraint_group")
            problem.add_constraint(con)
            _constraint_group(problem, g[2], [v2, v3], angleratio)
예제 #17
0
def randomize_balloons(problem):
    """combine adjacent angles to balloons and replace with different angles.
       modifies problem
    """
    assert problem.dimension == 2
    angles = filter(lambda c: isinstance(c, AngleConstraint),
                    problem.cg.constraints())
    balloons = set()
    toremove = set()
    # make hogs from angles
    for angle1 in angles:
        cvar1 = angle1.variables()[1]
        for angle2 in angles:
            if angle2 == angle1: continue
            cvar2 = angle2.variables()[1]
            if cvar1 == cvar2: continue
            shared = set(angle1.variables()).intersection(angle2.variables())
            if len(shared) == 3:
                balloon = frozenset(angle1.variables())
                balloons.add(balloon)
                toremove.add(angle1)
                toremove.add(angle2)

    # remove constraints
    for con in toremove:
        problem.rem_constraint(con)

    print("initial balloons", balloons)

    # combine balloons
    queue = list(balloons)
    while len(queue) > 0:
        bal1 = queue.pop()
        if bal1 not in balloons:
            continue
        for bal2 in balloons:
            if bal1 == bal2:
                continue
            shared = bal1.intersection(bal2)
            if len(shared) >= 2:
                balloons.remove(bal1)
                balloons.remove(bal2)
                newbal = (bal1.union(bal2))
                balloons.add(newbal)
                queue.append(newbal)
                break

    print("combined balloons", balloons)

    # rewrite balloons
    for bal in balloons:
        # constrain first three points
        vars = list(bal)
        random.shuffle(vars)
        for i in range(2, len(vars)):
            lvars = vars[i - 2:i + 1]
            random.shuffle(lvars)
            problem.add_constraint(
                AngleConstraint(
                    lvars[0], lvars[1], lvars[2],
                    angle_3p(problem.get_point(lvars[0]),
                             problem.get_point(lvars[1]),
                             problem.get_point(lvars[2]))))
            problem.add_constraint(
                AngleConstraint(
                    lvars[1], lvars[2], lvars[0],
                    angle_3p(problem.get_point(lvars[1]),
                             problem.get_point(lvars[2]),
                             problem.get_point(lvars[0]))))

    return problem