248 строки
11 KiB
Ruby
248 строки
11 KiB
Ruby
#!/usr/bin/env ruby
|
|
|
|
require 'geos'
|
|
require "rexml/document"
|
|
|
|
XmlTest = Struct.new(:case_id, :test_id,
|
|
:operation, :expected,
|
|
:geom1, :geom2,
|
|
:arg1, :arg2, :arg3)
|
|
|
|
class GeosTestHelper
|
|
|
|
def create_point(x, y)
|
|
cs = Geos::CoordinateSequence.new(1,2)
|
|
cs.set_x(0, x)
|
|
cs.set_y(0, y)
|
|
Geos.create_point(cs)
|
|
end
|
|
|
|
def create_ushaped_linestring(xoffset, yoffset, side)
|
|
cs = Geos::CoordinateSequence.new(4,2)
|
|
cs.set_x(0, xoffset)
|
|
cs.set_y(0, yoffset)
|
|
cs.set_x(1, xoffset)
|
|
cs.set_y(1, yoffset + side)
|
|
cs.set_x(2, xoffset + side)
|
|
cs.set_y(2, yoffset + side)
|
|
cs.set_x(3, xoffset + side)
|
|
cs.set_y(3, yoffset)
|
|
Geos.create_line_string(cs)
|
|
end
|
|
|
|
# This function will create a LinearRing geometry
|
|
# representing a square with the given origin and side
|
|
def create_square_linear_ring(xoffset, yoffset, side)
|
|
cs = Geos::CoordinateSequence.new(5,2)
|
|
cs.set_x(0, xoffset)
|
|
cs.set_y(0, yoffset)
|
|
cs.set_x(1, xoffset)
|
|
cs.set_y(1, yoffset + side)
|
|
cs.set_x(2, xoffset + side)
|
|
cs.set_y(2, yoffset + side)
|
|
cs.set_x(3, xoffset + side)
|
|
cs.set_y(3, yoffset)
|
|
cs.set_x(4, xoffset)
|
|
cs.set_y(4, yoffset)
|
|
Geos.create_linear_ring(cs)
|
|
end
|
|
|
|
# This function will create a Polygon
|
|
# geometry representing a square with the given origin
|
|
# and side and with a central hole 1/3 sided.
|
|
def create_square_polygon(xoffset, yoffset, side)
|
|
# We need a LinearRing for the polygon shell
|
|
outer = create_square_linear_ring(xoffset,yoffset,side);
|
|
|
|
# And another for the hole
|
|
inner = create_square_linear_ring(xoffset+(side/3), yoffset+(side/3),(side/3));
|
|
|
|
Geos.create_polygon(outer, [inner])
|
|
end
|
|
|
|
def create_simple_collection(geoms)
|
|
# This function creates a GeometryCollection
|
|
# containing copies of all Geometries in given vector.
|
|
#@geom_factory.create_geometry_collection(geoms)
|
|
wkt = "GEOMETRYCOLLECTION (POLYGON ((0.00 250.00, 0.00 550.00, 300.00 550.00, 300.00 250.00, 0.00 250.00), (100.00 350.00, 200.00 350.00, 200.00 450.00, 100.00 450.00, 100.00 350.00)), POLYGON ((0.00 200.00, 0.00 500.00, 300.00 500.00, 300.00 200.00, 0.00 200.00), (100.00 300.00, 200.00 300.00, 200.00 400.00, 100.00 400.00, 100.00 300.00)), LINEARRING (0.00 0.00, 0.00 100.00, 100.00 100.00, 100.00 0.00, 0.00 0.00), LINEARRING (0.00 0.00, 0.00 100.00, 100.00 100.00, 100.00 0.00, 0.00 0.00), LINESTRING (60.00 60.00, 60.00 160.00, 160.00 160.00, 160.00 60.00), POINT (150.00 350.00))"
|
|
reader = Geos::WktReader.new
|
|
reader.read(wkt)
|
|
end
|
|
|
|
def create_circle(centerX, centerY, radius)
|
|
# Use a GeometricShapeFactory to render
|
|
# a circle having the specified center and radius
|
|
|
|
#shapefactory = Geos::GeometricShapeFactory.new(@geom_factory)
|
|
#shapefactory.set_centre(Geos::Coordinate.new(centerX, centerY))
|
|
#shapefactory.set_size(radius);
|
|
# same as:
|
|
# shapefactory.set_height(radius)
|
|
# shapefactory.set_width(radius)
|
|
|
|
#shapefactory.create_circle()
|
|
wkt = "POLYGON ((-5.00 0.00, -4.99 0.31, -4.96 0.63, -4.91 0.94, -4.84 1.24, -4.76 1.55, -4.65 1.84, -4.52 2.13, -4.38 2.41, -4.22 2.68, -4.05 2.94, -3.85 3.19, -3.64 3.42, -3.42 3.64, -3.19 3.85, -2.94 4.05, -2.68 4.22, -2.41 4.38, -2.13 4.52, -1.84 4.65, -1.55 4.76, -1.24 4.84, -0.94 4.91, -0.63 4.96, -0.31 4.99, 0.00 5.00, 0.31 4.99, 0.63 4.96, 0.94 4.91, 1.24 4.84, 1.55 4.76, 1.84 4.65, 2.13 4.52, 2.41 4.38, 2.68 4.22, 2.94 4.05, 3.19 3.85, 3.42 3.64, 3.64 3.42, 3.85 3.19, 4.05 2.94, 4.22 2.68, 4.38 2.41, 4.52 2.13, 4.65 1.84, 4.76 1.55, 4.84 1.24, 4.91 0.94, 4.96 0.63, 4.99 0.31, 5.00 0.00, 4.99 -0.31, 4.96 -0.63, 4.91 -0.94, 4.84 -1.24, 4.76 -1.55, 4.65 -1.84, 4.52 -2.13, 4.38 -2.41, 4.22 -2.68, 4.05 -2.94, 3.85 -3.19, 3.64 -3.42, 3.42 -3.64, 3.19 -3.85, 2.94 -4.05, 2.68 -4.22, 2.41 -4.38, 2.13 -4.52, 1.84 -4.65, 1.55 -4.76, 1.24 -4.84, 0.94 -4.91, 0.63 -4.96, 0.31 -4.99, -0.00 -5.00, -0.31 -4.99, -0.63 -4.96, -0.94 -4.91, -1.24 -4.84, -1.55 -4.76, -1.84 -4.65, -2.13 -4.52, -2.41 -4.38, -2.68 -4.22, -2.94 -4.05, -3.19 -3.85, -3.42 -3.64, -3.64 -3.42, -3.85 -3.19, -4.05 -2.94, -4.22 -2.68, -4.38 -2.41, -4.52 -2.13, -4.65 -1.84, -4.76 -1.55, -4.84 -1.24, -4.91 -0.94, -4.96 -0.63, -4.99 -0.31, -5.00 0.00))"
|
|
reader = Geos::WktReader.new
|
|
reader.read(wkt)
|
|
end
|
|
|
|
def create_ellipse(centerX, centerY, width, height)
|
|
# Use a GeometricShapeFactory to render
|
|
# a circle having the specified center and radius
|
|
|
|
#shapefactory = Geos::GeometricShapeFactory.new(@geom_factory)
|
|
#shapefactory.set_centre(Geos::Coordinate.new(centerX, centerY))
|
|
#shapefactory.set_height(width)
|
|
#shapefactory.set_width(height)
|
|
|
|
#shapefactory.create_circle()
|
|
wkt = "POLYGON ((-4.00 0.00, -3.99 0.38, -3.97 0.75, -3.93 1.12, -3.87 1.49, -3.80 1.85, -3.72 2.21, -3.62 2.55, -3.51 2.89, -3.38 3.21, -3.24 3.53, -3.08 3.82, -2.92 4.11, -2.74 4.37, -2.55 4.62, -2.35 4.85, -2.14 5.07, -1.93 5.26, -1.70 5.43, -1.47 5.58, -1.24 5.71, -0.99 5.81, -0.75 5.89, -0.50 5.95, -0.25 5.99, 0.00 6.00, 0.25 5.99, 0.50 5.95, 0.75 5.89, 0.99 5.81, 1.24 5.71, 1.47 5.58, 1.70 5.43, 1.93 5.26, 2.14 5.07, 2.35 4.85, 2.55 4.62, 2.74 4.37, 2.92 4.11, 3.08 3.82, 3.24 3.53, 3.38 3.21, 3.51 2.89, 3.62 2.55, 3.72 2.21, 3.80 1.85, 3.87 1.49, 3.93 1.12, 3.97 0.75, 3.99 0.38, 4.00 0.00, 3.99 -0.38, 3.97 -0.75, 3.93 -1.12, 3.87 -1.49, 3.80 -1.85, 3.72 -2.21, 3.62 -2.55, 3.51 -2.89, 3.38 -3.21, 3.24 -3.53, 3.08 -3.82, 2.92 -4.11, 2.74 -4.37, 2.55 -4.62, 2.35 -4.85, 2.14 -5.07, 1.93 -5.26, 1.70 -5.43, 1.47 -5.58, 1.24 -5.71, 0.99 -5.81, 0.75 -5.89, 0.50 -5.95, 0.25 -5.99, -0.00 -6.00, -0.25 -5.99, -0.50 -5.95, -0.75 -5.89, -0.99 -5.81, -1.24 -5.71, -1.47 -5.58, -1.70 -5.43, -1.93 -5.26, -2.14 -5.07, -2.35 -4.85, -2.55 -4.62, -2.74 -4.37, -2.92 -4.11, -3.08 -3.82, -3.24 -3.53, -3.38 -3.21, -3.51 -2.89, -3.62 -2.55, -3.72 -2.21, -3.80 -1.85, -3.87 -1.49, -3.93 -1.12, -3.97 -0.75, -3.99 -0.38, -4.00 0.00))"
|
|
reader = Geos::WktReader.new
|
|
reader.read(wkt)
|
|
end
|
|
|
|
def create_rectangle(llX, llY, width, height)
|
|
# This function uses GeometricShapeFactory to render
|
|
# a rectangle having lower-left corner at given coordinates
|
|
# and given sizes.
|
|
|
|
#shapefactory = Geos::GeometricShapeFactory.new(@geom_factory)
|
|
#shapefactory.set_base(Geos::Coordinate.new(llX, llY))
|
|
#shapefactory.set_height(height)
|
|
#shapefactory.set_width(width)
|
|
|
|
# we don't need more then 4 points for a rectangle...
|
|
#shapefactory.set_num_points(4)
|
|
# can use setSize for a square
|
|
#shapefactory.create_rectangle()
|
|
wkt = "POLYGON ((#{llX} #{llY}, #{llX} #{llY + height}, #{llX+width} #{llY+height}, #{llX+width} #{llY}, #{llX} #{llY}))"
|
|
reader = Geos::WktReader.new
|
|
reader.read(wkt)
|
|
end
|
|
|
|
def create_arc(llX, llY, width, height, startang, endang)
|
|
# This function uses GeometricShapeFactory to render
|
|
# an arc having lower-left corner at given coordinates,
|
|
# given sizes and given angles.
|
|
|
|
#shapefactory = Geos::GeometricShapeFactory.new(@geom_factory)
|
|
#shapefactory.set_base(Geos::Coordinate.new(llX, llY))
|
|
#shapefactory.set_height(height)
|
|
#shapefactory.set_width(width)
|
|
# the default (100 pts)
|
|
#shapefactory.set_num_points(100)
|
|
|
|
#shapefactory.create_arc(startang, endang)
|
|
wkt = "LINESTRING (5.00 20.00, 5.00 20.00, 5.00 20.00, 5.50 20.00, 5.50 20.00, 5.50 20.00, 5.50 20.00, 5.50 20.00, 5.50 20.00, 6.00 20.00, 6.00 20.00, 6.00 20.00, 6.00 20.00, 6.00 20.00, 6.00 19.50, 6.00 19.50, 6.50 19.50, 6.50 19.50, 6.50 19.50, 6.50 19.50, 6.50 19.50, 6.50 19.50, 7.00 19.50, 7.00 19.50, 7.00 19.00, 7.00 19.00, 7.00 19.00, 7.00 19.00, 7.00 19.00, 7.50 19.00, 7.50 19.00, 7.50 19.00, 7.50 18.50, 7.50 18.50, 7.50 18.50, 7.50 18.50, 7.50 18.50, 8.00 18.50, 8.00 18.00, 8.00 18.00, 8.00 18.00, 8.00 18.00, 8.00 18.00, 8.00 17.50, 8.00 17.50, 8.50 17.50, 8.50 17.50, 8.50 17.50, 8.50 17.00, 8.50 17.00, 8.50 17.00, 8.50 17.00, 8.50 16.50, 9.00 16.50, 9.00 16.50, 9.00 16.50, 9.00 16.50, 9.00 16.00, 9.00 16.00, 9.00 16.00, 9.00 16.00, 9.00 15.50, 9.00 15.50, 9.00 15.50, 9.50 15.00, 9.50 15.00, 9.50 15.00, 9.50 15.00, 9.50 14.50, 9.50 14.50, 9.50 14.50, 9.50 14.50, 9.50 14.00, 9.50 14.00, 9.50 14.00, 9.50 13.50, 9.50 13.50, 9.50 13.50, 9.50 13.00, 10.00 13.00, 10.00 13.00, 10.00 13.00, 10.00 12.50, 10.00 12.50, 10.00 12.50, 10.00 12.00, 10.00 12.00, 10.00 12.00, 10.00 11.50, 10.00 11.50, 10.00 11.50, 10.00 11.50, 10.00 11.00, 10.00 11.00, 10.00 11.00, 10.00 10.50, 10.00 10.50, 10.00 10.50, 10.00 10.00, 10.00 10.00)"
|
|
reader = Geos::WktReader.new
|
|
reader.read(wkt)
|
|
end
|
|
|
|
def create_geoms
|
|
geoms = Array.new
|
|
|
|
geoms.push(create_point(150, 350))
|
|
geoms.push(create_square_linear_ring(0,0,100))
|
|
geoms.push(create_ushaped_linestring(60,60,100))
|
|
geoms.push(create_square_linear_ring(0,0,100))
|
|
geoms.push(create_square_polygon(0,200,300))
|
|
geoms.push(create_square_polygon(0,250,300))
|
|
geoms.push(create_simple_collection(geoms))
|
|
|
|
# These ones use a GeometricShapeFactory
|
|
geoms.push(create_circle(0, 0, 10))
|
|
geoms.push(create_ellipse(0, 0, 8, 12))
|
|
# A square
|
|
geoms.push(create_rectangle(-5, -5, 10, 10))
|
|
# A rectangle
|
|
geoms.push(create_rectangle(-5, -5, 10, 20))
|
|
# The upper-right quarter of a vertical ellipse
|
|
geoms.push(create_arc(0, 0, 10, 20, 0, Math::PI/2))
|
|
|
|
return geoms
|
|
end
|
|
|
|
def print_geoms(geoms)
|
|
geoms.each do |geom|
|
|
wkt = Geos.geom_to_wkt(geom)
|
|
STDOUT << wkt << "\n"
|
|
end
|
|
end
|
|
|
|
# ----- xml support ---------
|
|
def load_tests(file_name)
|
|
current_path = File.expand_path(__FILE__)
|
|
xml_path = File.join(current_path, "..", "..", "..", "..", "tests", "xmltester")
|
|
file_path = File.expand_path(File.join(xml_path, file_name))
|
|
|
|
file = File.new(file_path)
|
|
result = nil
|
|
begin
|
|
doc = REXML::Document.new(file)
|
|
result = load_cases(doc)
|
|
ensure
|
|
file.close
|
|
end
|
|
result
|
|
end
|
|
|
|
def parse_geometry(value)
|
|
value.strip!
|
|
|
|
if value.match(/\A[0-9A-F]/)
|
|
reader = Geos::WkbReader.new
|
|
reader.read_hex(value)
|
|
else
|
|
reader = Geos::WktReader.new
|
|
reader.read(value)
|
|
end
|
|
end
|
|
|
|
def load_cases(doc)
|
|
case_id = 1
|
|
result = Array.new
|
|
|
|
# get the run element
|
|
run_element = doc.elements["run"]
|
|
|
|
# Iterate over each case
|
|
run_element.elements.each("case") do |case_element|
|
|
test_id = 1
|
|
# Get geometry a
|
|
a_element = case_element.elements["a"]
|
|
geom1 = parse_geometry(a_element.text) if a_element
|
|
|
|
# Get geometry b
|
|
b_element = case_element.elements["b"]
|
|
geom2 = parse_geometry(b_element.text) if b_element
|
|
|
|
# Iterate over each test in this case
|
|
case_element.elements.each("test") do |test_element|
|
|
operation_element = test_element.elements["op"]
|
|
|
|
# Get operation name and result
|
|
operation = operation_element.attributes['name'].strip!
|
|
expected = operation_element.text.strip!
|
|
|
|
# Figure arguments
|
|
arg1 = operation_element.attributes['arg1']
|
|
arg2 = operation_element.attributes['arg2']
|
|
arg3 = operation_element.attributes['arg3']
|
|
|
|
arg1.strip! if arg1
|
|
arg2.strip! if arg2
|
|
arg3.strip! if arg3
|
|
|
|
# Create test
|
|
test = XmlTest.new(case_id, test_id,
|
|
operation, expected,
|
|
geom1, geom2,
|
|
arg1, arg2, arg3)
|
|
result.push(test)
|
|
test_id += 1
|
|
end
|
|
case_id += 1
|
|
end
|
|
result
|
|
end
|
|
end |