Example #1
0
 def reflect(self):
     a = self._points[0] - self._position
     b = self._points[2] - self._position
     c = (a - b).normalized()
     a = self._points[1] - self._position
     b = self._points[3] - self._position
     a = 2 * QVector2D.dotProduct(a, c) * c - a
     b = 2 * QVector2D.dotProduct(b, c) * c - b
     self._points[1] = a + self._position
     self._points[3] = b + self._position
 def isBetween(self, p1, p2, max_offset, offsetBeyondEnds=False):
     if offsetBeyondEnds and any(
             self.distanceTo(p) <= max_offset for p in (p1, p2)):
         return True
     q = self.toQPointF()
     q1 = p1.toQPointF()
     q2 = p2.toQPointF()
     vp1p2 = QVector2D(q2 - q1)
     return QVector2D.dotProduct(vp1p2, QVector2D(q - q1)) >= 0 \
      and QVector2D.dotProduct(vp1p2, QVector2D(q - q2)) <= 0 \
      and QVector2D(q).distanceToLine(QVector2D(q1), vp1p2.normalized()) <= max_offset
 def orthProj(self, p1, p2):
     q1 = p1.toQPointF()
     q2 = p2.toQPointF()
     vdir = QVector2D(q2 - q1).normalized()
     vq1q = QVector2D(self.toQPointF() - q1)
     vq1h = QVector2D.dotProduct(vq1q, vdir) * vdir
     return RadarCoords.fromQPointF(q1 + QPointF(vq1h))
Example #4
0
 def rotate(self, direction):
     theta = -2.0 / 360.0
     points = []
     a = QVector2D(math.cos(theta), -math.sin(theta))
     b = QVector2D(math.sin(theta), math.cos(theta))
     c = QVector2D(math.cos(-theta), -math.sin(-theta))
     d = QVector2D(math.sin(-theta), math.cos(-theta))
     if direction:
         for i in self._points:
             x = QVector2D.dotProduct(i - self._position, a)
             y = QVector2D.dotProduct(i - self._position, b)
             points.append(QVector2D(x, y) + self._position)
         self._points = points
     else:
         for i in self._points:
             x = QVector2D.dotProduct(i - self._position, c)
             y = QVector2D.dotProduct(i - self._position, d)
             points.append(QVector2D(x, y) + self._position)
         self._points = points
Example #5
0
    def mouseMoveEvent(self, event):
        if self.__dragActive:
            mousePos = self.view.mapToScene(self.view.mapFromGlobal(QCursor.pos()))
            vec1 = QVector2D(mousePos)
            vec1.normalize()
            trans = QTransform()
            trans.rotate(self.rotation())
            vec2 = QVector2D(self.p2 * trans)
            vec2.normalize()
            angle = math.acos(max(-1, min(1, QVector2D.dotProduct(vec1, vec2)))) * 180 / math.pi

            # clockwise rotation
            if vec1.y() * vec2.x() < vec1.x() * vec2.y():
                angle *= -1

            angle = (self.rotation() + angle) % 360
            self.setRotation(angle)
Example #6
0
    def mouseMoveEvent(self, event):
        if self.__dragActive:
            mousePos = self.view.mapToScene(self.view.mapFromGlobal(QCursor.pos()))
            vec1 = QVector2D(mousePos)
            vec1.normalize()
            trans = QTransform()
            trans.rotate(self.rotation())
            vec2 = QVector2D(self.p2 * trans)
            vec2.normalize()
            angle = math.acos(max(-1, min(1, QVector2D.dotProduct(vec1, vec2)))) * 180 / math.pi

            # clockwise rotation
            if vec1.y() * vec2.x() < vec1.x() * vec2.y():
                angle *= -1

            angle = (self.rotation() + angle) % 360
            self.setRotation(angle)
Example #7
0
    def intersectsCircle(self, position, rect, size):
        size_sqr = size**2
        scene_translation = self.startSocket().sceneTransform()
        connection_rect = scene_translation.mapRect(self._rect)

        # Line circle intersection test http://i.stack.imgur.com/P556i.png
        if connection_rect.contains(rect) or (
                connection_rect.width() <= size
                or connection_rect.height() <= size):
            connection_path = scene_translation.map(self._path)
            simplified_path = connection_path.simplified()

            element_count = simplified_path.elementCount() - 1

            # In case path is linear
            if element_count == -1:
                simplified_path = connection_path
                element_count = simplified_path.elementCount()

            previous_point = None
            for i in range(element_count):
                element = simplified_path.elementAt(i)
                point = QPointF(element.x, element.y)

                previous_point, _previous_point = point, previous_point

                if _previous_point is None:
                    continue

                to_position = QVector2D(position - _previous_point)
                to_end = QVector2D(point - _previous_point)

                to_end_length = to_end.length()
                if not to_end_length:
                    continue

                projection = QVector2D.dotProduct(to_position,
                                                  to_end) / to_end_length

                # Projected point lies within this segment
                if 0 <= projection <= to_end_length:
                    dist_path_sqr = to_position.lengthSquared() - projection**2

                    if dist_path_sqr < size_sqr:
                        return self
