voruby 1.1.1 → 2.0.0
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.
- data/Rakefile.rb +107 -224
- data/lib/misc.rb +1 -0
- data/lib/misc/misc.rb +60 -0
- data/lib/misc/propertyfile.rb +31 -0
- data/lib/symphony.rb +1 -0
- data/lib/symphony/symphony.rb +247 -0
- data/lib/voruby.rb +186 -0
- data/lib/voruby/active_votable/active_votable.rb +468 -347
- data/lib/voruby/adql/1.0/adql.rb +2418 -0
- data/lib/voruby/adql/support.rb +2 -0
- data/lib/voruby/misc.rb +351 -0
- data/lib/voruby/misc/connection_monitor.rb +97 -0
- data/lib/voruby/misc/libxml_ext.rb +121 -0
- data/lib/voruby/misc/rexml_ext.rb +223 -0
- data/lib/voruby/resolver/resolver.rb +12 -0
- data/lib/voruby/resolver/sesame.rb +299 -0
- data/lib/voruby/sky_query/sky_query.rb +192 -0
- data/lib/voruby/stc/1.10/coords.rb +2272 -0
- data/lib/voruby/stc/1.10/region.rb +892 -0
- data/lib/voruby/stc/1.10/stc.rb +3271 -0
- data/lib/voruby/stc/1.30/stc.rb +8666 -0
- data/lib/voruby/stc/support.rb +2 -0
- data/lib/voruby/ucd/ucd.rb +173 -0
- data/lib/voruby/voevent/1.1/voevent.rb +1124 -0
- data/lib/voruby/voevent/support.rb +5 -0
- data/lib/voruby/votable/1.0/votable.rb +1807 -0
- data/lib/voruby/votable/1.1/votable.rb +2100 -0
- data/lib/voruby/votable/votable.rb +305 -0
- data/lib/voruby/wesix/wesix.rb +491 -0
- data/lib/voruby/xlink/1.2/xlink.rb +21 -0
- data/test/voruby/active_votable/complex.vot +60 -0
- data/test/voruby/active_votable/error.vot +6 -0
- data/test/voruby/active_votable/large.vot +130040 -0
- data/test/voruby/active_votable/simple1.vot +38 -0
- data/test/voruby/active_votable/simple2.vot +38 -0
- data/test/voruby/active_votable/test.rb +193 -0
- data/test/voruby/adql/1.0/adql-alias.sql +1 -0
- data/test/voruby/adql/1.0/adql-alias.xml +26 -0
- data/test/voruby/adql/1.0/adql-avg.sql +1 -0
- data/test/voruby/adql/1.0/adql-avg.xml +31 -0
- data/test/voruby/adql/1.0/adql-circle.sql +1 -0
- data/test/voruby/adql/1.0/adql-circle.xml +46 -0
- data/test/voruby/adql/1.0/adql-expr.sql +1 -0
- data/test/voruby/adql/1.0/adql-expr.xml +34 -0
- data/test/voruby/adql/1.0/adql-function.sql +1 -0
- data/test/voruby/adql/1.0/adql-function.xml +41 -0
- data/test/voruby/adql/1.0/adql-group.sql +1 -0
- data/test/voruby/adql/1.0/adql-group.xml +51 -0
- data/test/voruby/adql/1.0/adql-having.sql +1 -0
- data/test/voruby/adql/1.0/adql-having.xml +25 -0
- data/test/voruby/adql/1.0/adql-like.sql +1 -0
- data/test/voruby/adql/1.0/adql-like.xml +17 -0
- data/test/voruby/adql/1.0/adql-order.sql +1 -0
- data/test/voruby/adql/1.0/adql-order.xml +37 -0
- data/test/voruby/adql/1.0/adql-simple.sql +1 -0
- data/test/voruby/adql/1.0/adql-simple.xml +12 -0
- data/test/voruby/adql/1.0/adql-top.sql +1 -0
- data/test/voruby/adql/1.0/adql-top.xml +33 -0
- data/test/voruby/adql/1.0/test.rb +2220 -0
- data/test/voruby/misc/test.rb +32 -0
- data/test/voruby/resolver/sesame/test.rb +56 -0
- data/test/voruby/sky_query/test.rb +107 -0
- data/test/voruby/stc/1.10/coords_test.rb +3704 -0
- data/test/voruby/stc/1.10/region_test.rb +993 -0
- data/test/voruby/stc/1.10/stc-catalog-entry-location.xml +112 -0
- data/test/voruby/stc/1.10/stc-obs-data-location.xml +126 -0
- data/test/voruby/stc/1.10/stc-region-circle.xml +5 -0
- data/test/voruby/stc/1.10/stc-region-convex.xml +11 -0
- data/test/voruby/stc/1.10/stc-region-convexhull.xml +5 -0
- data/test/voruby/stc/1.10/stc-region-ellipse.xml +7 -0
- data/test/voruby/stc/1.10/stc-region-intersection.xml +25 -0
- data/test/voruby/stc/1.10/stc-region-negation.xml +7 -0
- data/test/voruby/stc/1.10/stc-region-polygon.xml +13 -0
- data/test/voruby/stc/1.10/stc-region-sector.xml +6 -0
- data/test/voruby/stc/1.10/stc-region-union.xml +25 -0
- data/test/voruby/stc/1.10/stc-resource-profile.xml +60 -0
- data/test/voruby/stc/1.10/stc-search-location.xml +54 -0
- data/test/voruby/stc/1.10/stc_test.rb +4626 -0
- data/test/voruby/stc/1.30/stc-catalog-entry-location.xml +210 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-arecibo.xml +353 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-fits.xml +250 -0
- data/test/voruby/stc/1.30/stc-obs-data-location-xlink.xml +63 -0
- data/test/voruby/stc/1.30/stc-obs-data-location.xml +216 -0
- data/test/voruby/stc/1.30/stc-resource-profile-unusual-ref-pos.xml +39 -0
- data/test/voruby/stc/1.30/stc-resource-profile.xml +129 -0
- data/test/voruby/stc/1.30/stc-search-location-arecibo.xml +86 -0
- data/test/voruby/stc/1.30/stc-search-location.xml +101 -0
- data/test/voruby/stc/1.30/test.rb +6274 -0
- data/test/voruby/ucd/test.rb +48 -0
- data/test/voruby/voevent/1.1/test.rb +812 -0
- data/test/{voevent/voevent_v1_1.xml → voruby/voevent/1.1/voevent.xml} +2 -2
- data/test/voruby/voregistry/0.3/test.rb +137 -0
- data/test/voruby/votable/1.0/test.rb +714 -0
- data/test/voruby/votable/1.0/votable.basic.xml +660 -0
- data/test/voruby/votable/1.0/votable.html +86 -0
- data/test/voruby/votable/1.0/votable.ns.xml +56 -0
- data/test/voruby/votable/1.1/test.rb +785 -0
- data/test/voruby/votable/1.1/votable.basic.xml +38 -0
- data/test/voruby/votable/1.1/votable.html +86 -0
- data/test/voruby/votable/1.1/votable.ns.xml +56 -0
- data/test/voruby/votable/test.rb +15 -0
- data/test/voruby/wesix/test.rb +268 -0
- data/test/voruby/wesix/testr.fits +28 -0
- metadata +234 -247
- data/REQUIREMENTS +0 -6
- data/lib/voruby/active_votable/loader.rb +0 -5
- data/lib/voruby/adql/adql.rb +0 -2787
- data/lib/voruby/adql/ext.rb +0 -14
- data/lib/voruby/adql/loader.rb +0 -6
- data/lib/voruby/adql/operations.rb +0 -54
- data/lib/voruby/adql/parser.rb +0 -160
- data/lib/voruby/adql/transforms.rb +0 -573
- data/lib/voruby/ext.rb +0 -17
- data/lib/voruby/loader.rb +0 -4
- data/lib/voruby/misc/propertyfile.rb +0 -36
- data/lib/voruby/plastic/applications.rb +0 -174
- data/lib/voruby/plastic/constants.rb +0 -30
- data/lib/voruby/plastic/loader.rb +0 -10
- data/lib/voruby/plastic/plastic.rb +0 -1
- data/lib/voruby/resources/conesearch/conesearch.rb +0 -9
- data/lib/voruby/resources/conesearch/conesearch_v0_2.rb +0 -55
- data/lib/voruby/resources/conesearch/conesearch_v0_3.rb +0 -50
- data/lib/voruby/resources/conesearch/conesearch_v1_0.rb +0 -72
- data/lib/voruby/resources/conesearch/loader.rb +0 -4
- data/lib/voruby/resources/loader.rb +0 -50
- data/lib/voruby/resources/nodes.rb +0 -190
- data/lib/voruby/resources/openskynode/loader.rb +0 -4
- data/lib/voruby/resources/openskynode/openskynode.rb +0 -9
- data/lib/voruby/resources/openskynode/openskynode_v0_1.rb +0 -54
- data/lib/voruby/resources/sia/loader.rb +0 -5
- data/lib/voruby/resources/sia/sia.rb +0 -9
- data/lib/voruby/resources/sia/sia_v0_6.rb +0 -90
- data/lib/voruby/resources/sia/sia_v0_7.rb +0 -89
- data/lib/voruby/resources/sia/sia_v1_0.rb +0 -122
- data/lib/voruby/resources/stsci.rb +0 -59
- data/lib/voruby/resources/vodataservice/coverage_v0_2.rb +0 -195
- data/lib/voruby/resources/vodataservice/coverage_v0_3.rb +0 -158
- data/lib/voruby/resources/vodataservice/loader.rb +0 -5
- data/lib/voruby/resources/vodataservice/vodataservice.rb +0 -9
- data/lib/voruby/resources/vodataservice/vodataservice_v0_4.rb +0 -189
- data/lib/voruby/resources/vodataservice/vodataservice_v0_5.rb +0 -163
- data/lib/voruby/resources/vodataservice/vodataservice_v1_0.rb +0 -221
- data/lib/voruby/resources/voregistry/loader.rb +0 -4
- data/lib/voruby/resources/voregistry/voregistry.rb +0 -9
- data/lib/voruby/resources/voregistry/voregistry_v0_2.rb +0 -40
- data/lib/voruby/resources/voregistry/voregistry_v0_3.rb +0 -30
- data/lib/voruby/resources/voregistry/voregistry_v1_0.rb +0 -86
- data/lib/voruby/resources/voresource/loader.rb +0 -17
- data/lib/voruby/resources/voresource/voresource.rb +0 -9
- data/lib/voruby/resources/voresource/voresource_v0_10.rb +0 -327
- data/lib/voruby/resources/voresource/voresource_v0_9.rb +0 -405
- data/lib/voruby/resources/voresource/voresource_v1_0.rb +0 -230
- data/lib/voruby/services/ext.rb +0 -11
- data/lib/voruby/services/gestalt/footprint.rb +0 -95
- data/lib/voruby/services/gestalt/wcs_fixer.rb +0 -105
- data/lib/voruby/services/gestalt/wesix.rb +0 -155
- data/lib/voruby/services/loader.rb +0 -7
- data/lib/voruby/services/registry/registry.rb +0 -53
- data/lib/voruby/services/resolver/resolver.rb +0 -35
- data/lib/voruby/services/schema/schema.rb +0 -644
- data/lib/voruby/sesame/loader.rb +0 -6
- data/lib/voruby/sesame/sesame_v1_0.rb +0 -64
- data/lib/voruby/simple/loader.rb +0 -6
- data/lib/voruby/simple/parameters.rb +0 -196
- data/lib/voruby/simple/sap.rb +0 -446
- data/lib/voruby/spacetime/loader.rb +0 -3
- data/lib/voruby/spacetime/spacetime.rb +0 -607
- data/lib/voruby/stc/coords_v1_20.rb +0 -900
- data/lib/voruby/stc/loader.rb +0 -55
- data/lib/voruby/stc/region_v1_20.rb +0 -274
- data/lib/voruby/stc/stc_v1_20.rb +0 -1196
- data/lib/voruby/util.rb +0 -27
- data/lib/voruby/voevent/loader.rb +0 -7
- data/lib/voruby/voevent/voevent_v1_0.rb +0 -213
- data/lib/voruby/voevent/voevent_v1_1.rb +0 -196
- data/lib/voruby/votables/chandra.rb +0 -373
- data/lib/voruby/votables/data.rb +0 -179
- data/lib/voruby/votables/galex.rb +0 -377
- data/lib/voruby/votables/int.rb +0 -354
- data/lib/voruby/votables/libxml_parser.rb +0 -411
- data/lib/voruby/votables/libxml_votable.rb +0 -67
- data/lib/voruby/votables/loader.rb +0 -10
- data/lib/voruby/votables/meta.rb +0 -763
- data/lib/voruby/votables/misc.rb +0 -51
- data/lib/voruby/votables/nsa.rb +0 -410
- data/lib/voruby/votables/rexml_parser.rb +0 -408
- data/lib/voruby/votables/rexml_votable.rb +0 -67
- data/lib/voruby/votables/sdss.rb +0 -356
- data/lib/voruby/votables/transforms.rb +0 -388
- data/lib/voruby/votables/tree.rb +0 -45
- data/lib/voruby/votables/types.rb +0 -391
- data/lib/voruby/votables/votable.rb +0 -687
- data/test/active_votable/database.yml +0 -6
- data/test/active_votable/test.vot +0 -168492
- data/test/active_votable/unittest.rb +0 -41
- data/test/adql/test1.adql +0 -49
- data/test/adql/test2.adql +0 -51
- data/test/adql/test3.adql +0 -81
- data/test/adql/test4.adql +0 -53
- data/test/adql/test5.adql +0 -55
- data/test/adql/test6.adql +0 -18
- data/test/adql/test7.adql +0 -48
- data/test/adql/unittest.rb +0 -1672
- data/test/plastic/test.rb +0 -44
- data/test/plastic/test.vot +0 -5385
- data/test/plastic/unittest.rb +0 -66
- data/test/resources/conesearch/conesearch_v0_3.xml +0 -31
- data/test/resources/conesearch/conesearch_v1_0.xml +0 -86
- data/test/resources/conesearch/unittest_v0_3.rb +0 -22
- data/test/resources/conesearch/unittest_v1_0.rb +0 -24
- data/test/resources/openskynode/open_sky_node_v0_1.xml +0 -32
- data/test/resources/openskynode/unittest_v0_1.rb +0 -31
- data/test/resources/sia/simple_image_access_v0_7.xml +0 -36
- data/test/resources/sia/simple_image_access_v1_0.xml +0 -122
- data/test/resources/sia/unittest_v0_7.rb +0 -24
- data/test/resources/sia/unittest_v1_0.rb +0 -29
- data/test/resources/stsci.xml +0 -336
- data/test/resources/unittest_stsci.rb +0 -25
- data/test/resources/vodataservice/catalog_service_resource_v1_0.xml +0 -128
- data/test/resources/vodataservice/data_collection_resource_v0_5.xml +0 -54
- data/test/resources/vodataservice/data_collection_resource_v1_0.xml +0 -117
- data/test/resources/vodataservice/data_service_resource_v1_0.xml +0 -115
- data/test/resources/vodataservice/sky_service_resource_v0_10.xml +0 -45
- data/test/resources/vodataservice/table_service_resource_v1_0.xml +0 -122
- data/test/resources/vodataservice/tabular_sky_service_resource_v0_10.xml +0 -60
- data/test/resources/vodataservice/unittest_v0_5.rb +0 -126
- data/test/resources/vodataservice/unittest_v1_0.rb +0 -151
- data/test/resources/voregistry/authority_resource_v0_3.xml +0 -20
- data/test/resources/voregistry/authority_resource_v1_0.xml +0 -82
- data/test/resources/voregistry/registry_service_v0_3.xml +0 -20
- data/test/resources/voregistry/registry_service_v1_0.xml +0 -107
- data/test/resources/voregistry/unittest_v0_3.rb +0 -31
- data/test/resources/voregistry/unittest_v1_0.rb +0 -34
- data/test/resources/voresource/organisation_resource_v1_0.xml +0 -90
- data/test/resources/voresource/resource_organisation_v0_10.xml +0 -22
- data/test/resources/voresource/resource_service_v0_10.xml +0 -19
- data/test/resources/voresource/resource_v0_10.xml +0 -19
- data/test/resources/voresource/resource_v1_0.xml +0 -79
- data/test/resources/voresource/service_resource_v1_0.xml +0 -91
- data/test/resources/voresource/unittest_v0_10.rb +0 -61
- data/test/resources/voresource/unittest_v0_9.rb +0 -4
- data/test/resources/voresource/unittest_v1_0.rb +0 -190
- data/test/services/gestalt/unittest.rb +0 -74
- data/test/services/registry/unittest.rb +0 -34
- data/test/services/resolver/unittest.rb +0 -38
- data/test/simple/unittest.rb +0 -46
- data/test/spacetime/unittest.rb +0 -39
- data/test/stc/catalog_entry_location_v1_20.xml +0 -112
- data/test/stc/obs_data_location_v1_20.xml +0 -108
- data/test/stc/search_location_v1_20.xml +0 -54
- data/test/stc/stc_resource_profile_v1_20.xml +0 -60
- data/test/stc/unittest_v1_20.rb +0 -620
- data/test/voevent/unittest_v1_0.rb +0 -79
- data/test/voevent/unittest_v1_1.rb +0 -70
- data/test/voevent/voevent_v1_0.xml +0 -96
- data/test/votables/test.vot +0 -366
- data/test/votables/unittest.rb +0 -54
@@ -0,0 +1,892 @@
|
|
1
|
+
require 'voruby/stc/support'
|
2
|
+
require 'voruby/stc/1.10/coords'
|
3
|
+
include VORuby::STC::V1_10::Coords
|
4
|
+
|
5
|
+
module VORuby
|
6
|
+
module STC
|
7
|
+
module V1_10
|
8
|
+
module Region
|
9
|
+
include XMLUtilities
|
10
|
+
|
11
|
+
# Region is the base type for everything.
|
12
|
+
class RegionType
|
13
|
+
include SerializableToXml
|
14
|
+
|
15
|
+
attr_reader :note
|
16
|
+
|
17
|
+
def initialize(options={})
|
18
|
+
options.each { |key, value| send("#{key}=", value) }
|
19
|
+
end
|
20
|
+
|
21
|
+
# The fill_factor (value between 0 and 1) indicates the fraction of the region that
|
22
|
+
# is actually included; possible application: large scale resource coverage areas
|
23
|
+
def fill_factor
|
24
|
+
@fill_factor || 1.0
|
25
|
+
end
|
26
|
+
|
27
|
+
def fill_factor=(f)
|
28
|
+
raise ArgumentError, "fill factor must be between 0.0 and 1.0" if f and (Float(f) < 0.0 or Float(f) > 1.0)
|
29
|
+
@fill_factor = f ? Float(f) : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def note=(n)
|
33
|
+
@note = n ? n.to_s : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def ==(r)
|
37
|
+
self.fill_factor == r.fill_factor and
|
38
|
+
self.note == r.note
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_xml(name=nil)
|
42
|
+
el = element(name)
|
43
|
+
|
44
|
+
el.attributes["#{obj_ns.prefix}:fill_factor"] = self.fill_factor.to_s if self.fill_factor
|
45
|
+
el.attributes["#{obj_ns.prefix}:note"] = self.note if self.note
|
46
|
+
|
47
|
+
collapse_namespaces(el)
|
48
|
+
el
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.from_xml(xml)
|
52
|
+
root = element_from(xml)
|
53
|
+
|
54
|
+
options = {}
|
55
|
+
|
56
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
57
|
+
options[:fill_factor] = Float(fill_factor.value) if fill_factor
|
58
|
+
|
59
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
60
|
+
options[:note] = note.value if note
|
61
|
+
|
62
|
+
self.new(options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module Region; end
|
67
|
+
|
68
|
+
# Shape is the abstract type that is the building block of regions; in real life it needs to be replaced by a concrete shape
|
69
|
+
class Shape < RegionType
|
70
|
+
include SerializableToXml
|
71
|
+
|
72
|
+
attr_reader :coord_system_id, :unit
|
73
|
+
|
74
|
+
def initialize(options={})
|
75
|
+
raise_argument_required_error('coord system id') if !options.has_key?(:coord_system_id)
|
76
|
+
options.each { |key, value| send("#{key}=", value) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def coord_system_id=(id)
|
80
|
+
raise_argument_required_error('coord sys id') if !id
|
81
|
+
@coord_system_id = id.is_a?(IdRef) ? id : IdRef.new(id.to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
def unit=(u)
|
85
|
+
# unit should be required according to the schema, but I've seen
|
86
|
+
# examples (even in the official docs) where it's not.
|
87
|
+
if u
|
88
|
+
@unit = u.is_a?(PosUnit) ? u : PosUnit.new(u.to_s)
|
89
|
+
else
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==(s)
|
95
|
+
self.coord_system_id == s.coord_system_id and
|
96
|
+
self.unit == s.unit
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_xml(name=nil)
|
100
|
+
el = super(name)
|
101
|
+
|
102
|
+
el.attributes["#{obj_ns.prefix}:coord_system_id"] = self.coord_system_id.to_s
|
103
|
+
el.attributes["#{obj_ns.prefix}:unit"] = self.unit.to_s if self.unit
|
104
|
+
|
105
|
+
collapse_namespaces(el)
|
106
|
+
|
107
|
+
el
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Circle shape: center and radius
|
112
|
+
class CircleType < Shape
|
113
|
+
attr_reader :center, :radius
|
114
|
+
|
115
|
+
def self.xml_type; 'circleType' end
|
116
|
+
|
117
|
+
def initialize(options={})
|
118
|
+
raise_argument_required_error('center') if !options.has_key?(:center)
|
119
|
+
raise_argument_required_error('radius') if !options.has_key?(:radius)
|
120
|
+
super(options)
|
121
|
+
end
|
122
|
+
|
123
|
+
# The coordinates of the circle's center
|
124
|
+
def center=(c)
|
125
|
+
raise_argument_required_error('center') if !c
|
126
|
+
@center = Double2.new(c)
|
127
|
+
end
|
128
|
+
|
129
|
+
# The radius of the circle
|
130
|
+
def radius=(r)
|
131
|
+
raise_argument_required_error('radius') if !r
|
132
|
+
@radius = Float(r)
|
133
|
+
end
|
134
|
+
|
135
|
+
def ==(s)
|
136
|
+
super(s) and
|
137
|
+
self.center == s.center and
|
138
|
+
self.radius == s.radius
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_xml(name=nil)
|
142
|
+
el = super(name)
|
143
|
+
|
144
|
+
el.add_element(self.center.to_xml("Center", obj_ns))
|
145
|
+
radius = REXML::Element.new("#{obj_ns.prefix}:Radius")
|
146
|
+
radius.text = self.radius.to_s
|
147
|
+
el.add_element(radius)
|
148
|
+
|
149
|
+
collapse_namespaces(el)
|
150
|
+
el
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_s
|
154
|
+
"CIRCLE #{self.coord_system_id} #{self.center} #{self.radius}"
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.from_xml(xml)
|
158
|
+
root = element_from(xml)
|
159
|
+
|
160
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
161
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
162
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
163
|
+
options = {
|
164
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
165
|
+
:note => note ? note.value : nil,
|
166
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
167
|
+
:unit => unit ? PosUnit.new(unit.value) : nil,
|
168
|
+
:center => Double2.from_xml(REXML::XPath.first(root, 'x:Center', {'x' => obj_ns.uri})),
|
169
|
+
:radius => Float(REXML::XPath.first(root, 'x:Radius', {'x' => obj_ns.uri}).text)
|
170
|
+
}
|
171
|
+
|
172
|
+
self.new(options)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Circle < CircleType
|
177
|
+
include Region
|
178
|
+
end
|
179
|
+
|
180
|
+
# AllSky is just a convenience, meaning no bounds
|
181
|
+
class AllSky < RegionType
|
182
|
+
include Region
|
183
|
+
|
184
|
+
def to_xml(name=nil)
|
185
|
+
el = super(name)
|
186
|
+
el
|
187
|
+
end
|
188
|
+
|
189
|
+
def to_s
|
190
|
+
"ALLSKY"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Ellipse shape: adds semi-minor axis and position angle to Circle
|
195
|
+
class EllipseType < CircleType
|
196
|
+
attr_reader :minor_radius, :pos_angle
|
197
|
+
|
198
|
+
def self.xml_type; 'ellipseType' end
|
199
|
+
|
200
|
+
def initialize(options={})
|
201
|
+
raise_argument_required_error('minor radius') if !options.has_key?(:minor_radius)
|
202
|
+
raise_argument_required_error('position angle') if !options.has_key?(:pos_angle)
|
203
|
+
super(options)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Half the minor axis of the ellipse, in radius_unit
|
207
|
+
def minor_radius=(r)
|
208
|
+
raise_argument_required_error('minor radius') if !r
|
209
|
+
@minor_radius = Float(r)
|
210
|
+
end
|
211
|
+
|
212
|
+
# Position angle of major axis (Radius), counter-clockwise from north in pos_angle_unit
|
213
|
+
def pos_angle=(a)
|
214
|
+
raise_argument_required_error('position angle') if !a
|
215
|
+
@pos_angle = Float(a)
|
216
|
+
end
|
217
|
+
|
218
|
+
def pos_angle_unit=(u)
|
219
|
+
raise ArgumentError, 'position angle unit required' if !u
|
220
|
+
@pos_angle_unit = u.is_a?(AngleUnit) ? u : AngleUnit.new(u.to_s)
|
221
|
+
end
|
222
|
+
|
223
|
+
def pos_angle_unit
|
224
|
+
@pos_angle_unit || AngleUnit.new('deg')
|
225
|
+
end
|
226
|
+
|
227
|
+
def ==(s)
|
228
|
+
super(s) and
|
229
|
+
self.minor_radius = s.minor_radius and
|
230
|
+
self.pos_angle = s.pos_angle and
|
231
|
+
self.pos_angle_unit = s.pos_angle_unit
|
232
|
+
end
|
233
|
+
|
234
|
+
def to_xml(name=nil)
|
235
|
+
el = super(name)
|
236
|
+
|
237
|
+
el.attributes["#{obj_ns.prefix}:pos_angle_unit"] = self.pos_angle_unit.to_s
|
238
|
+
|
239
|
+
minor_radius = REXML::Element.new("#{obj_ns.prefix}:MinorRadius")
|
240
|
+
minor_radius.text = self.minor_radius.to_s
|
241
|
+
el.add_element(minor_radius)
|
242
|
+
|
243
|
+
pos_angle = REXML::Element.new("#{obj_ns.prefix}:PosAngle")
|
244
|
+
pos_angle.text = self.pos_angle.to_s
|
245
|
+
el.add_element(pos_angle)
|
246
|
+
|
247
|
+
collapse_namespaces(el)
|
248
|
+
|
249
|
+
el
|
250
|
+
end
|
251
|
+
|
252
|
+
def to_s
|
253
|
+
"ELLIPSE #{self.coord_system_id} #{self.center} #{self.radius} #{self.minor_radius} #{self.pos_angle}"
|
254
|
+
end
|
255
|
+
|
256
|
+
def self.from_xml(xml)
|
257
|
+
root = element_from(xml)
|
258
|
+
|
259
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
260
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
261
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
262
|
+
options = {
|
263
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
264
|
+
:note => note ? note.value : nil,
|
265
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
266
|
+
:pos_angle_unit => AngleUnit.new(root.attributes.get_attribute_ns(obj_ns.uri, 'pos_angle_unit').value),
|
267
|
+
:unit => unit ? PosUnit.new(unit.value) : nil,
|
268
|
+
:center => Double2.from_xml(REXML::XPath.first(root, 'x:Center', {'x' => obj_ns.uri})),
|
269
|
+
:radius => Float(REXML::XPath.first(root, 'x:Radius', {'x' => obj_ns.uri}).text),
|
270
|
+
:minor_radius => Float(REXML::XPath.first(root, 'x:MinorRadius', {'x' => obj_ns.uri}).text),
|
271
|
+
:pos_angle => Float(REXML::XPath.first(root, 'x:PosAngle', {'x' => obj_ns.uri}).text)
|
272
|
+
}
|
273
|
+
|
274
|
+
self.new(options)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
class Ellipse < EllipseType
|
279
|
+
include Region
|
280
|
+
end
|
281
|
+
|
282
|
+
# SmallCircle is used in vertices to indicate that the polygon side associated with the vertex
|
283
|
+
# is to be a small circle rather than the default great circle.
|
284
|
+
# SmallCircle indicates in polygons that side is along small circle; with optional pole.
|
285
|
+
class SmallCircle
|
286
|
+
include SerializableToXml
|
287
|
+
|
288
|
+
attr_reader :pole
|
289
|
+
|
290
|
+
def initialize(options={})
|
291
|
+
options.is_a?(Hash) ? options.each { |key, value| send("#{key}=", value) } : self.pole = options
|
292
|
+
end
|
293
|
+
|
294
|
+
def pole=(p)
|
295
|
+
p = Double2.new(p) if p and p.class == Array
|
296
|
+
raise_type_mismatch_error(p, Double2) if p
|
297
|
+
@pole = p
|
298
|
+
end
|
299
|
+
|
300
|
+
def ==(c)
|
301
|
+
self.pole == c.pole
|
302
|
+
end
|
303
|
+
|
304
|
+
def to_xml(name=nil)
|
305
|
+
el = element(name)
|
306
|
+
|
307
|
+
el.add_element(self.pole.to_xml('Pole', obj_ns)) if pole
|
308
|
+
|
309
|
+
collapse_namespaces(el)
|
310
|
+
|
311
|
+
el
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.from_xml(xml)
|
315
|
+
root = element_from(xml)
|
316
|
+
|
317
|
+
options = {}
|
318
|
+
pole = REXML::XPath.first(root, 'x:Pole', {'x' => obj_ns.uri})
|
319
|
+
options[:pole] = Double2.from_xml(pole) if pole
|
320
|
+
|
321
|
+
SmallCircle.new(options)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
# Vertex is a position with optional SmallCircle element
|
326
|
+
class Vertex
|
327
|
+
include SerializableToXml
|
328
|
+
|
329
|
+
attr_reader :position, :small_circle
|
330
|
+
|
331
|
+
def initialize(options={})
|
332
|
+
raise_argument_required_error('position') if !options.has_key?(:position)
|
333
|
+
options.each { |key, value| send("#{key}=", value) }
|
334
|
+
end
|
335
|
+
|
336
|
+
def position=(p)
|
337
|
+
raise_argument_required_error('position') if !p
|
338
|
+
p = Double2.new(p) if p.class == Array
|
339
|
+
raise_type_mismatch_error(p, Double2)
|
340
|
+
@position = p
|
341
|
+
end
|
342
|
+
|
343
|
+
def small_circle=(c)
|
344
|
+
raise_type_mismatch_error(c, SmallCircle) if c
|
345
|
+
@small_circle = c
|
346
|
+
end
|
347
|
+
|
348
|
+
def ==(v)
|
349
|
+
self.position == v.position and
|
350
|
+
self.small_circle == v.small_circle
|
351
|
+
end
|
352
|
+
|
353
|
+
def to_xml(name=nil)
|
354
|
+
el = element(name)
|
355
|
+
|
356
|
+
el.add_element(self.position.to_xml('Position', obj_ns))
|
357
|
+
el.add_element(self.small_circle.to_xml('SmallCircle')) if self.small_circle
|
358
|
+
|
359
|
+
collapse_namespaces(el)
|
360
|
+
|
361
|
+
el
|
362
|
+
end
|
363
|
+
|
364
|
+
def to_s
|
365
|
+
self.position.to_s
|
366
|
+
end
|
367
|
+
|
368
|
+
def self.from_xml(xml)
|
369
|
+
root = element_from(xml)
|
370
|
+
|
371
|
+
options = {
|
372
|
+
:position => Double2.from_xml(REXML::XPath.first(root, 'x:Position', {'x' => obj_ns.uri}))
|
373
|
+
}
|
374
|
+
|
375
|
+
small_circle = REXML::XPath.first(root, 'x:SmallCircle', {'x' => obj_ns.uri})
|
376
|
+
options[:small_circle] = SmallCircle.from_xml(small_circle) if small_circle
|
377
|
+
|
378
|
+
Vertex.new(options)
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
class VertexList < TypedArray
|
383
|
+
def self.restricted_to; [Vertex] end
|
384
|
+
def self.minimum_length; 1 end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Polygon: one or more vertices; counter-clockwise encircled area is enclosed;
|
388
|
+
# cyclical coordinates may exceed 0 and 360 limits if necessary
|
389
|
+
class PolygonType < Shape
|
390
|
+
attr_reader :vertices
|
391
|
+
|
392
|
+
def self.xml_type; 'polygonType' end
|
393
|
+
|
394
|
+
def initialize(options={})
|
395
|
+
raise_argument_required_error('list of vertexes') if !options.has_key?(:vertices)
|
396
|
+
super(options)
|
397
|
+
end
|
398
|
+
|
399
|
+
# In order to form polygons, vertices are to be connected with straight line segments.
|
400
|
+
# In the case of spherical coordinates: GreatCircle segments; if a SmallCircle element
|
401
|
+
# is present, the vertex and its predecessor are to be connected with a SmallCircle, by
|
402
|
+
# default in the CoordSys that is referenced; optionally, a pole may be specified (other
|
403
|
+
# than the CoordSys pole) that defines the SmallCircle system
|
404
|
+
def vertices=(vs)
|
405
|
+
raise_argument_required_error('list of vertexes') if !vs
|
406
|
+
|
407
|
+
vs = VertexList.new(vs) if vs.class == Array
|
408
|
+
raise_type_mismatch_error(vs, VertexList)
|
409
|
+
|
410
|
+
@vertices = vs
|
411
|
+
end
|
412
|
+
|
413
|
+
def ==(p)
|
414
|
+
super(p) and
|
415
|
+
self.vertices == p.vertices
|
416
|
+
end
|
417
|
+
|
418
|
+
def to_xml(name=nil)
|
419
|
+
el = super(name)
|
420
|
+
self.vertices.each { |v| el.add_element(v.to_xml('Vertex')) }
|
421
|
+
collapse_namespaces(el)
|
422
|
+
el
|
423
|
+
end
|
424
|
+
|
425
|
+
def to_s
|
426
|
+
"POLYGON #{self.coord_system_id} #{self.vertices.collect{ |v| v.to_s }.join(' ')}"
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.from_xml(xml)
|
430
|
+
root = element_from(xml)
|
431
|
+
|
432
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
433
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
434
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
435
|
+
options = {
|
436
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
437
|
+
:note => note ? note.value : nil,
|
438
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
439
|
+
:unit => unit ? PosUnit.new(unit.value) : nil,
|
440
|
+
:vertices => VertexList.new(xml_to_obj(root, Vertex))
|
441
|
+
}
|
442
|
+
|
443
|
+
self.new(options)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
class Polygon < PolygonType
|
448
|
+
include Region
|
449
|
+
end
|
450
|
+
|
451
|
+
# A sector is the counter-clockwise area between two half-lines
|
452
|
+
class SectorType < Shape
|
453
|
+
attr_reader :position, :pos_angle1, :pos_angle2
|
454
|
+
|
455
|
+
def self.xml_type; 'sectorType' end
|
456
|
+
|
457
|
+
def initialize(options)
|
458
|
+
raise_argument_required_error('position') if !options.has_key?(:position)
|
459
|
+
raise_argument_required_error('position angle 1') if !options.has_key?(:pos_angle1)
|
460
|
+
raise_argument_required_error('position angle 2') if !options.has_key?(:pos_angle2)
|
461
|
+
super(options)
|
462
|
+
end
|
463
|
+
|
464
|
+
# The vertex position of the sector
|
465
|
+
def position=(p)
|
466
|
+
raise_argument_required_error('position') if !p
|
467
|
+
p = Double2.new(p) if p.class == Array
|
468
|
+
raise_type_mismatch_error(p, Double2)
|
469
|
+
@position = p
|
470
|
+
end
|
471
|
+
|
472
|
+
# The area ccw from this position angle is included
|
473
|
+
def pos_angle1=(a)
|
474
|
+
raise_argument_required_error('position angle 1') if !a
|
475
|
+
@pos_angle1 = Float(a)
|
476
|
+
end
|
477
|
+
|
478
|
+
# The area cw from this position angle is included
|
479
|
+
def pos_angle2=(a)
|
480
|
+
raise_argument_required_error('position angle 2') if !a
|
481
|
+
@pos_angle2 = Float(a)
|
482
|
+
end
|
483
|
+
|
484
|
+
def pos_angle_unit=(u)
|
485
|
+
raise_argument_required_error('position angle unit') if !u
|
486
|
+
@pos_angle_unit = u.is_a?(PosUnit) ? u : PosUnit.new(u.to_s)
|
487
|
+
end
|
488
|
+
|
489
|
+
def pos_angle_unit
|
490
|
+
@pos_angle_unit || PosUnit.new('deg')
|
491
|
+
end
|
492
|
+
|
493
|
+
def ==(s)
|
494
|
+
super(s) and
|
495
|
+
self.position == s.position and
|
496
|
+
self.pos_angle1 == s.pos_angle1 and
|
497
|
+
self.pos_angle2 == s.pos_angle2 and
|
498
|
+
self.pos_angle_unit == s.pos_angle_unit
|
499
|
+
end
|
500
|
+
|
501
|
+
def to_xml(name=nil)
|
502
|
+
el = super(name)
|
503
|
+
|
504
|
+
el.attributes["#{obj_ns.prefix}:pos_angle_unit"] = self.pos_angle_unit.to_s
|
505
|
+
|
506
|
+
el.add_element(self.position.to_xml('Position', obj_ns))
|
507
|
+
|
508
|
+
pos_angle1 = REXML::Element.new("#{obj_ns.prefix}:PosAngle1")
|
509
|
+
pos_angle1.text = self.pos_angle1.to_s
|
510
|
+
el.add_element(pos_angle1)
|
511
|
+
|
512
|
+
pos_angle2 = REXML::Element.new("#{obj_ns.prefix}:PosAngle2")
|
513
|
+
pos_angle2.text = self.pos_angle2.to_s
|
514
|
+
el.add_element(pos_angle2)
|
515
|
+
|
516
|
+
collapse_namespaces(el)
|
517
|
+
|
518
|
+
el
|
519
|
+
end
|
520
|
+
|
521
|
+
def to_s
|
522
|
+
"SECTOR #{self.coord_system_id} #{self.position} #{self.pos_angle1} #{self.pos_angle2}"
|
523
|
+
end
|
524
|
+
|
525
|
+
def self.from_xml(xml)
|
526
|
+
root = element_from(xml)
|
527
|
+
|
528
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
529
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
530
|
+
options = {
|
531
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
532
|
+
:note => note ? note.value : nil,
|
533
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
534
|
+
:position => Double2.from_xml(REXML::XPath.first(root, 'x:Position', {'x' => obj_ns.uri})),
|
535
|
+
:pos_angle1 => Float(REXML::XPath.first(root, 'x:PosAngle1', {'x' => obj_ns.uri}).text),
|
536
|
+
:pos_angle2 => Float(REXML::XPath.first(root, 'x:PosAngle2', {'x' => obj_ns.uri}).text)
|
537
|
+
}
|
538
|
+
|
539
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
540
|
+
options[:unit] = PosUnit.new(unit.value) if unit
|
541
|
+
|
542
|
+
pos_angle_unit = root.attributes.get_attribute_ns(obj_ns.uri, 'pos_angle_unit')
|
543
|
+
options[:pos_angle_unit] = PosUnit.new(pos_angle_unit.value) if pos_angle_unit
|
544
|
+
|
545
|
+
self.new(options)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
class Sector < SectorType
|
550
|
+
include Region
|
551
|
+
end
|
552
|
+
|
553
|
+
# An area on the unit sphere defined by the intersection with a plane
|
554
|
+
class Constraint
|
555
|
+
include SerializableToXml
|
556
|
+
|
557
|
+
attr_reader :vector, :offset
|
558
|
+
|
559
|
+
def initialize(options={})
|
560
|
+
raise_argument_required_error('vector') if !options.has_key?(:vector)
|
561
|
+
raise_argument_required_error('offset') if !options.has_key?(:offset)
|
562
|
+
options.each { |key, value| send("#{key}=", value) }
|
563
|
+
end
|
564
|
+
|
565
|
+
# This needs to be a spherical coordinate vector; it is the unit vector that
|
566
|
+
# is normal to the plane that forms a constraint for a convex
|
567
|
+
def vector=(v)
|
568
|
+
raise_argument_required_error('vector') if !v
|
569
|
+
v = Double3.new(v) if v.class == Array
|
570
|
+
|
571
|
+
raise_type_mismatch_error(v, Double3)
|
572
|
+
@vector = v
|
573
|
+
end
|
574
|
+
|
575
|
+
# The distance along the normal vector where the constraint plane intersects
|
576
|
+
# that vector; if positive, the spherical sector on the far side (seen from
|
577
|
+
# the center) is selected; if negative, the point of intersection is in the
|
578
|
+
# opposite direction of the vector, resulting in more than a hemisphere
|
579
|
+
def offset=(o)
|
580
|
+
raise_argument_required_error('offset') if !o
|
581
|
+
@offset = Float(o)
|
582
|
+
end
|
583
|
+
|
584
|
+
def ==(c)
|
585
|
+
self.vector == c.vector and
|
586
|
+
self.offset == c.offset
|
587
|
+
end
|
588
|
+
|
589
|
+
def to_xml(name=nil)
|
590
|
+
el = element(name)
|
591
|
+
|
592
|
+
el.add_element(self.vector.to_xml('Vector', obj_ns))
|
593
|
+
|
594
|
+
offset = REXML::Element.new("#{obj_ns.prefix}:Offset")
|
595
|
+
offset.text = self.offset.to_s
|
596
|
+
el.add_element(offset)
|
597
|
+
|
598
|
+
collapse_namespaces(el)
|
599
|
+
|
600
|
+
el
|
601
|
+
end
|
602
|
+
|
603
|
+
def to_s
|
604
|
+
"#{self.vector} #{self.offset}"
|
605
|
+
end
|
606
|
+
|
607
|
+
def self.from_xml(xml)
|
608
|
+
root = element_from(xml)
|
609
|
+
|
610
|
+
options = {
|
611
|
+
:vector => Double3.from_xml(REXML::XPath.first(root, 'x:Vector', {'x' => obj_ns.uri})),
|
612
|
+
:offset => Float(REXML::XPath.first(root, 'x:Offset', {'x' => obj_ns.uri}).text)
|
613
|
+
}
|
614
|
+
|
615
|
+
Constraint.new(options)
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
class ConstraintList < TypedArray
|
620
|
+
def self.restricted_to; [Constraint] end
|
621
|
+
def self.minimum_length; 1 end
|
622
|
+
end
|
623
|
+
|
624
|
+
# A convex polygon defined by one or more Constraints
|
625
|
+
class ConvexType < Shape
|
626
|
+
attr_reader :constraints
|
627
|
+
|
628
|
+
def self.xml_type; 'convexType' end
|
629
|
+
|
630
|
+
def initialize(options={})
|
631
|
+
raise_argument_required_error('list of constraints') if !options.has_key?(:constraints)
|
632
|
+
super(options)
|
633
|
+
end
|
634
|
+
|
635
|
+
def constraints=(cs)
|
636
|
+
raise_argument_required_error('list of constraints') if !cs
|
637
|
+
|
638
|
+
cs = ConstraintList.new(cs) if cs.class == Array
|
639
|
+
raise_type_mismatch_error(cs, ConstraintList)
|
640
|
+
|
641
|
+
@constraints = cs
|
642
|
+
end
|
643
|
+
|
644
|
+
def ==(c)
|
645
|
+
super(c) and
|
646
|
+
self.constraints == c.constraints
|
647
|
+
end
|
648
|
+
|
649
|
+
def to_xml(name=nil)
|
650
|
+
el = super(name)
|
651
|
+
self.constraints.each { |c| el.add_element(c.to_xml('Constraint')) }
|
652
|
+
collapse_namespaces(el)
|
653
|
+
el
|
654
|
+
end
|
655
|
+
|
656
|
+
def to_s
|
657
|
+
"CONVEX #{self.coord_system_id} #{self.constraints.collect{ |c| c.to_s }.join(' ') }"
|
658
|
+
end
|
659
|
+
|
660
|
+
def self.from_xml(xml)
|
661
|
+
root = element_from(xml)
|
662
|
+
|
663
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
664
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
665
|
+
options = {
|
666
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
667
|
+
:note => note ? note.value : nil,
|
668
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
669
|
+
:constraints => REXML::XPath.match(root, 'x:Constraint', {'x' => obj_ns.uri}).collect{ |c| Constraint.from_xml(c) }
|
670
|
+
}
|
671
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
672
|
+
options[:unit] = PosUnit.new(unit.value) if unit
|
673
|
+
|
674
|
+
self.new(options)
|
675
|
+
end
|
676
|
+
end
|
677
|
+
|
678
|
+
class Convex < ConvexType
|
679
|
+
include Region
|
680
|
+
end
|
681
|
+
|
682
|
+
class PointList < TypedArray
|
683
|
+
def self.restricted_to; [Double3] end
|
684
|
+
def self.minimum_length; 1 end
|
685
|
+
end
|
686
|
+
|
687
|
+
# A convex hull
|
688
|
+
class ConvexHullType < Shape
|
689
|
+
attr_reader :points
|
690
|
+
|
691
|
+
def self.xml_type; 'convexHullType' end
|
692
|
+
|
693
|
+
def initialize(options={})
|
694
|
+
raise_argument_required_error('list of points') if !options.has_key?(:points)
|
695
|
+
super(options)
|
696
|
+
end
|
697
|
+
|
698
|
+
def points=(ps)
|
699
|
+
raise_argument_required_error('list of points') if !ps
|
700
|
+
|
701
|
+
ps = PointList.new(ps) if ps.class == Array
|
702
|
+
raise_type_mismatch_error(ps, PointList)
|
703
|
+
|
704
|
+
@points = ps
|
705
|
+
end
|
706
|
+
|
707
|
+
def ==(c)
|
708
|
+
super(c) and
|
709
|
+
self.points == c.points
|
710
|
+
end
|
711
|
+
|
712
|
+
def to_xml(name=nil)
|
713
|
+
el = super(name)
|
714
|
+
self.points.each { |p| el.add_element(p.to_xml('Point', obj_ns)) }
|
715
|
+
collapse_namespaces(el)
|
716
|
+
el
|
717
|
+
end
|
718
|
+
|
719
|
+
def to_s
|
720
|
+
"CHULL #{self.coord_system_id} #{self.points}"
|
721
|
+
end
|
722
|
+
|
723
|
+
def self.from_xml(xml)
|
724
|
+
root = element_from(xml)
|
725
|
+
|
726
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
727
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
728
|
+
options = {
|
729
|
+
:fill_factor => fill_factor ? Float(fill_factor.value) : nil,
|
730
|
+
:note => note ? note.value : nil,
|
731
|
+
:coord_system_id => IdRef.new(root.attributes.get_attribute_ns(obj_ns.uri, 'coord_system_id').value),
|
732
|
+
:points => PointList.new(
|
733
|
+
REXML::XPath.match(root, 'x:Point', {'x' => obj_ns.uri}).collect{ |p| Double3.from_xml(p) }
|
734
|
+
)
|
735
|
+
}
|
736
|
+
unit = root.attributes.get_attribute_ns(obj_ns.uri, 'unit')
|
737
|
+
options[:unit] = PosUnit.new(unit.value) if unit
|
738
|
+
|
739
|
+
self.new(options)
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
class ConvexHull < ConvexHullType
|
744
|
+
include Region
|
745
|
+
end
|
746
|
+
|
747
|
+
# This is a generic hook for regions defined in sky indexing schemes
|
748
|
+
class SkyIndexType < Shape
|
749
|
+
def self.xml_type; 'skyIndexType' end
|
750
|
+
end
|
751
|
+
|
752
|
+
class SkyIndex < SkyIndexType
|
753
|
+
include Region
|
754
|
+
end
|
755
|
+
|
756
|
+
class RegionList < TypedArray
|
757
|
+
def self.restricted_to; [Region] end
|
758
|
+
def self.minimum_length; 2 end
|
759
|
+
end
|
760
|
+
|
761
|
+
class BooleanOperatorType < RegionType
|
762
|
+
include SerializableToXml
|
763
|
+
|
764
|
+
attr_reader :regions
|
765
|
+
|
766
|
+
def initialize(options={})
|
767
|
+
raise_argument_required_error('list of regions') if !options.has_key?(:regions)
|
768
|
+
super(options)
|
769
|
+
end
|
770
|
+
|
771
|
+
def regions=(rs)
|
772
|
+
raise_argument_required_error('list of regions') if !rs
|
773
|
+
|
774
|
+
rs = RegionList.new(rs) if rs.class == Array
|
775
|
+
raise_type_mismatch_error(rs, RegionList)
|
776
|
+
|
777
|
+
@regions = rs
|
778
|
+
end
|
779
|
+
|
780
|
+
def ==(u)
|
781
|
+
super(u) and
|
782
|
+
self.regions == u.regions
|
783
|
+
end
|
784
|
+
|
785
|
+
def to_xml(name=nil)
|
786
|
+
el = super(name)
|
787
|
+
self.regions.each { |r| el.add_element(r.to_xml) }
|
788
|
+
collapse_namespaces(el)
|
789
|
+
el
|
790
|
+
end
|
791
|
+
|
792
|
+
def to_s(name)
|
793
|
+
"#{name}(#{self.regions.collect{ |r| r.to_s }.join(' ')})"
|
794
|
+
end
|
795
|
+
|
796
|
+
def self.from_xml(xml)
|
797
|
+
root = element_from(xml)
|
798
|
+
|
799
|
+
options = {
|
800
|
+
:regions => xml_to_obj(root, Region)
|
801
|
+
}
|
802
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
803
|
+
options[:fill_factor] = Float(fill_factor.value) if fill_factor
|
804
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
805
|
+
options[:note] = note.value if note
|
806
|
+
|
807
|
+
self.new(options)
|
808
|
+
end
|
809
|
+
end
|
810
|
+
|
811
|
+
# The union of two or more regions is a region
|
812
|
+
class UnionType < BooleanOperatorType
|
813
|
+
def self.xml_type; 'unionType' end
|
814
|
+
|
815
|
+
def to_s
|
816
|
+
super('UNION')
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
class Union < UnionType
|
821
|
+
include Region
|
822
|
+
end
|
823
|
+
|
824
|
+
# The intersection of two or more regions is a region
|
825
|
+
class IntersectionType < BooleanOperatorType
|
826
|
+
def self.xml_type; 'intersectionType' end
|
827
|
+
|
828
|
+
def to_s
|
829
|
+
super('INTERSECT')
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
class Intersection < IntersectionType
|
834
|
+
include Region
|
835
|
+
end
|
836
|
+
|
837
|
+
class NegationType < RegionType
|
838
|
+
attr_reader :region
|
839
|
+
|
840
|
+
def self.xml_type; 'negationType' end
|
841
|
+
|
842
|
+
def initialize(options={})
|
843
|
+
raise_argument_required_error('region') if !options.has_key?(:region)
|
844
|
+
super(options)
|
845
|
+
end
|
846
|
+
|
847
|
+
def region=(r)
|
848
|
+
raise_argument_required_error('region') if !r
|
849
|
+
raise TypeError, "invalid value #{r}, expected Region" if !r.is_a?(Region)
|
850
|
+
|
851
|
+
@region = r
|
852
|
+
end
|
853
|
+
|
854
|
+
def ==(n)
|
855
|
+
super(n) and
|
856
|
+
self.region == n.region
|
857
|
+
end
|
858
|
+
|
859
|
+
def to_xml(name=nil)
|
860
|
+
el = element(name)
|
861
|
+
el.add_element(self.region.to_xml)
|
862
|
+
collapse_namespaces(name)
|
863
|
+
el
|
864
|
+
end
|
865
|
+
|
866
|
+
def to_s
|
867
|
+
"NOT(#{self.region})"
|
868
|
+
end
|
869
|
+
|
870
|
+
def self.from_xml(xml)
|
871
|
+
root = element_from(xml)
|
872
|
+
|
873
|
+
options = {
|
874
|
+
:region => xml_to_obj(root, Region, true)
|
875
|
+
}
|
876
|
+
fill_factor = root.attributes.get_attribute_ns(obj_ns.uri, 'fill_factor')
|
877
|
+
options[:fill_factor] = Float(fill_factor.value) if fill_factor
|
878
|
+
note = root.attributes.get_attribute_ns(obj_ns.uri, 'note')
|
879
|
+
options[:note] = note.value if note
|
880
|
+
|
881
|
+
self.new(options)
|
882
|
+
end
|
883
|
+
end
|
884
|
+
|
885
|
+
class Negation < NegationType
|
886
|
+
include Region
|
887
|
+
end
|
888
|
+
|
889
|
+
end
|
890
|
+
end
|
891
|
+
end
|
892
|
+
end
|