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))
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
 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)
Ejemplo n.º 4
0
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