def shootToWay(tw): return functools.reduce( min, ((l, ti) for ti, (l, s) in ((i, osmcmd.Segment(rpt1, rpt2).intersect( osmcmd.Segment.fromNodes( data.nodes[tw[OsmData.REF][i]], data.nodes[tw[ OsmData.REF][i + 1]]))) for i in range(len(tw[OsmData.REF]) - 1)) if s > 0 and s < 1 and l > 0), (float('inf'), None))
def testSegmentIntersectX(self): s1 = osmcmd.Segment(Pt(0, 0), Pt(2, 2)) s2 = osmcmd.Segment(Pt(1, 0), Pt(0, 1)) d1, d2 = s1.intersect(s2) self.assertAlmostEqual(d1, 0.25) self.assertAlmostEqual(d2, 0.5)
def testSegmentProject(self): s1 = osmcmd.Segment(Pt(0, 0), Pt(2, 0)) l, s = s1.project(Pt(1, 1)) self.assertAlmostEqual(l, -1) self.assertAlmostEqual(s, 0.5)
def getPoiAndEntranceLocations(poiPoint, buildingChain, offsetLength): entrancePoint, buildingChainIndices = getClosestPointOnChain( poiPoint, buildingChain) if offsetLength < (poiPoint - entrancePoint).length: # pull mode newPoiPoint = entrancePoint + (poiPoint - entrancePoint).dir(offsetLength) return newPoiPoint, entrancePoint, buildingChainIndices # push mode pusher0 = None pusher1 = None p = poiPoint def pushByPoint( wp): # invalidates l1,s1, but it shouldn't affect the result return p + (p - wp).dir(offsetLength * delta) def pushBySegment( l, seg): # invalidates l1,s1, but it shouldn't affect the result nv = ((seg.p1 - seg.p2).rot90() * l).dir(offsetLength * delta) return p + nv for nIterations in range(maxIterations): isModified = False def recordPush(pusher): nonlocal isModified, pusher0, pusher1 isModified = True pusher0 = pusher1 pusher1 = pusher if buildingChain.isClosed: l1, s1 = buildingChain.segments[-1].project(p) else: l1, s1 = buildingChain.segments[0].rev().project(p) for i, seg in enumerate(buildingChain.segments): l0, s0 = l1, s1 l1, s1 = seg.project(p) if s0 > 1 and s1 < 0 and (p - seg.p1).length < offsetLength - epsilon: p = pushByPoint(seg.p1) recordPush((i, )) if 0 <= s1 <= 1 and abs(l1) < offsetLength - epsilon: p = pushBySegment(l1, seg) recordPush((i, i + 1)) if not buildingChain.isClosed: l0, s0 = l1, s1 l1, s1 = seg.rev().project(p) if s0 > 1 and s1 < 0 and (p - seg.p1).length < offsetLength - epsilon: p = pushByPoint(seg.p1) recordPush((i, )) if not isModified: break if pusher1 is None: return p, None, None elif len(pusher1) == 1: return p, buildingChain.points[pusher1[0]], pusher1 elif len(pusher1) == 2 and (pusher0 is None or len(pusher0) == 1 or pusher0 == pusher1): wp1 = buildingChain.points[pusher1[0]] wp2 = buildingChain.points[pusher1[1]] l, s = osmcmd.Segment(wp1, wp2).project(p) ep = wp1 + (wp2 - wp1) * s return p, ep, pusher1 elif len(pusher1) == 2 and len(pusher0) == 2: if pusher1[1] == pusher0[0]: pusher0, pusher1 = pusher1, pusher0 if pusher0[1] == pusher1[0]: return p, buildingChain.points[pusher1[0]], (pusher1[0], ) else: return p, None, None else: return p, None, None