Example #8
0
    def chooseMove(self, init_position, sectors, borders=None):
        smax, lrange, hrange = self.findTarget(sectors)

        best_path = None
        #print ("target", target)
        #print (angle)

        steps = 5
        # FIXME se il fantino e` preciso fare uno scan ulteriore
        # intorno a +- 2.5 gradi dal best (da valutare con semaring dovuto al cavallo)
        for anAngle in range(lrange, hrange, steps):
            collisions = 0
            origin = QVector2D(self.pos.x(), self.pos.y())
            min_dist = origin.distanceToPoint(self.target)
            current_best = [min_dist, 0, origin, anAngle]
            #print("Angolo", anAngle, origin)
            path = QPainterPath()
            path.addEllipse(origin.toPoint(), 20, 20)
            dv = QVector2D(math.cos(math.radians(anAngle)), math.sin(math.radians(anAngle)))
            #print ("dV", dv)
            #print ("orig", origin)
            # for it in self.scene().items():
            #     if it.type() == QGraphicsItem.UserType + 2:
            #         if it == self:
            #             continue
            #         print (it.boundingRect())
            #         pen = QPen(Qt.red, 5, Qt.SolidLine)
            #         self.scene().addPath(it.shape(), pen)
            #         if path.intersects(it.shape()):
            #             print("COLLISION ", it.id)
            # return

            iterS = 0
            while iterS <= int(smax):
            #for i in range(int(smax)):
                origin += dv
                #print ("origin", iterS, origin)
                path.moveTo(origin.toPoint())

                for it in self.scene().items():
                    if it.type() == QGraphicsItem.UserType + 2:
                        if it == self:
                            continue
                        if path.intersects(it.mapToScene(it.shape())):
                            collisions += 1
                            #print ("COLLISION ", it.id)
                            r = QVector2D(it.pos.x() - origin.x(), it.pos.y() - origin.y()).normalized()
                            cos_theta = QVector2D.dotProduct(dv, r)
                            dv_mod_squared = (smax - iterS) * 2 * self.FRICTION * cos_theta * cos_theta
                            #print ("before ", iterS, dv_mod_squared)
                            #print (cos_theta, r)
                            dv_coll = cos_theta * r
                            dv -= dv_coll
                            origin += dv
                            iterS += 0.5 * dv_mod_squared / self.FRICTION
                            #print ( "after ", iterS, smax)
                            #print ("new dv ", dv)
                            break

                # FIXME loop solo sui bordi associati al settore
                for ib, b in enumerate(borders):
                    #FIXME riduci velocita in caso di urto
                    #print ("border ", ib)
                    if path.intersects(b.boundingRect()):
                        #print ("Collision ", ib)
                        new_angle = collisionAngle2(b.line, QLineF((origin+22*dv).toPointF(), origin.toPointF()))
                        #print ("NEW ANGLE ", new_angle)
                        dv = QVector2D(math.cos(new_angle), math.sin(new_angle))
                        #cos_theta = abs(math.cos(math.radians(angle)))
                        #print("angle after: ", angle, cos_theta)

                        # simulare perdita di energia nel rimbalzo
                        #print ("intersect with:", ib, path.currentPosition())
                        #cos_theta = QVector2D.dotProduct(b.direction, dv)
                        #print ("angle after: ", math.degrees(math.acos(cos_theta)))
                        #dv -= 2 * dv * cos_theta
                        #dv = dv.normalized()
                        #print ("dv ", dv)
                        origin += dv
                        break
                #print (collisions)
                tmp_dist = origin.distanceToPoint(self.target) #+ collisions * 200
                #print (tmp_dist)
                if tmp_dist < min_dist:
                    min_dist = tmp_dist
                    current_best = [min_dist, iterS, origin, anAngle]
                    #print (current_best)
                iterS += 1

            #current_best[0] += 0.5*origin.distanceToPoint(sectors[self.currentSector+1].guide)
            sect = -1
            for iSector, s in enumerate(sectors):
                if s.isIn(origin.toPointF()):
                    sect = iSector
                    break
            me = [sect, origin.distanceToPoint(sectors[sect+1].guide)]
            overtakes = 0
            for it in self.scene().items():
                if it == self:
                    continue
                if it.type() == QGraphicsItem.UserType + 2:
                    sect = -1
                    for iSector, s in enumerate(sectors):
                        if s.isIn(origin.toPointF()):
                            sect = iSector
                            break
                    if sect < me[0]:
                        overtakes += 1
                    elif sect == me[0]:
                        dist = it.pos.distanceToPoint(sectors[sect+1].guide)
                        if dist > me[1]:
                            overtakes += 1
            # FIXME modulare questo numero in base alla posizione
            # se e` dietro se ne frega delle collisioni
            delta = - collisions * 100
            print (delta)
            if (10 - overtakes) < init_position:
                delta += (init_position - 10 + overtakes) * 20
                print (delta)

            current_best[0] -= delta
            print ("{}".format(self.id), current_best, self.target, origin)
            if best_path is None:
                best_path = current_best
            else:
                if current_best[0] < best_path[0]:
                    best_path = current_best
                elif abs(current_best[0] - best_path[0])/current_best[0] < 0.05:
                    if current_best[1] < best_path[1]:
                        best_path = current_best

        # salva il percorso con minore distanza dalla guida (poi aggiungere la distanza anche dal prossimo punto)
        #                       minore spazio percorso
            #self.scene().addLine(QLineF(self.pos.x(), origin.x(), self.pos.y(), origin.y()))
        #speed = 40
        #direction = -85
        print ("BEST ", best_path)
        speed = math.sqrt(2*best_path[1]*self.FRICTION)
        #print (speed)
        #self.min_dist = best_path[0]
        # FIXME errore casuale gaussiano in base alla precisione
        # del cavallo
        self.initKinematics(best_path[3], speed)
