Beispiel #1
0
def remove_hidden(shapes: Sequence[Collection]):
    """Remove shapes from (nested) list if they are entirely covered.

    Used to optimize SVG file without altering appearance, e.g. when
    randomly placing objects to fill a region.  Ignores opacity when
    determining overlap.

    Args:
        shapes: A list of shapes.

    """
    def process_list(l, cover):
        for i, item in reversed(list(enumerate(l))):
            if isinstance(item, list):
                process_list(item, cover)
            elif type(item) is Group:
                if len(item.clip) > 0:
                    keep_shapes_inside(item.members, shapes.clip)
                process_list(item.members, cover)
            else:
                shape = coverage(item)
                if shape.within(cover[0]):
                    del l[i]
                else:
                    cover[0] = cover[0].union(shape)

    # Pass list to recursive calls so coverage updates:
    cover = [SPoint((0, 0))]
    # Pack in list because 'shapes' can be single group:
    process_list([shapes], cover)
Beispiel #2
0
def coverage(obj: Collection) -> Union[SPolygon, SPoint, GeometryCollection]:
    """Create a shapely object.

    Used to calculate area/coverage.

    Args:
        obj: One or more shapes.

    Returns:
        A shapely object representing the union of coverage for all
        input shapes.

    """
    if type(obj) is list:
        cover = coverage(obj[0])
        for o in obj[1:]:
            cover = cover.union(coverage(o))
        return cover
    elif type(obj) in [Polygon, Spline, Line]:
        return SPolygon([pt.state() for pt in obj.points])
    elif type(obj) is Circle:
        c = obj.c.state()
        return SPoint(c[0], c[1]).buffer(obj.r.state())
    else:
        print("Can't get coverage for:", obj)
Beispiel #3
0
	def random_point(self):
		poly = wkb.loads(bytes(self.geom.data))
		(min_x, min_y, max_x, max_y) = poly.bounds
		while True:
			p = SPoint(random.uniform(min_x, max_x), random.uniform(min_y, max_y))
			if poly.contains(p):
				return p
Beispiel #4
0
def keep_points_inside(points: Sequence[Pnt], boundary: Collection):
    """Keep points that lie within a boundary.

    Args:
        points: A list of points.
        boundary: One or more shapes giving the boundary.

    """
    # reverse so deleting items doesn't affect loop
    for i, point in reversed(list(enumerate(points))):
        if not coverage(boundary).intersects(SPoint(point)):
            del points[i]
Beispiel #5
0
    def checkIfObjectInArea(objectPos: Point, field: Field):
        """Checks if object in area of map.
        Args:
            field: polygon defining the area
            objectPos (list): object x and y coordinates
        Returns:
            bool: True if object in area
        """
        point = SPoint(objectPos.reprTuple())

        (topLeft, topRight, bottomLeft, bottomRight) = field.reprTuple()

        polygon = SPolygon((bottomLeft, topLeft, topRight, bottomRight))

        return polygon.contains(point)
Beispiel #6
0
 def as_shapely(self) -> SPoint:
     """Use with caution! Convert this point to a shapely point."""
     # Shapely Point construction is expensive!
     # Note that before python3.8, @cached_property was not thread safe,
     # nor can it be used in a NamedTuple (which doesn't have a __dict__).
     # (Points can be used by multi-threaded client code, even when
     # SMARTS is still single-threaded, so we want to be safe here.)
     # So we use the private global _shapely_points as a cache instead.
     # Here we are relying on CPython's implementation of dict
     # to be thread-safe.
     cached = _shapely_points.get(self)
     if cached:
         return cached
     spt = SPoint((self.x, self.y, self.z))
     _shapely_points[self] = spt
     return spt
Beispiel #7
0
def sample_points_in_shape(shape: dict, n: int) -> List[Pnt]:
    """Sample random points inside a shape.

    Args:
        shape: A shape (currently works for polygons and splines).
        n: Number of points to sample.

    Returns:
        The sampled points.

    """
    bound = bounding_box(shape)
    points = []
    for i in range(n):
        while True:
            p = (
                np.random.uniform(bound[0], bound[2]),
                np.random.uniform(bound[1], bound[3]),
            )
            region = SPolygon([pt.state() for pt in shape.points])
            if SPoint(p[0], p[1]).within(region):
                points.append(p)
                break
    return points
Beispiel #8
0
def shapely_contains(point):
    point = SPoint(*point)
    for shape in shapes:
        if shape.contains(point) or shape.boundary.contains(point): return True
    return False
Beispiel #9
0
    for idx in correct_negatives:
        ax.add_patch(patches.Circle(points[idx], 3, color='xkcd:red'))

    for idx in false_negatives:
        ax.add_patch(patches.Circle(points[idx], 3, color='xkcd:red'))
    #     ax.text(points[idx][0]+3, points[idx][1]-3 , axtext(points[idx][0], points[idx][1]), fontsize=5, zorder=5)

    for idx in false_positives:
        ax.add_patch(patches.Circle(points[idx], 3, color='xkcd:green'))
    #     ax.text(points[idx][0]+3, points[idx][1]-3 , axtext(points[idx][0], points[idx][1]), fontsize=5, zorder=5)

    if len(false_negatives)> 0:
        test_point = points[false_negatives[0]]

        pt, spt = Point(*test_point), SPoint(*test_point)
        found = None
        for idx in range(len(obstacles.obss)):
            if obstacles.obss[idx].point_in_obstacle(pt) != shapes[idx].contains(spt):
                found = idx
                break

        if found is not None:
            idx = found
            print(idx)
            obstacle = obstacles.obss[idx]
            projection = Line(pt, Point(obstacle.x.max+5, pt.y))
            print(projection)
            num_cross  = 0
            for l in obstacle.lines:
                print(l, l.intersects(projection), projection.intersects(l))
