# frozen_string_literal: true # ----------------------------------------------------------------------------- # # Feature factory interface # # ----------------------------------------------------------------------------- module RGeo module Feature # This is a standard interface for factories of features. # Generally, each Feature implementation will implement these # methods as a standard way to create features. # # If the implementation is unable to create the given feature, # it should generally return nil. Implementations may also choose to # raise an exception on failure. # # Some implementations may extend this interface to provide facilities # for creating additional objects according to the capabilities # provided by that implementation. Examples might include # higher-dimensional coordinates or additional subclasses not # explicitly required by the Simple Features Specification. # # Factory is defined as a module and is provided primarily for the # sake of documentation. Implementations need not necessarily include # this module itself. Therefore, you should not depend on the result # of is_a?(Factory) to check type. However, to support # testing for factory-ness, the Factory::Instance submodule # is provided. All factory implementation classes MUST include # Factory::Instance, and you may use it in is_a?, # ===, and case-when constructs. module Factory # All factory implementations MUST include this submodule. # This serves as a marker that may be used to test an object for # factory-ness. module Instance end # Returns meta-information about this factory, by key. This # information may involve support for optional functionality, # properties of the coordinate system, or other characteristics. # # Each property has a symbolic name. Names that have no periods are # considered well-known names and are reserved for use by RGeo. If # you want to define your own properties, use a name that is # namespaced with periods, such as :'mycompany.myprop'. # # Property values are dependent on the individual property. # Generally, properties that involve testing for functionality # should return true if the functionality is support, or false or # nil if not. A property value could also invlove different values # indicating different levels of support. In any case, the factory # should return nil for property names it does not recognize. This # value is considered the "default" or "no value" value. # # Currently defined well-known properties are: # # [:has_z_coordinate] # Set to true if geometries created by this factory include a Z # coordinate, and the Point#z method is available. # [:has_m_coordinate] # Set to true if geometries created by this factory include a M # coordinate, and the Point#m method is available. # [:is_cartesian] # Set to true if this Factory guarantees that it operates in # Cartesian geometry. If false or nil, no such guarantee is made, # though it is possible the geometries may still be Cartesian. # [:is_geographic] # Set to true if this Factory's coordinate system is meant to be # interpreted as x=longitude and y=latitude. If false or nil, no # information is present about whether the coordinate system is # meant to be so interpreted. def property(name) nil end # Parse the given string in well-known-text format and return the # resulting feature. Returns nil if the string couldn't be parsed. def parse_wkt(str) nil end # Parse the given string in well-known-binary format and return the # resulting feature. Returns nil if the string couldn't be parsed. def parse_wkb(str) nil end # Create a feature of type Point. # The x and y parameters should be Float values. # # The extra parameters should be the Z and/or M coordinates, if # supported. If both Z and M coordinates are supported, Z should # be passed first. def point(x, y, *extra) nil end # Create a feature of type LineString. # The given points argument should be an Enumerable of Point # objects, or objects that can be cast to Point. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def line_string(points) nil end # Create a feature of type Line. # The given point arguments should be Point objects, or objects # that can be cast to Point. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def line(start, stop) nil end # Create a feature of type LinearRing. # The given points argument should be an Enumerable of Point # objects, or objects that can be cast to Point. # If the first and last points are not equal, the ring is # automatically closed by appending the first point to the end of the # string. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def linear_ring(points) nil end # Create a feature of type Polygon. # The outer_ring should be a LinearRing, or an object that can be # cast to LinearRing. # The inner_rings should be a possibly empty Enumerable of # LinearRing (or objects that can be casted to LinearRing). # You may also pass nil to indicate no inner rings. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def polygon(outer_ring, inner_rings = nil) nil end # Create a feature of type GeometryCollection. # The elems should be an Enumerable of Geometry objects. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def collection(elems) nil end # Create a feature of type MultiPoint. # The elems should be an Enumerable of Point objects, or objects # that can be cast to Point. # Returns nil if any of the contained geometries is not a Point, # which would break the MultiPoint contract. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def multi_point(elems) nil end # Create a feature of type MultiLineString. # The elems should be an Enumerable of objects that are or can be # cast to LineString or any of its subclasses. # Returns nil if any of the contained geometries is not a # LineString, which would break the MultiLineString contract. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def multi_line_string(elems) nil end # Create a feature of type MultiPolygon. # The elems should be an Enumerable of objects that are or can be # cast to Polygon or any of its subclasses. # Returns nil if any of the contained geometries is not a Polygon, # which would break the MultiPolygon contract. # Also returns nil if any of the other assertions for MultiPolygon # are not met, e.g. if any of the polygons overlap. # # Although implementations are free to attempt to handle input # objects that are not of this factory, strictly speaking, the # result of building geometries from objects of the wrong factory # is undefined. def multi_polygon(elems) nil end # Returns a RGeo::CoordSys::Proj4 representing the projection for # the coordinate system of features created by this factory, or nil # if there is no such proj4 projection. def proj4 nil end # Returns the coordinate system specification for the features # created by this factory, or nil if there is no such coordinate # system. # # NOTE: This is a required method of the factory interface, but the # coordinate system classes themselves are not yet available, so # implementations should just return nil for now. def coord_sys nil end # This is an optional method that may be implemented to customize # casting for this factory. Basically, RGeo defines standard ways # to cast certain types of objects from one factory to another and # one SFS type to another. However, a factory may choose to # override how things are casted TO its implementation using this # method. It can do this to optimize certain casting cases, or # implement special cases particular to this factory. # # This method will be called (if defined) on the destination # factory, and will be passed the original object (which may or may # not already be created by this factory), the SFS feature type # (which again may or may not already be the type of the original # object), and a hash of additional flags. These flags are: # # [:keep_subtype] # indicates whether to keep the subtype if casting to a supertype # of the current type # [:force_new] # indicates whether to force the creation of a new object even if # the original is already of the desired factory and type # [:project] # indicates whether to project the coordinates from the source to # the destination proj4 coordinate system, if available # # It should return either a casted result object, false, or nil. # A nil return value indicates that casting should be forced to # fail (and RGeo::Feature.cast will return nil). # A false return value indicates that this method declines to # override the casting algorithm, and RGeo should use its default # algorithm to cast the object. Therefore, by default, you should # return false. def override_cast(original, type, flags) false end end end end