Example #9
0
    def move(self, sectors):
        #print ("{} {}".format(self.id, (self.v.length())))
        if self.v.length() < 3.5:
            self.v = QVector2D()
            #self.scene().move_ended.emit()
            return
            #print ("{} non si muove".format(self.id))
            #return
        #else:
        #    print ("{} v: {}".format(self.id, self.v.length()))

        #smax = self.v.length() * self.dt
        #orig_pos = self.pos
        steps = 1
        self.setRotation(math.degrees(math.atan2(self.v.y(), self.v.x())))

        for _ in range(steps):
            ds = self.v * self.dt / steps
            newpos = self.pos + ds
            items = self.scene().collidingItems(self)
            #print ("COLLISIONI ", len(items), newpos)
            if len(items) != 0:
                for it in items:
                    if it.type() == QGraphicsItem.UserType + 1:
                        tmp = (self.pos + 22*self.v.normalized())
                        test = QLineF(tmp.x(), tmp.y(), self.pos.x(), self.pos.y())
                        #print ("test", test)
                        new_angle = collisionAngle2(it.line, test)
                        #cos_theta = abs(math.cos(math.radians(angle)))
                        #self.v -= 2 * self.v * cos_theta
                        self.v = self.v.length() * QVector2D(math.cos(new_angle), math.sin(new_angle))
                        ds = self.v * self.dt / steps
                        newpos = self.pos + ds
                        break
                    elif it.type() == QGraphicsItem.UserType + 2:
                        #print ("COLLISION ", it.id)
                        r = QVector2D(it.pos.x() - self.pos.x(), it.pos.y() - self.pos.y()).normalized()
                        cos_theta = QVector2D.dotProduct(self.v.normalized(), r)
                        #print (cos_theta, r, self.v)
                        if cos_theta > 0:
                            #self.setRotation(math.degrees(new_angle))
                            delta_v = self.v.length() * cos_theta * r
                            self.v -= delta_v
                            it.v += delta_v
                            newpos = it.pos + it.v * self.dt/steps
                            it.setPos(newpos.toPointF())
                            ds = self.v * self.dt / steps
                            newpos = self.pos + ds

            #print ("POST BREAK")
            self.currentFrame -= int(ds.length())
            if self.currentFrame < 0:
                self.currentFrame = 99 #self.currentFrame % 100
            self.update(0, 0, self.RADIUS, self.RADIUS)

            self.pos = newpos
            #print (newpos)
            self.setPos(self.pos.toPoint()) #self.mapToParent(0, -(3 + math.sin(self.speed) * 3)))

        #print ("deltaV ", self.dt * self.FRICTION / steps)
        self.v -= self.v.normalized() * self.dt * self.FRICTION / steps
        if self.v.length() < 3.5:
            self.v = QVector2D()
            self.scene().move_ended.emit()

        if sectors[self.currentSector + 1].isIn(self.pos.toPointF()):
            self.currentSector += 1
            self.target = sectors[self.currentSector].guide
            print ("TARGET SET ", self.target)
        if sectors[self.currentSector].isFinish:
            self.scene().race_ended.emit(self.id)