nswtopo 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/nswtopo +20 -4
- data/docs/contours.md +2 -0
- data/docs/relief.md +2 -3
- data/docs/spot-heights.md +2 -0
- data/lib/nswtopo/archive.rb +6 -3
- data/lib/nswtopo/chrome.rb +9 -6
- data/lib/nswtopo/commands/layers.rb +2 -2
- data/lib/nswtopo/config.rb +1 -0
- data/lib/nswtopo/formats/gemf.rb +1 -0
- data/lib/nswtopo/formats/kmz.rb +16 -10
- data/lib/nswtopo/formats/mbtiles.rb +1 -0
- data/lib/nswtopo/formats/pdf.rb +4 -3
- data/lib/nswtopo/formats/svg.rb +5 -13
- data/lib/nswtopo/formats/svgz.rb +1 -0
- data/lib/nswtopo/formats/zip.rb +5 -4
- data/lib/nswtopo/formats.rb +35 -36
- data/lib/nswtopo/geometry/r_tree.rb +24 -23
- data/lib/nswtopo/geometry/straight_skeleton/node.rb +4 -4
- data/lib/nswtopo/geometry/straight_skeleton/nodes.rb +51 -40
- data/lib/nswtopo/geometry/straight_skeleton/split.rb +2 -2
- data/lib/nswtopo/geometry/vector.rb +55 -49
- data/lib/nswtopo/geometry.rb +0 -5
- data/lib/nswtopo/gis/arcgis/layer/map.rb +11 -10
- data/lib/nswtopo/gis/arcgis/layer/query.rb +8 -10
- data/lib/nswtopo/gis/arcgis/layer.rb +7 -11
- data/lib/nswtopo/gis/dem.rb +3 -2
- data/lib/nswtopo/gis/gdal_glob.rb +3 -3
- data/lib/nswtopo/gis/geojson/collection.rb +60 -14
- data/lib/nswtopo/gis/geojson/line_string.rb +142 -1
- data/lib/nswtopo/gis/geojson/multi_line_string.rb +49 -7
- data/lib/nswtopo/gis/geojson/multi_point.rb +87 -0
- data/lib/nswtopo/gis/geojson/multi_polygon.rb +35 -23
- data/lib/nswtopo/gis/geojson/point.rb +16 -1
- data/lib/nswtopo/gis/geojson/polygon.rb +69 -7
- data/lib/nswtopo/gis/geojson.rb +92 -46
- data/lib/nswtopo/gis/projection.rb +5 -1
- data/lib/nswtopo/helpers/thread_pool.rb +39 -0
- data/lib/nswtopo/helpers.rb +44 -5
- data/lib/nswtopo/layer/arcgis_raster.rb +4 -6
- data/lib/nswtopo/layer/contour.rb +24 -26
- data/lib/nswtopo/layer/control.rb +5 -3
- data/lib/nswtopo/layer/declination.rb +14 -10
- data/lib/nswtopo/layer/feature.rb +5 -5
- data/lib/nswtopo/layer/grid.rb +19 -18
- data/lib/nswtopo/layer/labels/barriers.rb +23 -0
- data/lib/nswtopo/layer/labels/convex_hull.rb +12 -0
- data/lib/nswtopo/layer/labels/convex_hulls.rb +86 -0
- data/lib/nswtopo/layer/labels/label.rb +63 -0
- data/lib/nswtopo/layer/labels.rb +192 -315
- data/lib/nswtopo/layer/overlay.rb +11 -12
- data/lib/nswtopo/layer/raster.rb +1 -0
- data/lib/nswtopo/layer/relief.rb +6 -4
- data/lib/nswtopo/layer/spot.rb +11 -17
- data/lib/nswtopo/layer/{vector → vector_render}/cutout.rb +1 -1
- data/lib/nswtopo/layer/{vector → vector_render}/knockout.rb +2 -3
- data/lib/nswtopo/layer/{vector.rb → vector_render.rb} +20 -45
- data/lib/nswtopo/layer.rb +2 -1
- data/lib/nswtopo/map.rb +70 -56
- data/lib/nswtopo/svg.rb +5 -0
- data/lib/nswtopo/tiled_web_map.rb +3 -3
- data/lib/nswtopo/tree_indenter.rb +2 -2
- data/lib/nswtopo/version.rb +1 -1
- data/lib/nswtopo.rb +4 -0
- metadata +15 -17
- data/lib/nswtopo/geometry/overlap.rb +0 -47
- data/lib/nswtopo/geometry/segment.rb +0 -27
- data/lib/nswtopo/geometry/vector_sequence.rb +0 -180
- data/lib/nswtopo/helpers/array.rb +0 -19
- data/lib/nswtopo/helpers/concurrently.rb +0 -27
- data/lib/nswtopo/helpers/dir.rb +0 -7
- data/lib/nswtopo/helpers/hash.rb +0 -15
- data/lib/nswtopo/helpers/tar_writer.rb +0 -11
- data/lib/nswtopo/layer/labels/barrier.rb +0 -39
@@ -0,0 +1,86 @@
|
|
1
|
+
module NSWTopo
|
2
|
+
module Labels
|
3
|
+
class ConvexHulls < GeoJSON::MultiLineString
|
4
|
+
def initialize(feature, buffer, &block)
|
5
|
+
coordinates = case feature
|
6
|
+
when GeoJSON::Polygon then feature.rings
|
7
|
+
when GeoJSON::MultiPolygon then feature.rings
|
8
|
+
else feature
|
9
|
+
end.explode.flat_map do |feature|
|
10
|
+
case feature
|
11
|
+
when GeoJSON::Point # a point feature barrier
|
12
|
+
x, y = *feature
|
13
|
+
[[Vector[x-buffer, y-buffer], Vector[x+buffer, y-buffer], Vector[x+buffer, y+buffer], Vector[x-buffer, y+buffer]]]
|
14
|
+
when GeoJSON::LineString # a linestring label to be broken down into segment hulls
|
15
|
+
offsets = feature.each_cons(2).map do |p0, p1|
|
16
|
+
(p1 - p0).perp.normalised * buffer
|
17
|
+
end
|
18
|
+
corners = offsets.then do |offsets|
|
19
|
+
feature.closed? ? [offsets.last, *offsets, offsets.first] : [offsets.first, *offsets, offsets.last]
|
20
|
+
end.each_cons(2).map do |o01, o12|
|
21
|
+
next if o12.cross(o01) == 0
|
22
|
+
(o01 + o12).normalised * buffer * (o12.cross(o01) <=> 0)
|
23
|
+
end.each_cons(2)
|
24
|
+
feature.each_cons(2).zip(corners, offsets).map do |(p0, p1), (c0, c1), offset|
|
25
|
+
if c0 then [p0 + offset, p0 + c0, p0 - offset] else [p0 + offset, p0 - offset] end +
|
26
|
+
if c1 then [p1 - offset, p1 + c1, p1 + offset] else [p1 - offset, p1 + offset] end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
super coordinates, &block
|
31
|
+
end
|
32
|
+
|
33
|
+
delegate :length => :@coordinates
|
34
|
+
|
35
|
+
def each(&block)
|
36
|
+
enum = Enumerator.new do |yielder|
|
37
|
+
@coordinates.each do |coordinates|
|
38
|
+
yielder << ConvexHull.new(self, coordinates)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
block_given? ? enum.each(&block) : enum
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.overlap?(ring0, ring1, buffer)
|
45
|
+
# implements Gilbert–Johnson–Keerthi
|
46
|
+
simplex = [ring0.first - ring1.first]
|
47
|
+
perp = simplex[0].perp
|
48
|
+
loop do
|
49
|
+
return true unless case
|
50
|
+
when simplex.one? then simplex[0].norm
|
51
|
+
when simplex.inject(&:-).dot(simplex[1]) > 0 then simplex[1].norm
|
52
|
+
when simplex.inject(&:-).dot(simplex[0]) < 0 then simplex[0].norm
|
53
|
+
else simplex.inject(&:cross).abs / simplex.inject(&:-).norm
|
54
|
+
end > buffer
|
55
|
+
max = ring0.max_by { |point| perp.cross point }
|
56
|
+
min = ring1.min_by { |point| perp.cross point }
|
57
|
+
support = max - min
|
58
|
+
return false unless (simplex[0] - support).cross(perp) > 0
|
59
|
+
rays = simplex.map { |point| point - support }
|
60
|
+
case simplex.length
|
61
|
+
when 1
|
62
|
+
case
|
63
|
+
when rays[0].dot(support) > 0
|
64
|
+
simplex, perp = [support], support.perp
|
65
|
+
when rays[0].cross(support) < 0
|
66
|
+
simplex, perp = [support, *simplex], rays[0]
|
67
|
+
else
|
68
|
+
simplex, perp = [*simplex, support], -rays[0]
|
69
|
+
end
|
70
|
+
when 2
|
71
|
+
case
|
72
|
+
when rays[0].cross(support) > 0 && rays[0].dot(support) < 0
|
73
|
+
simplex, perp = [simplex[0], support], -rays[0]
|
74
|
+
when rays[1].cross(support) < 0 && rays[1].dot(support) < 0
|
75
|
+
simplex, perp = [support, simplex[1]], rays[1]
|
76
|
+
when rays[0].cross(support) <= 0 && rays[1].cross(support) >= 0
|
77
|
+
return true
|
78
|
+
else
|
79
|
+
simplex, perp = [support], support.perp
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module NSWTopo
|
2
|
+
module Labels
|
3
|
+
class Label < ConvexHulls
|
4
|
+
def self.knockout(value)
|
5
|
+
Float(Numeric === value ? value : value ? Config.fetch("knockout", 0.3) : 0)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(baselines, feature, priority, elements, along: nil, fixed: nil, &block)
|
9
|
+
super baselines, 0.5 * feature["font-size"] do
|
10
|
+
@categories, @text, @dual, @layer_name, @label_index, @feature_index = feature.values_at(:categories, :text, :dual, :layer_name, :label_index, :feature_index)
|
11
|
+
@indices = [@label_index, @feature_index]
|
12
|
+
@priority, @elements, @along, @fixed = priority, elements, along, fixed
|
13
|
+
@hull = dissolve_points.convex_hull
|
14
|
+
@optional, @coexist, knockout = feature.values_at("optional", "coexist", "knockout")
|
15
|
+
@barrier_count = each.with_object(Label.knockout(knockout)).map(&block).inject(&:merge).size
|
16
|
+
@ordinal = [@barrier_count, @priority]
|
17
|
+
@separation = feature.fetch("separation", {})
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :categories, :text, :dual, :layer_name, :label_index, :feature_index, :indices
|
22
|
+
attr_reader :priority, :elements, :along, :fixed, :hull, :barrier_count, :ordinal, :separation
|
23
|
+
|
24
|
+
def point?
|
25
|
+
@along.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def barriers?
|
29
|
+
@barrier_count > 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def optional?
|
33
|
+
@optional
|
34
|
+
end
|
35
|
+
|
36
|
+
def coexists_with?(other)
|
37
|
+
Array(@coexist).include? other.layer_name
|
38
|
+
end
|
39
|
+
|
40
|
+
def <=>(other)
|
41
|
+
self.ordinal <=> other.ordinal
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.overlaps(labels, group = labels, &block)
|
45
|
+
return Set[] unless group.any?(&block)
|
46
|
+
index = RTree.load(labels.flat_map(&:explode), &:bounds)
|
47
|
+
group.each.with_object Set[] do |label, overlaps|
|
48
|
+
next unless buffer = yield(label)
|
49
|
+
index.search(label.bounds, buffer).each do |other|
|
50
|
+
next if label == other.source
|
51
|
+
next if overlaps === [label, other.source]
|
52
|
+
next if overlaps === [other.source, label]
|
53
|
+
next unless label.length < 3 || ConvexHulls.overlap?(label.hull, other, buffer)
|
54
|
+
next unless label.any? do |hull|
|
55
|
+
ConvexHulls.overlap?(hull, other, buffer)
|
56
|
+
end
|
57
|
+
overlaps << [label, other.source]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|