module NSWTopo module GeoJSON class MultiLineString include StraightSkeleton def freeze! each { } freeze end def path_length sum(&:path_length) end def nodes Nodes.new self end def offset(*margins, **options) linestrings = margins.inject nodes do |nodes, margin| nodes.progress limit: margin, **options.slice(:rounding_angle, :cutoff_angle) end.readout MultiLineString.new linestrings, @properties end def buffer(*margins, **options) MultiLineString.new(@coordinates + @coordinates.map(&:reverse), @properties).offset(*margins, **options) end def smooth(margin, **options) linestrings = nodes.tap do |nodes| nodes.progress **options.slice(:rounding_angle).merge(limit: margin) nodes.progress **options.slice(:rounding_angle, :cutoff_angle).merge(limit: -2 * margin) nodes.progress **options.slice(:rounding_angle, :cutoff_angle).merge(limit: margin) end.readout MultiLineString.new linestrings, @properties end def samples(interval) sampled = flat_map do |linestring| distance = linestring.path_length linestring.sample_at(interval) do |point, along, angle| [point, (2 * along - distance).abs - distance] end end.sort_by(&:last).map(&:first) MultiPoint.new sampled, @properties end def dissolve_points MultiPoint.new @coordinates.flatten(1), @properties end def subdivide(count) subdivided = flat_map do |linestring| linestring.each_cons(2).each_slice(count).map do |pairs| pairs.inject { |part, (p0, p1)| part << p1 } end end MultiLineString.new subdivided, @properties end def trim(amount) map do |feature| feature.trim amount end.reject(&:empty?).inject(empty_linestrings, &:+) end def to_polygon Polygon.new @coordinates, @properties end def to_multipolygon unclaimed, exterior_rings = partition(&:interior?) exterior_rings.sort_by(&:signed_area).map(&:to_polygon).map do |polygon| interior_rings, unclaimed = unclaimed.partition do |ring| polygon.contains? ring.first end interior_rings.inject(polygon, &:add_ring) end.inject(empty_polygons, &:+) end end end end