Beispiel #10
0
 def endpoint(self):
     return SPoint(self.coords[-1])
Beispiel #11
0
 def startpoint(self):
     return SPoint(self.coords[0])
Beispiel #12
0
def ConvertShapeToPlacemark(shape, geoid, aland, awater, kml):
  #if len(shape.parts) > 1:
  #  print '----------geoid=%s aland=%s awater=%s' % (geoid, aland, awater)
  if shape.shapeType != 5:
    raise Exception('Unexpected shape type [%d] in file' % shape.shapeType)

  pm = KML.Placemark(
    KML.name('%s' % geoid),
    KML.styleUrl('#ts'),
    KML.ExtendedData(
      KML.Data(
        KML.displayName('ALAND'),
        KML.value(aland),
        name='string'
      ),
      KML.Data(
        KML.displayName('AWATER'),
        KML.value(awater),
        name='string'
      )
    ),
    KML.MultiGeometry(
      KML.Polygon(
        KML.extrude(0),
        KML.altitudeMode('clampToGround')
      )
    )
  )

  # The parentPoly will be used to append rings, and a
  # new Polygon will be appended for multiple rings in
  # a geography.
  parentPoly = pm.MultiGeometry.Polygon

  #if len(shape.parts) > 1:
  #  print 'shape has %d parts' % len(shape.parts)
  for i in range(0, len(shape.parts)):
    lo = shape.parts[i]
    hi = len(shape.points)
    if i < len(shape.parts) - 1:
      hi = shape.parts[i + 1]
    #if len(shape.parts) > 1:
    #  print 'shape has points in [%d, %d) of %d' % (lo, hi, len(shape.points))
    if (shape.points[lo][0] != shape.points[hi-1][0] or
        shape.points[lo][1] != shape.points[hi-1][1]):
      raise Exception('Loop endpoints in [%d, %d) do not match' % (lo, hi))
    coords = []
    for j in reversed(range(lo, hi)):
      lng = shape.points[j][0]
      lat = shape.points[j][1]
      coords.append([lng, lat])

    latlngCoords = []
    for c in coords:
      latlngCoords.append('%f,%f,0' % (c[0], c[1]))
    coordinates = ' '.join(latlngCoords)

    # Note: need LinearRing to compute ccw. Need Polygon to compute contains().
    spoly = SPolygon(coords)
    if i == 0:
      parentSpoly = spoly
    ring = polygon.LinearRing(coords)

    # Some sanity checks to make sure all rings are closed, non-empty,
    # and valid.
    if not ring.is_ring:
      raise Exception('Badly formatted non-ring : %s' % geoid)
    if ring.is_empty:
      raise Exception('Empty geometry found: %s' % geoid)
    if not ring.is_valid:
      raise Exception('Invalid ring: %s' % geoid)

    if not ring.is_ccw:
      # This ring is an internal (enclave) ring.
      rring = copy.deepcopy(ring)
      rring.coords = list(rring.coords)[::-1]
      # Shapely contains does not handle point-overlaps. This
      # means that enclaves which touch the containing ring
      # are not handled correctly. To cure this, we check two
      # points.
      if not (parentSpoly.contains(SPoint(rring.coords[0])) or
              parentSpoly.contains(SPoint(rring.coords[1]))):
        print 'Out-of-order enclave'
        # print 'ring %s does not contain %s' % (parentSpoly, ring)
        # print ring
        # print rring
        # Note: if this triggers, we will need to store the polys
        # to figure out which one is the enclosing one. Hopefully
        # the census files will not exhibit this, although it is
        # legal strictly according to the shapefule spec.
        raise Exception('Out-of-order enclave')
        coordinates = coordinates + ' 0,0,0'
        parentPoly.append(KML.innerBoundaryIs(
          KML.LinearRing(
            KML.coordinates(coordinates)
          )
        ))
      else:
        # Find the containing poly...
        parentPoly.append(KML.innerBoundaryIs(
         KML.LinearRing(
            KML.coordinates(coordinates)
          )
        ))
    else:
      if i > 0:
        # Set the new parent polygon ring.
        parentSpoly = spoly
        parentPoly = KML.Polygon(
          KML.extrude(0),
          KML.altitudeMode('clampToGround'))
        pm.MultiGeometry.append(parentPoly)
      parentPoly.append(KML.outerBoundaryIs(
        KML.LinearRing(
          KML.coordinates(coordinates)
        )
      ))

  return pm
Beispiel #13
0
 def CheckIfInsidePolygon(self, config, polygon):
     spoint = SPoint(point[0], point[1])
     return polygon.contains(spoint)
Beispiel #14
0
 def convert(self):
     return SPoint(self.x, self.y)
Beispiel #15
0
 def filter_func(tree):
     """Inner function to filter tree by geo coordinates."""
     return filter_poly.intersects(SPoint(tree.latitude, tree.longitude))