Beispiel #1
0
 def click (self, ev):
     def move (o, pos):
         if callable (o):
             o (pos)
         else:
             o.pos = pos
     pos = vector (self.area_view.screen_coord ((ev.x, ev.y)))
     if self.move is None:
         def move_a (pos):
             self.area_view.area.a = pos
         def move_b (pos):
             self.area_view.area.b = pos
         objs = [ [ self.area_view.area.a, 0.2, move_a ],
                 [ self.area_view.area.b, 0.2, move_b ] ]
         for o in self.area_view.area.table.obstacles:
             objs.append ([ o.pos, getattr (o, 'radius', 0.2), o ])
         for obj in objs:
             opos = vector (obj[0])
             radius = obj[1]
             if abs (opos - pos) < radius:
                 self.move = obj[2]
                 break
         if self.move is not None:
             move (self.move, None)
     else:
         move (self.move, pos)
         self.move = None
     self.update ()
Beispiel #2
0
 def rotate (self, ev):
     pos = vector (self.area_view.screen_coord ((ev.x, ev.y)))
     for o in self.area_view.area.table.obstacles:
         if o.pos is None or not hasattr (o, 'angle'):
             continue
         opos = vector (o.pos)
         if abs (opos - pos) < 0.2:
             o.angle += pi / 4
     self.update ()
 def inside (self, a):
     """If A is inside obstacle, return True."""
     # Map point in obstacle coordinates.
     u = vector.polar (self.angle, 1)
     o = vector (self.pos)
     a = vector (a)
     oa = a - o
     x = oa * u / (.5 * self.dim[0])
     y = oa * u.normal () / (.5 * self.dim[1])
     return x > -1 and x < 1 and y > -1 and y < 1
Beispiel #4
0
 def update (self, test, **kwargs):
     self.result = None
     if self.a is not None and self.b is not None:
         if test == 'intersect':
             def nearer (a, b): return a < b
             i = self.table.intersect (self.a, self.b, comp = nearer,
                     **kwargs)
             if i is not None:
                 a, b = vector (self.a), vector (self.b)
                 self.result = a + (b - a).unit () * i.distance
         elif test == 'nearest':
             n = self.table.nearest (self.b, **kwargs)
             if n is not None:
                 self.result = n.pos
Beispiel #5
0
def segment_segment (a, b, c, d):
    """Find intersection between [AB] and [CD] line segments.  Return i such
    that A + i * (B - A).unit () gives this intersection.  Return None if no
    intersection found.

    If line segments are parallel or collinear, None is returned.
    """
    a, b, c, d = vector (a), vector (b), vector (c), vector (d)
    # For each point P on the line segment [AB], there is a real u in [0, 1]
    # for which P = A + u (B - A)
    #
    # An intersection point must be on both line segments:
    #
    # A + u (B - A) = C + v (D - C)
    #
    # xa + u (xb - xa) = xc + v (xd - xc)
    # ya + u (yb - ya) = yc + v (yd - yc)
    # 
    #     (xc - xa) (yd - yc) - (xd - xc) (yc - ya)
    # u = -----------------------------------------
    #     (xb - xa) (yd - yc) - (xd - xc) (yb - ya)
    #     (xc - xa) (yb - ya) - (xb - xa) (yc - ya)
    # v = -----------------------------------------
    #     (xb - xa) (yd - yc) - (xd - xc) (yb - ya)
    #
    # u = (vac.normal() . vcd) / (vab.normal() . vcd)
    # v = (vac.normal() . vab) / (vab.normal() . vcd)
    #
    # If vab.normal() . vcd is 0, AB and CD are parallel.
    vab = b - a
    vcd = d - c
    vac = c - a
    # Cannot test for 0 because we are using float, cannot test for a very
    # small number because we do not know what is small enough, therefore,
    # compare with numerator.
    den = vab.normal () * vcd
    unum = vac.normal () * vcd
    if abs (den) <= 1e-6 * abs (unum):
        return None
    else:
        u = unum / den
        if u >= 0 and u <= 1:
            v = vac.normal () * vab / den
            if v >= 0 and v <= 1:
                return u * vab.norm ()
    return None
