def _pointWithinThreshold(x, y, curve, eps): """ See whether *(x, y)* is within *eps* of *curve*. """ path = QPainterPath() path.addEllipse(x - eps, y - eps, 2 * eps, 2 * eps) curvePath = QPainterPath() if curve[-1].segmentType == "curve": p1, p2, p3, p4 = curve curvePath.moveTo(p1.x, p1.y) curvePath.cubicTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y) curvePath.cubicTo(p3.x, p3.y, p2.x, p2.y, p1.x, p1.y) else: first = curve[0] curvePath.moveTo(first.x, first.y) # PACK for fontTools pts = [] for pt in curve: pts.append((pt.x, pt.y)) # draw for pt1, pt2 in decomposeQuadraticSegment(pts[1:]): curvePath.quadTo(*pt1 + pt2) for pt1, pt2 in decomposeQuadraticSegment(list(reversed(pts[:-1]))): curvePath.quadTo(*pt1 + pt2) return path.intersects(curvePath)
def _pointWithinThreshold(x, y, curve, eps): """ See whether *(x, y)* is within *eps* of *curve*. """ path = QPainterPath() path.addEllipse(x - eps, y - eps, 2 * eps, 2 * eps) curvePath = QPainterPath() if curve[-1].segmentType == "curve": p1, p2, p3, p4 = curve curvePath.moveTo(p1.x, p1.y) curvePath.cubicTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y) curvePath.cubicTo(p3.x, p3.y, p2.x, p2.y, p1.x, p1.y) else: first = curve[0] curvePath.moveTo(first.x, first.y) # PACK for fontTools pts = [] for pt in curve: pts.append((pt.x, pt.y)) # draw for pt1, pt2 in decomposeQuadraticSegment(pts[1:]): curvePath.quadTo(*pt1+pt2) for pt1, pt2 in decomposeQuadraticSegment(list(reversed(pts[:-1]))): curvePath.quadTo(*pt1+pt2) return path.intersects(curvePath)
def intersects_with(self, point1: QPointF, point2: QPointF) -> bool: """Determines if the GraphicsEdge intersects with the cutline. Args: point1 (QPointF): The starting cutline point. point2 (QPointF): The ending cutline point. Returns: bool: True if the cutline intersects, False otherwise. """ cutpath = QPainterPath(point1) cutpath.lineTo(point2) path = self.calc_path() return cutpath.intersects(path)
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)