Beispiel #6
0
 def __arm_notified (self):
     if self.arm_cyl.pos > .9:
         push_point = (vector (self.robot_position.pos)
                 + vector.polar (self.robot_position.angle - pi / 2, side + 100)
                 - vector.polar (self.robot_position.angle, 100))
         gift = self.table.nearest (push_point, level = 0, max = 150)
         if gift is not None and hasattr (gift, 'state'):
             gift.state = True
             gift.notify ()
     self.notify ()
Beispiel #7
0
 def __door_notified (self):
     self.door = self.door_cylinder.pos # 1. is open.
     if self.door > 0.5 and self.load:
         for e in self.load:
             e.pos = (vector (self.robot_position.pos)
                     - vector.polar (self.robot_position.angle
                         + random.uniform (-pi/8, pi/8),
                         200 + random.uniform (0, 70)))
             e.notify ()
         self.load = [ ]
     self.notify ()
Beispiel #8
0
 def __pot_notified (self):
     self.firing = self.pot.wiper[0] > .5
     if self.cherries and self.firing:
         m = TransMatrix ()
         m.translate (self.robot_position.pos)
         m.rotate (self.robot_position.angle)
         hit = vector (*m.apply (self.cannon_hit))
         for c in self.cherries:
             c.pos = hit + vector.polar (random.uniform (-pi, pi),
                     random.uniform (0, 50))
             c.notify ()
         self.table.cherries.cherries.extend (self.cherries)
         self.table.cherries.notify ()
         self.cherries = [ ]
     self.notify ()
 def intersect(self, a, b):
     """If the segment [AB] intersects the obstacle, return distance from a
     to intersection point, else, return None."""
     if self.pos is None:
         return None
     a, b = vector(a), vector(b)
     vab = b - a
     ab = abs(vab)  # distance AB.
     n = vab.unit()  # vector of length 1.
     o = vector(self.pos)  # obstacle center.
     # To check if the line (AB) intersects the circle, compute distance
     # from circle center to line using a dot product.
     vao = o - a  # vector AO.
     # abs of dot product.
     doc = abs(vao * n.normal())
     if doc < self.radius:
         # Line intersects, check if segment intersects.
         m = vao * n
         f = sqrt(self.radius ** 2 - doc ** 2)
         if m - f > 0 and m - f < ab:
             return m - f
         elif m + f > 0 and m + f < ab:
             return m + f
     return None
 def intersect (self, a, b):
     """If the segment [AB] intersects the obstacle, return distance from a
     to intersection point, else, return None."""
     if self.pos is None or self.angle is None:
         return None
     # Find intersection with each rectangle segments.  There is at most
     # two intersections, return the nearest.
     u = vector.polar (self.angle, self.dim[0] / 2.)
     v = vector.polar (self.angle + pi / 2, self.dim[1] / 2.)
     o = vector (self.pos)
     p1 = o + u + v
     p2 = o - u + v
     p3 = o - u - v
     p4 = o + u - v
     found = None
     for c, d in ((p1, p2), (p2, p3), (p3, p4), (p4, p1)):
         i = simu.utils.intersect.segment_segment (a, b, c, d)
         if i is not None:
             if found is not None:
                 found = min (found, i)
                 break
             else:
                 found = i
     return found
Beispiel #11
0
 def __plate_drop_point (self):
     return (vector (self.robot_position.pos)
             + vector (-back - 85, -35).rotate (self.robot_position.angle))
Beispiel #12
0
    den = vab.normal () * vcd
    unum = vac.normal () * vcd
    if abs (den) <= 1e-6 * abs (unum):
        return None
    else:
        u = unum / den
        if u >= 0 and u <= 1:
            v = vac.normal () * vab / den
            if v >= 0 and v <= 1:
                return u * vab.norm ()
    return None

if __name__ == '__main__':
    import sys
    import math
    v00 = vector (0, 0)
    v02 = vector (0, 2)
    v20 = vector (2, 0)
    v22 = vector (2, 2)
    v44 = vector (4, 4)
    failed = 0
    verbose = True
    def check (test, result):
        r = eval (test)
        if r != result:
            print test, 'is', r, 'but expected', result
            return 1
        elif verbose:
            print test, 'is', r, 'as expected'
            return 0
    v2 = math.sqrt (2)