--
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-- $Log$
+-- Revision 1.14 2003/08/08 18:19:20 dblasby
+-- Conformance changes.
+-- Removed junk from postgis_debug.c and added the first run of the long
+-- transaction locking support. (this will change - dont use it)
+-- conformance tests were corrected
+-- some dos cr/lf removed
+-- empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+-- pointN(<linestring>,1) now returns the first point (used to return 2nd)
+--
-- Revision 1.13 2003/08/06 19:31:18 dblasby
-- Added the WKB parser. Added all the functions like
-- PolyFromWKB(<WKB>,[<SRID>]).
AS '@MODULE_FILENAME@','LinefromWKB_SRID'
LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION LinestringFromWKB(wkb,int)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','LinefromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION LinestringFromWKB(wkb)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','LinefromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
CREATE FUNCTION PolyFromWKB(wkb,int)
RETURNS GEOMETRY
AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
RETURNS GEOMETRY
AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION PolygonFromWKB(wkb,int)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION PolygonFromWKB(wkb)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','PolyfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
CREATE FUNCTION MPointFromWKB(wkb,int)
RETURNS GEOMETRY
RETURNS GEOMETRY
AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
LANGUAGE 'C' WITH (iscachable,isstrict);
+
+
+CREATE FUNCTION MultiPointFromWKB(wkb,int)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION MultiPointFromWKB(wkb)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MPointfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION MultiLineFromWKB(wkb,int)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION MultiLineFromWKB(wkb)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MLinefromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
CREATE FUNCTION MLineFromWKB(wkb,int)
RETURNS GEOMETRY
AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
LANGUAGE 'C' WITH (iscachable,isstrict);
+CREATE FUNCTION MultiPolyFromWKB(wkb,int)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATE FUNCTION MultiPolyFromWKB(wkb)
+ RETURNS GEOMETRY
+ AS '@MODULE_FILENAME@','MPolyfromWKB_SRID'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
+
+
CREATE FUNCTION GeomCollFromWKB(wkb,int)
RETURNS GEOMETRY
AS '@MODULE_FILENAME@','GCfromWKB_SRID'
AS '@MODULE_FILENAME@'
LANGUAGE 'C' WITH (isstrict);
-CREATE FUNCTION numb_sub_objs(geometry)
- RETURNS int4
- AS '@MODULE_FILENAME@'
- LANGUAGE 'C' WITH (isstrict);
CREATE FUNCTION summary(geometry)
RETURNS text
AS '@MODULE_FILENAME@','geometry_from_text_poly'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION polygonfromtext(geometry,int4)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_poly'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION polygonfromtext(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_poly'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION mpolyfromtext(geometry,int4)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
AS '@MODULE_FILENAME@','geometry_from_text_line'
LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION mlinefromtext(geometry,int4)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_mline'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION multilinestringfromtext(geometry,int4)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mline'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION multilinestringfromtext(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mline'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION pointfromtext(geometry,int4)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_point'
AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION multipointfromtext(geometry,int4)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION multipointfromtext(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mpoint'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION geomcollfromtext(geometry,int4)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_gc'
CREATE FUNCTION setSRID(geometry,int4)
RETURNS geometry
- AS '@MODULE_FILENAME@','geometry_from_text_gc'
+ AS '@MODULE_FILENAME@','geometry_from_text'
LANGUAGE 'C' WITH (isstrict,iscachable);
CREATE FUNCTION polyfromtext(geometry)
AS '@MODULE_FILENAME@','geometry_from_text_poly'
LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION mpolyfromtext(geometry)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION multipolygonfromtext(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION multipolygonfromtext(geometry,int)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_mpoly'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
CREATE FUNCTION linefromtext(geometry)
RETURNS geometry
AS '@MODULE_FILENAME@','geometry_from_text_line'
LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION linestringfromtext(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_line'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION linestringfromtext(geometry,int)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','geometry_from_text_line'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
CREATE FUNCTION mlinefromtext(geometry)
RETURNS geometry
LANGUAGE 'C' WITH (isstrict,iscachable);
+CREATE FUNCTION isempty(geometry)
+ RETURNS int
+ AS '@MODULE_FILENAME@','isempty'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION issimple(geometry)
+ RETURNS boolean
+ AS '@MODULE_FILENAME@','issimple'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE FUNCTION equals(geometry,geometry)
+ RETURNS boolean
+ AS '@MODULE_FILENAME@','geomequals'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
--
RETURNS geometry
AS '@MODULE_FILENAME@'
LANGUAGE 'C' WITH (isstrict);
+
+CREATE FUNCTION isring(geometry)
+ RETURNS boolean
+ AS '@MODULE_FILENAME@'
+ LANGUAGE 'C' WITH (isstrict);
+
+CREATE FUNCTION pointonsurface(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@'
+ LANGUAGE 'C' WITH (isstrict);
+
--
-- BBox operations
AS '@MODULE_FILENAME@','symdifference'
LANGUAGE 'C' WITH (isstrict);
+
+ CREATE FUNCTION symmetricdifference(geometry,geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','symdifference'
+ LANGUAGE 'C' WITH (isstrict);
+
+
CREATE FUNCTION GeomUnion(geometry,geometry)
RETURNS geometry
AS '@MODULE_FILENAME@','geomunion'
# GEOMETRY_COLUMNS, so see the list archives for info or
# install a fresh database using postgis.sql
#
-USE_STATS=0
+USE_STATS=1
#---------------------------------------------------------------
subdir=contrib/postgis
running. This is useful in binary cursors to pull data out of
the database without converting it to a string representation.
</para>
+ <para>OGC SPEC s2.1.1.1 - also see asBinary(<geometry>,'XDR') and asBinary(<geometry>,'NDR')
</listitem>
</varlistentry>
<varlistentry>
<term>Dimension(geometry)</term>
<listitem>
- <para>Returns '2' if the geometry is two dimensional and '3' if the
- geometry is three dimensional.
+ <para>The inherent dimension of this Geometry object, which must be less than or equal
+to the coordinate dimension. OGC SPEC s2.1.1.1 - returns 0 for points, 1 for lines, 2 for polygons, and the largest dimension of the components of a GEOMETRYCOLLECTION.
</para>
+ <programlisting>select dimension('GEOMETRYCOLLECTION(LINESTRING(1 1,0 0),POINT(0 0)');
+dimension
+-----------
+1</programlisting>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>isEmpty(geometry)</term>
+ <listitem>
+ <para>
+ Returns 1 (TRUE) if this Geometry is the empty geometry . If true, then this
+Geometry represents the empty point set - i.e. GEOMETRYCOLLECTION(EMPTY).
+ </para>
+ <para>OGC SPEC s2.1.1.1 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>isSimple(geometry)</term>
+ <listitem>
+ <para>
+ Returns 1 (TRUE) if this Geometry has no anomalous geometric points, such as self
+ intersection or self tangency.
+ </para>
+ <para>Performed by the GEOS module</para>
+
+ <para>OGC SPEC s2.1.1.1 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>boundary(geometry)</term>
+ <listitem>
+ <para>
+ Returns the closure of the combinatorial boundary of this Geometry. The
+ combinatorial boundary is defined as described in section 3.12.3.2 of the OGC SPEC. Because the result of this function
+ is a closure, and hence topologically closed, the resulting boundary can be represented using
+representational geometry primitives as discussed in the OGC SPEC, section 3.12.2.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>OGC SPEC s2.1.1.1 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>equals(geometry)</term>
+ <listitem>
+ <para>
+ Returns 1 (TRUE) if this Geometry is \91spatially equal\92 to
+anotherGeometry. Use this for a 'better' answer than '='. equals ('LINESTRING(0 0, 10 10)','LINESTRING(0 0, 5 5, 10 10)') is true.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>OGC SPEC s2.1.1.1 </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>disjoint(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry is \91spatially disjoint\92 from anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 //s2.1.13.3 - a.Relate(b, \91FF*FF****\92) </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>intersects(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry \91spatially intersects\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 //s2.1.13.3 - Intersects(g1, g2 ) --> Not (Disjoint(g1, g2 )) </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>touches(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry \91spatially touches\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3- a.Touches(b) -> (I(a) intersection I(b) = {empty set} ) and (a intersection b) not empty </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>crosses(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry \91spatially crosses\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 - a.Relate(b, \91T*T******\92) </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>within(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry is \91spatially within\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 - a.Relate(b, \91T*F**F***\92) </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>overlaps(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry is \91spatially overlapping\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>contains(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry is \91spatially contains\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 - same as within(geometry,geometry)</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>intersects(geometry,geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Geometry is \91spatially intersects\92 anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 - NOT disjoint(geometry,geometry)</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>relate(geometry,geometry, intersectionPatternMatrix)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this
+Geometry is spatially related to anotherGeometry, by testing for intersections between the Interior,
+Boundary and Exterior of the two geometries as specified by the values in the intersectionPatternMatrix.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para> NOTE: this is the "allowable" version that returns a boolean, not an integer.
+ <para>OGC SPEC s2.1.1.1 // s2.1.13.3 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>relate(geometry,geometry)</term>
+ <listitem>
+ <para> returns the DE-9IM (dimensionally extended nine-intersection matrix)
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>not in OGC spec, but implied. see s2.1.13.2 </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>buffer(geometry,double)</term>
+ <listitem>
+ <para> Returns a geometry that represents all points whose distance from
+this Geometry is less than or equal to distance. Calculations are in the Spatial Reference System of this
+Geometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>convexhull(geometry)</term>
+ <listitem>
+ <para> Returns a geometry that represents the convex hull of this Geometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>intersection(geometry,geometry)</term>
+ <listitem>
+ <para> Returns a geometry that represents the point set
+intersection of this Geometry with anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>geomunion(geometry,geometry)</term>
+ <listitem>
+ <para> Returns a geometry that represents the point set union of
+this Geometry with anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>NOTE: this is renamed from "union" because union is an SQL reserved word</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>difference(geometry,geometry)</term>
+ <listitem>
+ <para> Returns a geometry that represents the point set
+difference of this Geometry with anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>difference(geometry,geometry)</term>
+ <listitem>
+ <para> Returns a geometry that represents the point set
+symmetric difference of this Geometry with anotherGeometry.
+ </para>
+ <para>Performed by the GEOS module</para>
+ <para>Do not call with a GeometryCollection as an argument</para>
+ <para>OGC SPEC s2.1.1.1</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>Envelope(geometry)</term>
<listitem>
<para>Returns a POLYGON representing the bounding box of the
geometry.
</para>
+ <para> OGC SPEC s2.1.1.1 - The minimum bounding box for this Geometry, returned as a Geometry. The
+polygon is defined by the corner points of the bounding box ((MINX, MINY), (MAXX, MINY), (MAXX,
+MAXY), (MINX, MAXY), (MINX, MINY)). </para><para>NOTE:PostGIS will add a Zmin/Zmax coordinate as well.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>GeometryType(geometry)</term>
<listitem>
<para>Returns the type of the geometry as a string. Eg: 'LINESTRING',
- 'POLYGON', 'MULTIPOINT', etc.
+ 'POLYGON', 'MULTIPOINT', etc.
</para>
+ <para>
+ OGC SPEC s2.1.1.1 - Returns the name of the instantiable subtype of Geometry of which this
+Geometry instance is a member. The name of the instantiable subtype of Geometry is returned as a string.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>IsRing(geometry)</term>
+ <listitem>
+ <para>Returns 1 (TRUE) if this Curve is closed (StartPoint ( ) = EndPoint ( )) and this Curve
+is simple (does not pass through the same point more than once).
+
+ </para>
+ <para>performed by GEOS</para>
+ <para> OGC spec 2.1.5.1</para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>NumGeometries(geometry)</term>
<listitem>
- <para>If geometry is a GEOMETRYCOLLECTION return the number of
+ <para>If geometry is a GEOMETRYCOLLECTION (or MULTI*) return the number of
geometries, otherwise return NULL.
</para>
</listitem>
GEOMETRYCOLLECTION, MULTIPOINT, MULTILINESTRING or
MULTIPOLYGON. Otherwise, return NULL.
</para>
+ <para>0 is 1st geometry</para>
</listitem>
</varlistentry>
<varlistentry>
<para>Return the Well-Known Text representation of the
geometry. For example: POLYGON(0 0,0 1,1 1,1 0,0 0)
</para>
+ <para>OGC SPEC s2.1.1.1</para>
</listitem>
</varlistentry>
<varlistentry>
<para>Returns the integer SRID number of the spatial
reference system of the geometry.
</para>
+ <para>OGC SPEC s2.1.1.1</para>
</listitem>
</varlistentry>
<varlistentry>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>area(geometry)</term>
+ <listitem>
+ <para>Returns the area of the geometry if it is a polygon or
+ multi-polygon. (same as area2(<polygon|multipolygon>)
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>asbinary(geometry,'NDR')</term>
<listitem>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>isvalid(geometry)</term>
+ <listitem>
+ <para>returns true if this geometry is valid.
+ </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>asbinary(geometry,'XDR')</term>
<listitem>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>GeomFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>GeometryFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PointFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a Point</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>LineFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a Line</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>LinestringFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> from the conformance suite</para>
+ <para> Throws an error if the WKT is not a Line</para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>PolyFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a Polygon</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PolygonFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> from the conformance suite</para>
+ <para> Throws an error if the WKT is not a Polygon</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MPointFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a MULTIPOINT</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MLineFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a MULTILINESTRING</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MPolyFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a MULTIPOLYGON</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>GeomCollFromText(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKT with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> Throws an error if the WKT is not a GEOMETRYCOLLECTION</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>GeomFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>GeometryFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PointFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a POINT </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>LineFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a LINESTRING </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>LinestringFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> from the conformance suite</para>
+ <para> throws an error if WKB is not a LINESTRING </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PolyFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a POLYGON </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PolygonFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> from the conformance suite</para>
+ <para> throws an error if WKB is not a POLYGON </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MPointFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a MULTIPOINT </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MLineFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a MULTILINESTRING </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>MPolyFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a MULTIPOLYGON </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>GeomCollFromWKB(text,[<srid>])</term>
+ <listitem>
+ <para>Makes a Geometry from WKB with the given SRID. If SRID is not give, it defaults to -1.</para>
+ <para> OGC SPEC 3.2.6.2 - option SRID is from the conformance suite</para>
+ <para> throws an error if WKB is not a GEOMETRYCOLLECTION </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>PointOnSurface(geometry)</term>
+ <listitem>
+ <para>Return a Point guaranteed to lie on the surface</para>
+ <para>Implemented using GEOS</para>
+ <para> OGC SPEC 3.2.14.2 and 3.2.18.2 - </para>
+ </listitem>
+ </varlistentry>
+
+
<varlistentry>
<term>box3d(geometry)</term>
<listitem>
linestring or multi-linestring.</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>length(geometry)</term>
+ <listitem>
+ <para>The length of this Curve in its associated spatial reference.</para>
+ <para>synonym for length2d()</para>
+ <para>OGC SPEC 2.1.5.1 </para>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term>length3d(geometry)</term>
<listitem>
--
--================================
--
-SELECT Union(shore, boundary)
+SELECT GeomUnion(shore, boundary)
FROM lakes, named_places
-WHERE lakes.name = 'Blue Lake' AND named_places.name = 'Ashton';
+WHERE lakes.name = 'Blue Lake' AND named_places.name = 'Goose Island';
--
--================================
-- Conformance Item T50
--
SELECT SymmetricDifference(shore, boundary)
FROM lakes, named_places
-WHERE lakes.name = 'Blue Lake' OR named_places.name = 'Ashton';
+WHERE lakes.name = 'Blue Lake' AND named_places.name = 'Goose Island';
--
--================================
-- Conformance Item T51
*
**********************************************************************
* $Log$
+ * Revision 1.33 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.32 2003/08/06 19:31:18 dblasby
* Added the WKB parser. Added all the functions like
* PolyFromWKB(<WKB>,[<SRID>]).
void set_point( POINT3D *pt,double x, double y, double z);
GEOMETRY *make_oneobj_geometry(int sub_obj_size, char *sub_obj, int type, bool is3d, int SRID,double scale, double offx,double offy);
-void print_box(BOX3D *box);
-void print_box_oneline(BOX3D *box);
+
void print_point(char *result, POINT3D *pt,bool is3d);
void print_many_points(char *result, POINT3D *pt ,int npoints, bool is3d);
void swap(double *d1, double *d2);
int size_subobject (char *sub_obj, int type);
GEOMETRY *add_to_geometry(GEOMETRY *geom,int sub_obj_size, char *sub_obj, int type);
LINE3D *make_line(int npoints, POINT3D *pts, int *size);
-char *print_geometry(GEOMETRY *geom);
+
void swap_char(char *a, char*b);
void flip_endian_double(char *dd);
char *to_wkb_collection(GEOMETRY *geom, bool flip_endian, int32 *size);
char *to_wkb_sub(GEOMETRY *geom, bool flip_endian, int32 *wkb_size);
-void decode_wkb_collection(char *wkb,int *size);
-void decode_wkb(char *wkb, int *size);
-void dump_bytes( char *a, int numb);
+
double deltaLongitude(double azimuth, double sigma, double tsm,SPHEROID *sphere);
double bigA(double u2);
Datum optimistic_overlap(PG_FUNCTION_ARGS);
-void print_point_debug(POINT3D *p);
+
unsigned char parse_hex(char *str);
void deparse_hex(unsigned char str, unsigned char *result);
POINT3D *wkb_linearring(char *WKB,char is3d, char flip_endian, int *numbPoints, int *bytes,int bytes_in_stream);
+GEOMETRY *makeNullGeometry(int SRID);
+
+void compressType(GEOMETRY *g);
+
+
//exposed to psql
Datum box3d_in(PG_FUNCTION_ARGS);
Datum npoints(PG_FUNCTION_ARGS);
Datum nrings(PG_FUNCTION_ARGS);
Datum mem_size(PG_FUNCTION_ARGS);
-Datum numb_sub_objs(PG_FUNCTION_ARGS);
Datum summary(PG_FUNCTION_ARGS);
Datum translate(PG_FUNCTION_ARGS);
Datum geometry_from_text_line(PG_FUNCTION_ARGS);
Datum geometry_from_text_mline(PG_FUNCTION_ARGS);
Datum geometry_from_text_gc(PG_FUNCTION_ARGS);
+Datum isempty(PG_FUNCTION_ARGS);
/*--------------------------------------------------------------------
* Useful floating point utilities and constants.
*
* This is free software; you can redistribute and/or modify it under
* the terms of hte GNU General Public Licence. See the COPYING file.
- *
+ *
**********************************************************************
* $Log$
+ * Revision 1.11 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.10 2003/07/25 17:08:37 pramsey
* Moved Cygwin endian define out of source files into postgis.h common
* header file.
#include "postgis.h"
#include "utils/elog.h"
+#include "executor/spi.h"
+#include "commands/trigger.h"
+
#define SHOW_DIGS_DOUBLE 15
#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
// #define DEBUG_GIST
//#define DEBUG_GIST2
-void print_box2d(BOX *box);
-
-
-void dump_bytes( char *a, int numb)
-{
- int t;
- for (t=0; t<numb; t++)
- {
- printf(" + Byte #%i has value %i (%x)\n",t,a[t],a[t]);
- }
-}
-//debug function - whats really in that BOX3D?
-void print_box(BOX3D *box)
-{
- printf("box is at %p\n",box);
- if (box == NULL)
- {
- printf (" + BOX IS NULL\n");
- return;
- }
- printf(" + LLB = [%g,%g,%g]\n", box->LLB.x, box->LLB.y,box->LLB.z);
- printf(" + URT = [%g,%g,%g]\n", box->URT.x, box->URT.y,box->URT.z);
-}
-
-void print_box2d(BOX *box)
-{
- printf (" BOX[%g %g , %g %g] ",box->low.x, box->low.y, box->high.x, box->high.y);
-}
-
-//debug function - whats really in that BOX3D?
-void print_box_oneline(BOX3D *box)
-{
- printf(" (%p) {",box);
- if (box == NULL)
- {
- printf ("BOX IS NULL}");
- return;
- }
- printf("[%g,%g,%g] ", box->LLB.x, box->LLB.y,box->LLB.z);
- printf("[%g,%g,%g]}", box->URT.x, box->URT.y,box->URT.z);
-}
//find the size of geometry
PG_FUNCTION_INFO_V1(mem_size);
PG_RETURN_INT32(geom1->size);
}
-//find the size of geometry
-PG_FUNCTION_INFO_V1(numb_sub_objs);
-Datum numb_sub_objs(PG_FUNCTION_ARGS)
-{
- GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- PG_RETURN_INT32(geom1->nobjs);
-}
//get summary info on a GEOMETRY
PG_FUNCTION_INFO_V1(summary);
-// DO NOT USE THESE decoding function (except for debugging purposes)
-// The code is NOT maintained and is thrown together
-// unsupported debugging function.
-// given a wkb input thats a geometrycollection, returns its size and prints out
-// its contents
-//
-// Its really messy - dont even think about using this for anything
-//
-// you shouldnt call this function; just call decode_wkb() and it will
-// call this function
-//
-void decode_wkb_collection(char *wkb,int *size)
-{
- int offset =0;
- bool flipbytes;
- int total_size=0,sub_size;
- int numb_sub,t;
- bool first_one = TRUE;
+extern Datum lockcheck(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(lockcheck);
- if (wkb[0] ==0 ) //big endian
- {
- if (BYTE_ORDER == LITTLE_ENDIAN)
- flipbytes= 1;
- else
- flipbytes= 0;
- }
- else //little
+Datum lockcheck (PG_FUNCTION_ARGS)
+{
+ TriggerData *trigdata = (TriggerData *) fcinfo->context;
+ char *colname ;
+ char *locktablename ;
+ int id;
+ HeapTuple rettuple;
+ TupleDesc tupdesc;
+ int SPIcode;
+ char *relname;
+ bool isnull;
+ char query[1024];
+
+ elog(NOTICE,"in lockcheck()");
+
+ /* Make sure trigdata is pointing at what I expect */
+ if (!CALLED_AS_TRIGGER(fcinfo))
+ elog(ERROR, "lockcheck: not fired by trigger manager");
+
+ rettuple = trigdata->tg_newtuple;
+ tupdesc = trigdata->tg_relation->rd_att;
+
+ /* Connect to SPI manager */
+ SPIcode = SPI_connect();
+
+ if (SPIcode != SPI_OK_CONNECT)
{
- if (BYTE_ORDER == LITTLE_ENDIAN)
- flipbytes= 0;
- else
- flipbytes= 1;
+ elog(ERROR,"lockcheck: couldnt open a connection to SPI");
+ PG_RETURN_NULL() ;
}
- memcpy(&numb_sub, wkb+5,4);
- if (flipbytes)
- flip_endian_int32( (char *) & numb_sub) ;
+ relname = SPI_getrelname(trigdata->tg_relation);
- printf("GEOMETRYCOLLECTION(\n");
- offset = 9;
- for (t=0;t<numb_sub;t++)
- {
- if (first_one)
- {
- first_one = FALSE;
- }
- else
- {
- printf(",");
- }
+ colname = trigdata->tg_trigger->tgargs[0];
- printf(" ");
- decode_wkb( wkb + offset, &sub_size);
- total_size += sub_size;
- offset += sub_size;
- }
- *size = total_size +9 ;
- printf(")\n");
- return;
-}
+ locktablename = trigdata->tg_trigger->tgargs[1];
-// unsupported debugging function.
-// given a wkb input, returns its size and prints out
-// its contents
-//
-// Its really messy - dont even think about using this for anything
-//
-//dump wkb to screen (for debugging)
-// assume endian is constant though out structure
-void decode_wkb(char *wkb, int *size)
-{
-
- bool flipbytes;
- uint32 type;
- uint32 n1,n2,n3,t,u,v;
- bool is3d;
- bool first_one,first_one2,first_one3;
+ elog(NOTICE,"trigger was executed on the relation: '%s', with attribute named '%s', with locktable named '%s'", relname,colname,locktablename);
- int offset,offset1;
- double x,y,z;
- int total_points;
+ //get the value
+ id = (int) DatumGetInt32( SPI_getbinval(rettuple, tupdesc, SPI_fnumber(tupdesc,colname), &isnull) );
+ sprintf(query,"SELECT lock_key FROM %s WHERE expires >= now() AND id = %i", locktablename,id);
+ elog(NOTICE,"about to execute :%s", query);
+ SPIcode = SPI_exec(query,0);
+ if (SPIcode !=SPI_OK_SELECT )
+ elog(ERROR,"couldnt execute to test for lock :%s",query);
- //printf("decoding wkb\n");
-
- if (wkb[0] ==0 ) //big endian
- {
- if (BYTE_ORDER == LITTLE_ENDIAN)
- flipbytes= 1;
- else
- flipbytes= 0;
- }
- else //little
+ if (SPI_processed >0)
{
- if (BYTE_ORDER == LITTLE_ENDIAN)
- flipbytes= 0;
- else
- flipbytes= 1;
- }
-
- //printf(" + flipbytes = %i\n", flipbytes);
+ // there is a lock - check to see if I have rights to it!
- //printf("info about wkb:\n");
- memcpy(&type, wkb+1,4);
- if (flipbytes)
- flip_endian_int32( (char *) & type) ;
+ TupleDesc tupdesc = SPI_tuptable->tupdesc;
+ SPITupleTable *tuptable = SPI_tuptable;
+ HeapTuple tuple = tuptable->vals[0];
+ char *lockcode = SPI_getvalue(tuple, tupdesc, 1);
- is3d = 0;
+ elog(NOTICE,"there is a lock on this row!");
- if (type > 1000 )
- {
- is3d = 1;
- type = type - 32768;
- }
- //printf(" Type = %i (is3d = %i)\n", type, is3d);
- if (type == 1) //POINT()
- {
- printf("POINT(");
- if (is3d)
+ // check to see if temp_lock_have_table table exists (it might not exist if they own no locks
+ sprintf(query,"SELECT * FROM pg_class WHERE relname = 'temp_lock_have_table'");
+ SPIcode = SPI_exec(query,0);
+ if (SPIcode !=SPI_OK_SELECT )
+ elog(ERROR,"couldnt execute to test for lockkey temp table :%s",query);
+ if (SPI_processed ==0)
{
- memcpy(&x, &wkb[5], 8);
- memcpy(&y, &wkb[5+8], 8);
- memcpy(&z, &wkb[5+16], 8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g)",x,y,z );
+ elog(NOTICE,"I do not own any locks (no lock table) - I cannot modify the row");
+ //PG_RETURN_NULL();
+ SPI_finish();
+ return NULL;
}
- else
- {
- memcpy(&x, &wkb[5], 8);
- memcpy(&y, &wkb[5+8], 8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g)", x,y);
- }
- printf("\n");
- if (is3d)
- *size = 29;
- else
- *size = 21;
- return;
- }
- if (type == 2)
- {
- printf("LINESTRING(");
- memcpy(&n1, &wkb[5],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n1) ;
- // printf(" --- has %i sub points\n",n1);
- first_one = TRUE;
- for (t=0; t<n1; t++)
- {
- if (first_one)
- {
- first_one = FALSE;
- }
- else
- {
- printf(",");
- }
- if (is3d)
- {
- memcpy(&x, &wkb[9+t*24],8);
- memcpy(&y, &wkb[9+t*24+8],8);
- memcpy(&z, &wkb[9+t*24+16],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g",x,y,z);
- }
- else
- {
- memcpy(&x, &wkb[9+t*16],8);
- memcpy(&y, &wkb[9+t*16+8],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g",x,y);
- }
- }
-
-
- printf(")\n");
- if (is3d)
- *size = 9 + n1*24;
- else
- *size = 9 + n1*16;
- return;
- }
- if (type == 3)
- {
- *size = 9;
- printf("POLYGON(");
- memcpy(&n1, &wkb[5],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n1) ;
- //printf(" --- has %i rings\n",n1);
- *size += 4*n1;
- offset= 9;
- first_one = TRUE;
- for (u=0; u<n1; u++)
- {
- memcpy(&n2, &wkb[offset],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n2) ;
- // printf(" ring %i: has %i points\n",u,n2);
+ sprintf(query,"SELECT * FROM temp_lock_have_table WHERE xideq(transid , getTransactionID() ) AND lockcode =%s",lockcode);
+ elog(NOTICE,"about to execute :%s", query);
- if (first_one)
- {
- first_one = FALSE;
- }
- else
- {
- printf(",");
- }
- printf("(");
+ SPIcode = SPI_exec(query,0);
+ if (SPIcode !=SPI_OK_SELECT )
+ elog(ERROR,"couldnt execute to test for lock aquire:%s",query);
- first_one2 = TRUE;
- for (v=0; v< n2; v++)
- {
- if (first_one2)
- {
- first_one2 = FALSE;
- }
- else
- {
- printf(",");
- }
- if (is3d)
- {
- memcpy(&x, &wkb[offset + 4+ v*24],8);
- memcpy(&y, &wkb[offset + 4+ v*24 + 8],8);
- memcpy(&z, &wkb[offset + 4+ v*24 + 16],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g",x,y,z);
-
- }
- else
- {
- memcpy(&x, &wkb[offset +4 +v*16],8);
- memcpy(&y, &wkb[offset +4 +v*16 + 8],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g",x,y);
-
- }
- }
- if (is3d)
- {
- offset +=4 +24*n2;
- *size += n2*24;
- }
- else
- {
- offset += 4+ 16*n2;
- *size += n2*16;
- }
- printf(")");
- }
-
- printf(")\n");
-
- return;
-
- }
- if (type == 4)
+ if (SPI_processed >0)
{
- printf("MULTIPOINT(");
- memcpy(&n1,&wkb[5],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n1) ;
- // printf(" -- has %i points\n",n1);
- if (is3d)
- *size = 9 + n1*29;
- else
- *size = 9 + n1*21;
- first_one = TRUE;
- for (t=0; t<n1; t++)
- {
- if (first_one)
- {
- first_one= FALSE;
- }
- else
- {
- printf(",");
- }
- if (is3d)
- {
- memcpy(&x, &wkb[9+t*29+5],8);
- memcpy(&y, &wkb[9+t*29+8+5],8);
- memcpy(&z, &wkb[9+t*29+16+5],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g",x,y,z);
- }
- else
- {
- memcpy(&x, &wkb[9+t*21+5],8);
- memcpy(&y, &wkb[9+t*21+8+5],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g",x,y);
- }
- }
- printf (")\n");
- return;
+ elog(NOTICE,"I own the lock - I can modify the row");
+ SPI_finish();
+ return PointerGetDatum(rettuple);
}
- if (type == 5)
- {
- *size = 9;
- printf("MULTILINESTRING(");
- memcpy(&n2,&wkb[5],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n2) ;
- // printf(" -- has %i sub-lines\n",n2);
- *size += 9 *n2;
- offset =9;
- first_one2 = TRUE;
- for (u=0; u<n2; u++)
- {
- if (first_one2)
- {
- first_one2= FALSE;
- }
- else
- {
- printf(",");
- }
- printf("(");
- memcpy(&n1, &wkb[5 +offset],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n1) ;
- // printf(" --- has %i sub points\n",n1);
- first_one = TRUE;
- for (t=0; t<n1; t++)
- {
- if (first_one)
- {
- first_one= FALSE;
- }
- else
- {
- printf(",");
- }
-
- if (is3d)
- {
- memcpy(&x, &wkb[offset+9+t*24],8);
- memcpy(&y, &wkb[offset+9+t*24+8],8);
- memcpy(&z, &wkb[offset+9+t*24+16],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g",x,y,z);
- }
- else
- {
- memcpy(&x, &wkb[offset+9+t*16],8);
- memcpy(&y, &wkb[offset+9+t*16+8],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g",x,y);
- }
- }
- printf(")");
- if (is3d)
- {
- *size += (24*n1);
- offset += 9 + (24*n1);
- }
- else
- {
- *size += (16*n1);
- offset += 9 + (16*n1);
- }
- }
- printf(")\n");
- return;
+ elog(NOTICE,"I do not own the lock - I cannot modify the row");
+ //PG_RETURN_NULL();
+ SPI_finish();
+ return NULL;
}
- if (type == 6)
+ else
{
- *size = 9;
- printf("MULTIPOLYGON(");
- memcpy(&n3,&wkb[5],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n3) ;
- //printf(" -- has %i sub-poly\n",n3);
- *size += 9*n3;
- offset1 =9;//where polygon starts
- first_one3= TRUE;
- for (t=0;t<n3; t++) //for each polygon
- {
- if (first_one3)
- {
- first_one3= FALSE;
- }
- else
- {
- printf(",");
- }
- printf("(");
- //printf("polygon #%i\n",t);
- total_points = 0;
- memcpy(&n1,&wkb[offset1+5],4); //# rings
- *size += 4*n1;
- if (flipbytes)
- flip_endian_int32( (char *) & n1) ;
- //printf("This polygon has %i rings\n",n1);
- offset = offset1+9; //where linear rings are
- first_one = TRUE;
- for (u=0; u<n1; u++) //for each ring
- {
- if (first_one)
- {
- first_one= FALSE;
- }
- else
- {
- printf(",");
- }
- printf("(");
- memcpy(&n2, &wkb[offset],4);
- if (flipbytes)
- flip_endian_int32( (char *) & n2) ; //pts in linear ring
- // printf(" ring %i: has %i points\n",u,n2);
- total_points += n2;
- first_one2 = TRUE;
- for (v=0; v< n2; v++) //for each point
- {
- if (first_one2)
- {
- first_one2= FALSE;
- }
- else
- {
- printf(",");
- }
- if (is3d)
- {
- memcpy(&x, &wkb[offset + 4+ v*24],8);
- memcpy(&y, &wkb[offset + 4+ v*24 + 8],8);
- memcpy(&z, &wkb[offset + 4+ v*24 + 16],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- flip_endian_double( (char *) & z) ;
- }
- printf("%g %g %g",x,y,z);
- }
- else
- {
- memcpy(&x, &wkb[offset +4 +v*16],8);
- memcpy(&y, &wkb[offset +4 +v*16 + 8],8);
- if (flipbytes)
- {
- flip_endian_double( (char *) & x) ;
- flip_endian_double( (char *) & y) ;
- }
- printf("%g %g",x,y);
- }
- }
- if (is3d)
- {
- *size += 24*n2;
- offset += 4+ 24*n2;
- }
- else
- {
- *size += 16*n2;
- offset += 4+ 16*n2;
- }
- printf(")");
- }
- printf(")");
- if (is3d)
- offset1 +=9 +24*total_points +4*n1;
- else
- offset1 += 9+ 16*total_points +4*n1;
- }
- printf(")\n");
- return;
+ elog(NOTICE,"there is NOT a lock on this row!");
+ SPI_finish();
+ return PointerGetDatum(rettuple);
}
- if (type == 7)
- {
- decode_wkb_collection(wkb, size);
- }
-}
+}
-char *print_geometry(GEOMETRY *geom)
-{
- char *text;
- text = (char *) DatumGetPointer(DirectFunctionCall1(geometry_out,PointerGetDatum(geom) ) ) ;
+extern Datum getTransactionID(PG_FUNCTION_ARGS);
- printf( "%s", text);
- return text;
-}
+PG_FUNCTION_INFO_V1(getTransactionID);
-void print_point_debug(POINT3D *p)
+Datum getTransactionID(PG_FUNCTION_ARGS)
{
- printf("[%g %g %g]\n",p->x,p->y,p->z);
+ TransactionId xid = GetCurrentTransactionId();
+ PG_RETURN_DATUM( TransactionIdGetDatum(xid) );
}
+
*
* This is free software; you can redistribute and/or modify it under
* the terms of hte GNU General Public Licence. See the COPYING file.
- *
+ *
**********************************************************************
* $Log$
+ * Revision 1.24 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.23 2003/07/25 17:08:37 pramsey
* Moved Cygwin endian define out of source files into postgis.h common
* header file.
#include "postgis.h"
#include "utils/elog.h"
+#define NfunctionFirstPoint 1
+
+// if you use #define NfunctionFirstPoint 0, you get 0-based indexing (this is what programmers want)::
+// pointN(<linestring>, 0) is the 1st point, and pointN(<linestring>, 1) is the second point.
+
+// if you use #define NfunctionFirstPoint 1, you get 1-based indexing (which seems to be what the spec wants)::
+// pointN(<linestring>, 1) is the 1st point, and pointN(<linestring>, 2) is the second point.
+
#define SHOW_DIGS_DOUBLE 15
#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
for (i=1; i<line->npoints;i++)
{
to = &line->points[i];
-
+
dist += sqrt( ( (frm->x - to->x)*(frm->x - to->x) ) +
( (frm->y - to->y)*(frm->y - to->y) ) );
for (i=1; i<line->npoints;i++)
{
to = &line->points[i];
-
+
dist += sqrt( ( (frm->x - to->x)*(frm->x - to->x) ) +
- ((frm->y - to->y)*(frm->y - to->y) ) +
+ ((frm->y - to->y)*(frm->y - to->y) ) +
((frm->z - to->z)*(frm->z - to->z) ) );
frm = to;
// length3d(line) = length of line
// length3d(polygon) = 0 -- could make sense to return sum(ring perimeter)
// uses euclidian 3d length
-
+
PG_FUNCTION_INFO_V1(length3d);
Datum length3d(PG_FUNCTION_ARGS)
{
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == LINETYPE) //LINESTRING
{
// length3d(line) = length of line
// length3d(polygon) = 0 -- could make sense to return sum(ring perimeter)
// uses euclidian 2d length
-
+
PG_FUNCTION_INFO_V1(length2d);
Datum length2d(PG_FUNCTION_ARGS)
{
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == LINETYPE) //LINESTRING
{
pts1 = (POINT3D *) MAXALIGN(pts1);
//elog(NOTICE,"in polygon_area2d_old");
-
+
pt_offset = 0; //index to first point in ring
for (ring = 0; ring < poly1->nrings; ring++)
{
ringarea = 0.0;
-
- for (i=0;i<(poly1->npoints[ring]-1);i++)
- {
+
+ for (i=0;i<(poly1->npoints[ring]-1);i++)
+ {
// j = (i+1) % (poly1->npoints[ring]);
j = i+1;
- ringarea += pts1[pt_offset+ i].x * pts1[pt_offset+j].y - pts1[pt_offset+ i].y * pts1[pt_offset+j].x;
- }
+ ringarea += pts1[pt_offset+ i].x * pts1[pt_offset+j].y - pts1[pt_offset+ i].y * pts1[pt_offset+j].x;
+ }
- ringarea /= 2.0;
+ ringarea /= 2.0;
//elog(NOTICE," ring 1 has area %lf",ringarea);
ringarea = fabs(ringarea );
if (ring != 0) //outer
ringarea = -1.0*ringarea ; // its a hole
-
+
poly_area += ringarea;
- pt_offset += poly1->npoints[ring];
+ pt_offset += poly1->npoints[ring];
}
return poly_area;
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POLYGONTYPE) //POLYGON
{
pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] ) );
pts1 = (POINT3D *) MAXALIGN(pts1);
-
-
+
+
pt_offset = 0; //index to first point in ring
for (ring = 0; ring < poly1->nrings; ring++)
{
ring_perimeter = 0.0;
-
+
frm = &pts1[pt_offset];
for (i=1; i<poly1->npoints[ring];i++)
{
to = &pts1[pt_offset+ i];
-
+
ring_perimeter += sqrt( ( (frm->x - to->x)*(frm->x - to->x) ) +
- ((frm->y - to->y)*(frm->y - to->y) ) +
+ ((frm->y - to->y)*(frm->y - to->y) ) +
((frm->z - to->z)*(frm->z - to->z) ) );
frm = to;
}
-
+
poly_perimeter += ring_perimeter;
- pt_offset += poly1->npoints[ring];
+ pt_offset += poly1->npoints[ring];
}
return poly_perimeter;
pts1 = (POINT3D *) ( (char *)&(poly1->npoints[poly1->nrings] ) );
pts1 = (POINT3D *) MAXALIGN(pts1);
-
+
pt_offset = 0; //index to first point in ring
for (ring = 0; ring < poly1->nrings; ring++)
{
ring_perimeter = 0.0;
-
+
frm = &pts1[pt_offset];
for (i=1; i<poly1->npoints[ring];i++)
{
to = &pts1[pt_offset+ i];
-
+
ring_perimeter += sqrt( ( (frm->x - to->x)*(frm->x - to->x) ) +
((frm->y - to->y)*(frm->y - to->y) ) );
frm = to;
}
-
+
poly_perimeter += ring_perimeter;
- pt_offset += poly1->npoints[ring];
+ pt_offset += poly1->npoints[ring];
}
return poly_perimeter;
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POLYGONTYPE) //POLYGON
{
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POLYGONTYPE) //POLYGON
{
// V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
// returns: 0 = outside, 1 = inside
//
-// Our polygons have first and last point the same,
+// Our polygons have first and last point the same,
//
int PIP( POINT3D *P, POINT3D *V, int n )
// loop through all edges of the polygon
- for (i=0; i< (n-1) ; i++)
+ for (i=0; i< (n-1) ; i++)
{ // edge from V[i] to V[i+1]
if (((V[i].y <= P->y) && (V[i+1].y > P->y)) // an upward crossing
|| ((V[i].y > P->y) && (V[i+1].y <= P->y))) // a downward crossing
- {
+ {
vt = (double)(P->y - V[i].y) / (V[i+1].y - V[i].y);
if (P->x < V[i].x + vt * (V[i+1].x - V[i].x)) // P.x <intersect
++cn; // a valid crossing of y=P.y right of P.x
- }
+ }
}
return (cn&1); // 0 if even (out), and 1 if odd (in)
//this one is easy - is the point inside a box?
bool point_truely_inside(POINT3D *point, BOX3D *box)
{
- return (
- (point->x >= box->LLB.x) && (point->x <= box->URT.x) &&
- (point->y >= box->LLB.y) && (point->y <= box->URT.y)
+ return (
+ (point->x >= box->LLB.x) && (point->x <= box->URT.x) &&
+ (point->y >= box->LLB.y) && (point->y <= box->URT.y)
);
}
// see if a linestring is inside a box - check to see if each its line
-// segments are inside the box
+// segments are inside the box
// NOTE: all this is happening in 2d - third dimention is ignored
//
//use a modified CohenSutherland line clipping algoritm
return (Code+1);
}
- return (Code);
+ return (Code);
}
outcode_p1 = compute_outcode(P1, box);
if (outcode_p1 ==0)
return TRUE;
-
+
outcode_p2 = compute_outcode(P2, box);
if (outcode_p2 ==0)
return TRUE;
// from comp.graphics.algo's faq:
/*
- (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
+ (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
r = ------------------------------------
- (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+ (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
- (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+ (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
s = -----------------------------------
- (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+ (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
*/
// if 0<= r&s <=1 then intersection exists
-
+
Ax = P1->x; Ay = P1->y;
Bx = P2->x; By = P2->y;
//otherwise we did not intersect the box
return FALSE;
-
+
}
for (i=1; i< npoints;i++)
{
to = &pts[i];
-
- if (lineseg_inside_box( frm, to, box))
+
+ if (lineseg_inside_box( frm, to, box))
return TRUE;
frm = to;
POINT3D test_point;
int32 ring;
int point_offset;
-
+
pts1 = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] ) );
pts1 = (POINT3D *) MAXALIGN(pts1);
//step 1 (and 2)
- outer_ring_inside = linestring_inside_box(pts1, poly->npoints[0], box);
+ outer_ring_inside = linestring_inside_box(pts1, poly->npoints[0], box);
if (outer_ring_inside)
return TRUE;
test_point.x = box->LLB.x;
test_point.y = box->LLB.y;
//.z unimportant
-
- outer_ring_surrounds = PIP(&test_point, pts1,poly->npoints[0] );
+
+ outer_ring_surrounds = PIP(&test_point, pts1,poly->npoints[0] );
if (!(outer_ring_surrounds))
return FALSE; // disjoing
}
point_offset += poly->npoints[ring];
}
-
+
return TRUE;
}
offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POINTTYPE) //point
offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POINTTYPE) //point
offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type1= geom1->objType[j];
if (type1 == POLYGONTYPE) //POLYGON
{
poly = (POLYGON3D *) o1;
- numb_rings += poly->nrings;
+ numb_rings += poly->nrings;
}
}
offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom1->nobjs; j++) //for each object in geom1
{
- o1 = (char *) geom1 +offsets1[j] ;
+ o1 = (char *) geom1 +offsets1[j] ;
type= geom1->objType[j];
if (type == POINTTYPE) //point
result = (GEOMETRY *) palloc(geom->size);
memcpy(result,geom, geom->size);
-
+
result->is3d = FALSE;
PG_RETURN_POINTER(result);
}
{
geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- box = (BOX3D *) palloc(sizeof(BOX3D));
+ box = (BOX3D *) palloc(sizeof(BOX3D));
memcpy(box, &(geom->bvol), sizeof(BOX3D) );
PG_RETURN_POINTER(box); // combine_bbox(null, geometry) => geometry->bvol
if (geom_ptr == NULL)
{
- box = (BOX3D *) palloc(sizeof(BOX3D));
+ box = (BOX3D *) palloc(sizeof(BOX3D));
memcpy(box, (char *) PG_GETARG_DATUM(0) , sizeof(BOX3D) );
-
+
PG_RETURN_POINTER( box ); // combine_bbox(BOX3D, null) => BOX3D
}
Datum dimension(PG_FUNCTION_ARGS)
{
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ int t;
+ int result,dim,type;
- if (geom->is3d)
- PG_RETURN_INT32(3);
- else
+
+ if ((geom->type == COLLECTIONTYPE) && (geom->nobjs ==0))
+ PG_RETURN_INT32(-1);
+
+ if (geom->type == POINTTYPE)
+ PG_RETURN_INT32(0);
+
+ if (geom->type == LINETYPE)
+ PG_RETURN_INT32(1);
+
+ if (geom->type == POLYGONTYPE)
+ PG_RETURN_INT32(2);
+
+
+ if (geom->type == MULTIPOINTTYPE)
+ PG_RETURN_INT32(0);
+
+ if (geom->type == MULTILINETYPE)
+ PG_RETURN_INT32(1);
+
+ if (geom->type == MULTIPOLYGONTYPE)
PG_RETURN_INT32(2);
+
+ result = -1;
+ dim =0;
+ //its a collection -look for the largest one
+ for (t=0;t<geom->nobjs;t++)
+ {
+ type= geom->objType[t];
+
+ if (type == POINTTYPE)
+ dim=0;
+
+ if (type == LINETYPE)
+ dim=1;
+
+ if (type == POLYGONTYPE)
+ dim=2;
+
+ if (dim>result)
+ result = dim;
+
+ }
+ PG_RETURN_INT32(result);
}
//returns a string representation of this geometry's type
char *text_ob = palloc(20+4);
char *result = text_ob+4;
int32 size;
-
+
memset(result,0,20);
size = strlen(result) +4 ;
memcpy(text_ob, &size,4); // size of string
-
+
PG_RETURN_POINTER(text_ob);
POINT3D pts[5]; //5 points around box
int pts_per_ring[1];
int poly_size;
-
+
//use LLB's z value (we're going to set is3d to false)
set_point( &pts[0], geom->bvol.LLB.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
set_point( &pts[2], geom->bvol.URT.x , geom->bvol.URT.y , geom->bvol.LLB.z );
set_point( &pts[3], geom->bvol.LLB.x , geom->bvol.URT.y , geom->bvol.LLB.z );
set_point( &pts[4], geom->bvol.LLB.x , geom->bvol.LLB.y , geom->bvol.LLB.z );
-
+
pts_per_ring[0] = 5; //ring has 5 points
//make a polygon
result = make_oneobj_geometry(poly_size, (char *)poly, POLYGONTYPE, FALSE,geom->SRID, geom->scale, geom->offsetX, geom->offsetY);
- PG_RETURN_POINTER(result);
+ PG_RETURN_POINTER(result);
}
-//X(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its X value.
+//X(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its X value.
//Return NULL if there is no POINT(..) in GEOMETRY
PG_FUNCTION_INFO_V1(x_point);
Datum x_point(PG_FUNCTION_ARGS)
char *o;
int type1,j;
int32 *offsets1;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POINTTYPE) //point
}
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
-//Y(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Y value.
+//Y(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Y value.
//Return NULL if there is no POINT(..) in GEOMETRY
PG_FUNCTION_INFO_V1(y_point);
Datum y_point(PG_FUNCTION_ARGS)
char *o;
int type1,j;
int32 *offsets1;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POINTTYPE) //point
}
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
-//Z(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Z value.
+//Z(GEOMETRY) -- find the first POINT(..) in GEOMETRY, returns its Z value.
//Return NULL if there is no POINT(..) in GEOMETRY
PG_FUNCTION_INFO_V1(z_point);
Datum z_point(PG_FUNCTION_ARGS)
char *o;
int type1,j;
int32 *offsets1;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POINTTYPE) //point
}
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
//numpoints(GEOMETRY) -- find the first linestring in GEOMETRY, return
char *o;
int type1,j;
int32 *offsets1;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == LINETYPE) //linestring
}
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
//pointn(GEOMETRY,INTEGER) -- find the first linestring in GEOMETRY,
Datum pointn_linestring(PG_FUNCTION_ARGS)
{
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- int32 wanted_index =PG_GETARG_INT32(1);
+ int32 wanted_index =PG_GETARG_INT32(1);
char *o;
int type1,j;
int32 *offsets1;
LINE3D *line;
-
+
+ wanted_index -= NfunctionFirstPoint;
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == LINETYPE) //linestring
PG_RETURN_NULL(); //index out of range
//get the point, make a new geometry
PG_RETURN_POINTER(
- make_oneobj_geometry(sizeof(POINT3D),
+ make_oneobj_geometry(sizeof(POINT3D),
(char *)&line->points[wanted_index],
- POINTTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ POINTTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
);
}
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
// exteriorRing(GEOMETRY) -- find the first polygon in GEOMETRY, return
//its exterior ring (as a linestring). Return NULL if there is no
-//POLYGON(..) in GEOMETRY.
+//POLYGON(..) in GEOMETRY.
PG_FUNCTION_INFO_V1(exteriorring_polygon);
Datum exteriorring_polygon(PG_FUNCTION_ARGS)
POINT3D *pts;
int size_line;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POLYGONTYPE) //polygon object
PG_RETURN_POINTER(
make_oneobj_geometry(size_line,
(char *) line,
- LINETYPE, geom->is3d,geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ LINETYPE, geom->is3d,geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
);
}
POLYGON3D *poly;
-
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POLYGONTYPE) //polygon object
Datum interiorringn_polygon(PG_FUNCTION_ARGS)
{
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- int32 wanted_index =PG_GETARG_INT32(1);
+ int32 wanted_index =PG_GETARG_INT32(1);
char *o;
int type1,j,t,point_offset;
int32 *offsets1;
POINT3D *pts;
int size_line;
-
+
+ wanted_index -= NfunctionFirstPoint;
+
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
for (j=0; j< geom->nobjs; j++) //for each object in geom1
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POLYGONTYPE) //polygon object
if ( (wanted_index<0) || (wanted_index> (poly->nrings-2) ) )
PG_RETURN_NULL(); //index out of range
-
+
pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
point_offset=0;
for (t=0; t< (wanted_index+1); t++)
{
- point_offset += poly->npoints[t];
+ point_offset += poly->npoints[t];
}
line = make_line(poly->npoints[wanted_index+1], &pts[point_offset], &size_line);
PG_RETURN_POINTER(
make_oneobj_geometry(size_line,
(char *) line,
- LINETYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
- );
+ LINETYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ );
}
}
PG_RETURN_NULL();
{
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- if ( (geom->type == COLLECTIONTYPE) ||
- (geom->type == MULTIPOINTTYPE) ||
- (geom->type == MULTILINETYPE) ||
+ if ( (geom->type == COLLECTIONTYPE) ||
+ (geom->type == MULTIPOINTTYPE) ||
+ (geom->type == MULTILINETYPE) ||
(geom->type == MULTIPOLYGONTYPE)
)
PG_RETURN_INT32( geom->nobjs ) ;
else
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
Datum geometryn_collection(PG_FUNCTION_ARGS)
{
GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- int32 wanted_index =PG_GETARG_INT32(1);
+ int32 wanted_index =PG_GETARG_INT32(1);
int type;
int32 *offsets1;
char *o;
-
+ wanted_index -= NfunctionFirstPoint;
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
- if (!(( (geom->type == COLLECTIONTYPE) ||
- (geom->type == MULTIPOINTTYPE) ||
- (geom->type == MULTILINETYPE) ||
+ if (!(( (geom->type == COLLECTIONTYPE) ||
+ (geom->type == MULTIPOINTTYPE) ||
+ (geom->type == MULTILINETYPE) ||
(geom->type == MULTIPOLYGONTYPE)
)))
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
if ( (wanted_index <0) || (wanted_index > (geom->nobjs-1) ) )
PG_RETURN_NULL(); //bad index
type = geom->objType[wanted_index];
- o = (char *) geom +offsets1[wanted_index] ;
-
+ o = (char *) geom +offsets1[wanted_index] ;
+
if (type == POINTTYPE)
{
PG_RETURN_POINTER(
make_oneobj_geometry(sizeof(POINT3D),
o,
- POINTTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ POINTTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
);
}
if (type == LINETYPE)
PG_RETURN_POINTER(
make_oneobj_geometry( size_subobject (o, LINETYPE),
o,
- LINETYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ LINETYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
);
}
if (type == POLYGONTYPE)
PG_RETURN_POINTER(
make_oneobj_geometry( size_subobject (o, POLYGONTYPE),
o,
- POLYGONTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
+ POLYGONTYPE, geom->is3d, geom->SRID, geom->scale, geom->offsetX, geom->offsetY)
);
}
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
result = (GEOMETRY *) palloc(geom->size);
memcpy(result,geom, geom->size);
-
+
result->type = COLLECTIONTYPE;
PG_RETURN_POINTER(result);
offsets1 = (int32 *) ( ((char *) &(geom->objType[0] ))+ sizeof(int32) * geom->nobjs ) ;
- //now have to do a scan of each object
+ //now have to do a scan of each object
for (j=0; j< geom->nobjs; j++) //for each object in geom
{
- o = (char *) geom +offsets1[j] ;
+ o = (char *) geom +offsets1[j] ;
type1= geom->objType[j];
if (type1 == POINTTYPE) //point
}
}
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
//otherwise, we use comp.graphics.algorithms Frequently Asked Questions method
- /*(1) AC dot AB
+ /*(1) AC dot AB
r = ---------
- ||AB||^2
+ ||AB||^2
r has the following meaning:
- r=0 P = A
- r=1 P = B
- r<0 P is on the backward extension of AB
- r>1 P is on the forward extension of AB
- 0<r<1 P is interior to AB
+ r=0 P = A
+ r=1 P = B
+ r<0 P is on the backward extension of AB
+ r>1 P is on the forward extension of AB
+ 0<r<1 P is interior to AB
*/
r = ( (p->x-A->x) * (B->x-A->x) + (p->y-A->y) * (B->y-A->y) )/( (B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
return (distance_pt_pt(p,A));
if (r>1)
return(distance_pt_pt(p,B));
-
+
/*(2)
- (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
- s = -----------------------------
- L^2
-
- Then the distance from C to P = |s|*L.
+ (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+ s = -----------------------------
+ L^2
+
+ Then the distance from C to P = |s|*L.
*/
s = ((A->y-p->y)*(B->x-A->x)- (A->x-p->x)*(B->y-A->y) )/ ((B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) );
-
+
return abs(s) * sqrt(((B->x-A->x)*(B->x-A->x) +(B->y-A->y)*(B->y-A->y) ));
}
// AB and CD are line segments
/* from comp.graphics.algo
- Solving the above for r and s yields
- (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
- r = ----------------------------- (eqn 1)
+ Solving the above for r and s yields
+ (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy)
+ r = ----------------------------- (eqn 1)
(Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
- (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
- s = ----------------------------- (eqn 2)
- (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
- Let P be the position vector of the intersection point, then
- P=A+r(B-A) or
- Px=Ax+r(Bx-Ax)
- Py=Ay+r(By-Ay)
- By examining the values of r & s, you can also determine some other limiting conditions:
- If 0<=r<=1 & 0<=s<=1, intersection exists
- r<0 or r>1 or s<0 or s>1 line segments do not intersect
- If the denominator in eqn 1 is zero, AB & CD are parallel
- If the numerator in eqn 1 is also zero, AB & CD are collinear.
+ (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
+ s = ----------------------------- (eqn 2)
+ (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx)
+ Let P be the position vector of the intersection point, then
+ P=A+r(B-A) or
+ Px=Ax+r(Bx-Ax)
+ Py=Ay+r(By-Ay)
+ By examining the values of r & s, you can also determine some other limiting conditions:
+ If 0<=r<=1 & 0<=s<=1, intersection exists
+ r<0 or r>1 or s<0 or s>1 line segments do not intersect
+ If the denominator in eqn 1 is zero, AB & CD are parallel
+ If the numerator in eqn 1 is also zero, AB & CD are collinear.
*/
r_top = (A->y-C->y)*(D->x-C->x) - (A->x-C->x)*(D->y-C->y) ;
if ( (r_bot==0) || (s_bot == 0) )
{
- return (
- min(distance_pt_seg(A,C,D),
- min(distance_pt_seg(B,C,D),
+ return (
+ min(distance_pt_seg(A,C,D),
+ min(distance_pt_seg(B,C,D),
min(distance_pt_seg(C,A,B),
distance_pt_seg(D,A,B) ) ) )
);
if ((r<0) || (r>1) || (s<0) || (s>1) )
{
//no intersection
- return (
- min(distance_pt_seg(A,C,D),
- min(distance_pt_seg(B,C,D),
+ return (
+ min(distance_pt_seg(A,C,D),
+ min(distance_pt_seg(B,C,D),
min(distance_pt_seg(C,A,B),
distance_pt_seg(D,A,B) ) ) )
);
-
+
}
- else
+ else
return -0; //intersection exists
-
+
}
-//trivial
+//trivial
double distance_pt_pt(POINT3D *p1, POINT3D *p2)
{
//print_point_debug(p1);
end = &(l1->points[t]);
start2 = &(l2->points[0]);
-
+
for (u=1; u< l2->npoints; u++) //for each segment in L2
{
end2 = &(l2->points[u]);
-
+
dist_this = distance_seg_seg(start,end,start2,end2);
//printf("line_line; seg %i * seg %i, dist = %g\n",t,u,dist_this);
line = make_line (poly2->npoints[t] , &pts[offset] , &junk);
result = distance_pt_line(p1, line);
pfree(line);
- return result;
+ return result;
}
offset += poly2->npoints[t];
- }
+ }
return 0; //its inside the polygon
}
return result;
}
-
+
}
// brute force. Test l1 against each ring. If there's an intersection then return 0 (crosses boundary)
-// otherwise, test to see if a point inside outer rings of polygon, but not in inner rings.
+// otherwise, test to see if a point inside outer rings of polygon, but not in inner rings.
// if so, return 0 (line inside polygon)
// otherwise return min distance to a ring (could be outside polygon or inside a hole)
double distance_line_poly(LINE3D *l1, POLYGON3D *poly2)
if ( PIP( &l1->points[0], &pts[offset], poly2->npoints[t] ) )
{
//its inside a hole, then the actual distance is the min ring distance
-//printf("line_poly; inside inner ring %i\n",t);
+//printf("line_poly; inside inner ring %i\n",t);
return min_dist;
}
offset += poly2->npoints[t];
- }
+ }
// not in hole, there for inside the polygon
return 0;
}
//not in the outside ring, so min distance to a ring is the actual min distance
return min_dist;
}
-
+
}
// true if point is in poly (and not in its holes)
int t;
POINT3D *pts1;
int offset;
-
+
pts1 = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] ) );
pts1 = (POINT3D *) MAXALIGN(pts1);
return FALSE; //not in outer ring
}
-// brute force.
+// brute force.
// test to see if any rings intersect. if yes, dist =0
// test to see if one inside the other and if they are inside holes.
// find min distance ring-to-ring
int g1_i, g2_i;
double dist,this_dist = 0;
bool dist_set = FALSE; //true once dist makes sense.
- int32 *offsets1,*offsets2;
+ int32 *offsets1,*offsets2;
int type1,type2;
char *o1,*o2;
for (g1_i=0; g1_i < geom1->nobjs; g1_i++)
{
- o1 = (char *) geom1 +offsets1[g1_i] ;
+ o1 = (char *) geom1 +offsets1[g1_i] ;
type1= geom1->objType[g1_i];
for (g2_i=0; g2_i < geom2->nobjs; g2_i++)
{
- o2 = (char *) geom2 +offsets2[g2_i] ;
+ o2 = (char *) geom2 +offsets2[g2_i] ;
type2= geom2->objType[g2_i];
if ( (type1 == POINTTYPE) && (type2 == POINTTYPE) )
if ( (type1 == LINETYPE) && (type2 == POINTTYPE) )
{
this_dist = distance_pt_line( (POINT3D *)o2, (LINE3D *)o1 );
- }
+ }
if ( (type1 == POLYGONTYPE) && (type2 == POINTTYPE) )
{
this_dist = distance_pt_poly( (POINT3D *)o2, (POLYGON3D *)o1 );
dist_set = TRUE;
}
- if (dist <= 0.0)
+ if (dist <= 0.0)
PG_RETURN_FLOAT8( (double) 0.0); // no need to look for things closer
}
}
result->URT.x = bbox->URT.x + d;
result->URT.y = bbox->URT.y + d;
result->URT.z = bbox->URT.z + d;
-
+
PG_RETURN_POINTER(result);
}
line = (LINE3D *) ( (char *) geom1 +offsets1[0]);
- pt = &line->points[0];
-
+ pt = &line->points[0];
+
PG_RETURN_POINTER(
make_oneobj_geometry(sizeof(POINT3D),
(char *) pt,
- POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
+ POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
);
}
line = (LINE3D *) ( (char *) geom1 +offsets1[0]);
- pt = &line->points[line->npoints-1];
-
+ pt = &line->points[line->npoints-1];
+
PG_RETURN_POINTER(
make_oneobj_geometry(sizeof(POINT3D),
(char *) pt,
- POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
+ POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
);
}
-//isclosed(geometry) :- if geometry is a linestring then returns
+//isclosed(geometry) :- if geometry is a linestring then returns
//startpoint == endpoint. If its not a linestring then return NULL. If
//its a multilinestring, return true only if all the sub-linestrings have
//startpoint=endpoint.
for (t=0; t< geom1->nobjs; t++)
{
line = (LINE3D *) ( (char *) geom1 +offsets1[t]);
- pt1 = &line->points[0];
- pt2 = &line->points[line->npoints-1];
-
+ pt1 = &line->points[0];
+ pt2 = &line->points[line->npoints-1];
+
if ( (pt1->x != pt2->x) || (pt1->y != pt2->y) || (pt1->z != pt2->z) )
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_RETURN_BOOL(TRUE);
}
int num_points,num_points_tot;
double tot_x,tot_y,tot_z;
GEOMETRY *result;
-
+
offsets1 = (int32 *) ( ((char *) &(geom1->objType[0] ))+ sizeof(int32) * geom1->nobjs ) ;
if (!((geom1->type == POLYGONTYPE) || (geom1->type == MULTIPOLYGONTYPE) ))
PG_RETURN_NULL();
- //find the centroid
+ //find the centroid
num_points_tot = 0;
tot_x = 0; tot_y =0; tot_z=0;
-
+
for (t=0;t<geom1->nobjs;t++)
{
- poly = (POLYGON3D *) ( (char *) geom1 +offsets1[t]);
+ poly = (POLYGON3D *) ( (char *) geom1 +offsets1[t]);
pts = (POINT3D *) ( (char *)&(poly->npoints[poly->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
num_points =poly->npoints[0];
num_points_tot += num_points-1; //last point = 1st point
for (v=0;v<num_points-1;v++)
{
- tot_x += pts[v].x;
+ tot_x += pts[v].x;
tot_y += pts[v].y;
- tot_z += pts[v].z;
+ tot_z += pts[v].z;
}
}
cent = palloc(sizeof(POINT3D));
result = (
make_oneobj_geometry(sizeof(POINT3D),
(char *) cent,
- POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
+ POINTTYPE, geom1->is3d, geom1->SRID, geom1->scale, geom1->offsetX, geom1->offsetY)
);
pfree(cent);
PG_RETURN_POINTER(result);
// max_distance(geom,geom) (both geoms must be linestrings)
//find max distance between l1 and l2
-// method: for each point in l1, find distance to l2.
+// method: for each point in l1, find distance to l2.
// return max distance
//
-// note: max_distance(l1,l2) != max_distance(l2,l1)
+// note: max_distance(l1,l2) != max_distance(l2,l1)
// returns double
PG_FUNCTION_INFO_V1(max_distance);
LINE3D *l1,*l2;
int32 *offsets1,*offsets2;
-
+
int t;
- POINT3D *pt;
+ POINT3D *pt;
double result,dist;
//bbox check
memcpy(&g1_bvol, &geom1->bvol, sizeof(BOX3D) );
-
+
g1_bvol.LLB.x = g1_bvol.LLB.x - dist;
g1_bvol.LLB.y = g1_bvol.LLB.y - dist;
-
+
g1_bvol.URT.x = g1_bvol.URT.x + dist;
g1_bvol.URT.y = g1_bvol.URT.y + dist;
-
+
//xmin = LLB.x, xmax = URT.x
-
+
if ( (g1_bvol.LLB.x > geom2->bvol.URT.x) ||
(g1_bvol.URT.x < geom2->bvol.LLB.x) ||
//returns a list of points for a single polygon
// foreach segment
// (1st and last points will be unaltered, but
-// there will be more points inbetween if segment length is
+// there will be more points inbetween if segment length is
POINT3D *segmentize_ring(POINT3D *points, double dist, int num_points_in, int *num_points_out)
{
double seg_distance;
POINT3D *result,*r;
bool keep_going;
POINT3D *last_point, *next_point;
-
+
//initial storage
- max_points = 1000;
+ max_points = 1000;
offset_new=0; //start at beginning of points list
result = (POINT3D *) palloc (sizeof(POINT3D) * max_points);
keep_going = 1;
while(keep_going)
{
- next_point = &points[offset_old];
+ next_point = &points[offset_old];
//distance last->next > dist
seg_distance = sqrt(
- (next_point->x-last_point->x)*(next_point->x-last_point->x) +
- (next_point->y-last_point->y)*(next_point->y-last_point->y) );
+ (next_point->x-last_point->x)*(next_point->x-last_point->x) +
+ (next_point->y-last_point->y)*(next_point->y-last_point->y) );
if (offset_new >= max_points)
{
//need to add new points to result
max_points *=2;
pfree(r);
}
-
+
if (seg_distance > dist)
{
//add a point at the distance location
// and set last_point to this loc
-
+
result[offset_new].x = last_point->x + (next_point->x-last_point->x)/seg_distance * dist;
result[offset_new].y = last_point->y + (next_point->y-last_point->y)/seg_distance * dist;
last_point = &result[offset_new];
for (r=0;r<p->nrings;r++) //foreach ring in the polygon
{
polypts = segmentize_ring(p_points, maxdist, p->npoints[r], &num_polypts);
- if ( (all_num_polypts + num_polypts) < all_num_polypts_max )
+ if ( (all_num_polypts + num_polypts) < all_num_polypts_max )
{
//just add
memcpy( &all_polypts[all_num_polypts], polypts, sizeof(POINT3D) *num_polypts );
all_num_polypts += num_polypts;
}
- else
+ else
{
//need more space
new_size = all_num_polypts_max + num_polypts + 1000;
rr = (POINT3D*) palloc(sizeof(POINT3D) * new_size);
- memcpy(rr,all_polypts, sizeof(POINT3D) *all_num_polypts);
+ memcpy(rr,all_polypts, sizeof(POINT3D) *all_num_polypts);
memcpy(&rr[all_num_polypts], polypts , sizeof(POINT3D) *num_polypts);
pfree(all_polypts);
all_polypts = rr;
pfree(polypts);
p_npoints_ring[r] = num_polypts;
} //for each ring
-
+
poly = make_polygon(p->nrings, p_npoints_ring, all_polypts, all_num_polypts, &poly_size);
if (first_one)
result = result2;
pfree(poly);
pfree(all_polypts);
- }
+ }
} // foreach polygon
PG_RETURN_POINTER(result);
// all the sub_objects from both of the argument geometries
// returned geometry is the simplest possible, based on the types
-// of the colelct objects
+// of the colelct objects
// ie. if all are of either X or multiX, then a multiX is returned
// bboxonly types are treated as null geometries (no sub_objects)
PG_FUNCTION_INFO_V1( collector );
geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
if ( geom1->SRID != geom2->SRID )
{
elog(ERROR,"Operation on two GEOMETRIES with different SRIDs\n");
PG_RETURN_NULL();
}
+
+ if (geom1->nobjs ==0)
+ {
+ geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ result = (GEOMETRY *)palloc( geom2->size );
+ memcpy( result, geom2, geom2->size );
+ PG_RETURN_POINTER(result);
+ }
+ if (geom2->nobjs ==0)
+ {
+ geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ result = (GEOMETRY *)palloc( geom1->size );
+ memcpy( result, geom1, geom1->size );
+ PG_RETURN_POINTER(result);
+ }
+
result = (GEOMETRY *)palloc( geom1->size );
memcpy( result, geom1, geom1->size );
-
+
offsets2 = (int32 *)( ((char *)&(geom2->objType[0])) + sizeof( int32 ) * geom2->nobjs ) ;
for (i=0; i<geom2->nobjs; i++)
{
size = geom2->size - offsets2[i];
}
- else
+ else
{
size = offsets2[i+1] - offsets2[i];
}
PG_RETURN_POINTER(out);
}
+
+PG_FUNCTION_INFO_V1(isempty);
+Datum isempty(PG_FUNCTION_ARGS)
+{
+ GEOMETRY *geom1= (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+
+ if (geom1->nobjs ==0)
+ PG_RETURN_INT32(1);
+ PG_RETURN_INT32(0);
+}
+
+
+// converts multi* types with 1 element to the single-element version.
+// ie. MULTIPOINT(0 0) --> POINT(0 0)
+void compressType(GEOMETRY *g)
+{
+ if (g->nobjs ==1)
+ {
+ if (g->type == MULTIPOINTTYPE)
+ {
+ g->type = POINTTYPE;
+ return;
+ }
+ if (g->type == MULTILINETYPE)
+ {
+ g->type = LINETYPE;
+ return;
+ }
+ if (g->type == MULTIPOLYGONTYPE)
+ {
+ g->type = POLYGONTYPE;
+ return;
+ }
+
+ }
+}
+
*
**********************************************************************
* $Log$
+ * Revision 1.8 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.7 2003/08/06 19:31:18 dblasby
* Added the WKB parser. Added all the functions like
* PolyFromWKB(<WKB>,[<SRID>]).
extern Geometry *GEOSBoundary(Geometry *g1);
extern Geometry *GEOSSymDifference(Geometry *g1,Geometry *g2);
extern Geometry *GEOSUnion(Geometry *g1,Geometry *g2);
+extern char GEOSequals(Geometry *g1, Geometry*g2);
+extern char GEOSisSimple(Geometry *g1);
+extern char GEOSisRing(Geometry *g1);
+extern Geometry *GEOSpointonSurface(Geometry *g1);
Datum relate_full(PG_FUNCTION_ARGS);
Datum symdifference(PG_FUNCTION_ARGS);
Datum geomunion(PG_FUNCTION_ARGS);
+
+Datum issimple(PG_FUNCTION_ARGS);
+Datum isring(PG_FUNCTION_ARGS);
+Datum geomequals(PG_FUNCTION_ARGS);
+Datum pointonsurface(PG_FUNCTION_ARGS);
+
+
+
Geometry *POSTGIS2GEOS(GEOMETRY *g);
void errorIfGeometryCollection(GEOMETRY *g1, GEOMETRY *g2);
GEOMETRY *GEOS2POSTGIS(Geometry *g, char want3d );
Geometry *g1,*g2,*g3;
GEOMETRY *result;
- char empty;
initGEOS(MAXIMUM_ALIGNOF);
}
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g2);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS union() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
-
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
Geometry *g1,*g2,*g3;
GEOMETRY *result;
- char empty;
initGEOS(MAXIMUM_ALIGNOF);
PG_RETURN_NULL(); //never get here
}
-
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g2);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS symdifference() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
-
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
Geometry *g1,*g3;
GEOMETRY *result;
- char empty;
-
initGEOS(MAXIMUM_ALIGNOF);
g1 = POSTGIS2GEOS(geom1 );
PG_RETURN_NULL(); //never get here
}
-
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS bounary() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
-
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
result = GEOS2POSTGIS(g3, geom1->is3d);
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g3);
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
Datum convexhull(PG_FUNCTION_ARGS)
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- char empty;
Geometry *g1,*g3;
GEOMETRY *result;
PG_RETURN_NULL(); //never get here
}
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS convexhull() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g3);
+
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
{
GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
double size = PG_GETARG_FLOAT8(1);
- char empty;
Geometry *g1,*g3;
GEOMETRY *result;
PG_RETURN_NULL(); //never get here
}
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS buffer() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g3);
+
+ compressType(result); // convert multi* to single item if appropriate
PG_RETURN_POINTER(result);
}
Geometry *g1,*g2,*g3;
GEOMETRY *result;
- char empty;
initGEOS(MAXIMUM_ALIGNOF);
}
- empty = GEOSisEmpty(g3);
- if (empty ==2)
- {
- GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g2);
- GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS Intersection() threw an error (couldnt test empty on result)!");
- PG_RETURN_NULL(); //never get here
- }
- if (empty)
- {
- PG_RETURN_NULL();
- }
+
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
Geometry *g1,*g2,*g3;
GEOMETRY *result;
- char empty;
initGEOS(MAXIMUM_ALIGNOF);
}
- empty = GEOSisEmpty(g3);
- if (empty ==2)
+
+
+// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
+
+ result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
+ if (result == NULL)
{
GEOSdeleteGeometry(g1);
GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS difference() threw an error (couldnt test empty on result)!");
+ elog(ERROR,"GEOS difference() threw an error (result postgis geometry formation)!");
PG_RETURN_NULL(); //never get here
}
- if (empty)
+
+
+
+ GEOSdeleteGeometry(g1);
+ GEOSdeleteGeometry(g2);
+ GEOSdeleteGeometry(g3);
+
+
+ compressType(result); // convert multi* to single item if appropriate
+
+ PG_RETURN_POINTER(result);
+}
+
+
+//select pointonsurface('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))');
+PG_FUNCTION_INFO_V1(pointonsurface);
+Datum pointonsurface(PG_FUNCTION_ARGS)
+{
+ GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+ Geometry *g1,*g3;
+ GEOMETRY *result;
+
+ initGEOS(MAXIMUM_ALIGNOF);
+
+ g1 = POSTGIS2GEOS(geom1 );
+ g3 = GEOSpointonSurface(g1);
+
+ if (g3 == NULL)
{
- PG_RETURN_NULL();
+ elog(ERROR,"GEOS pointonsurface() threw an error!");
+ GEOSdeleteGeometry(g1);
+ PG_RETURN_NULL(); //never get here
}
+
+
+
// elog(NOTICE,"result: %s", GEOSasText(g3) ) ;
- result = GEOS2POSTGIS(g3, geom1->is3d || geom2->is3d);
+ result = GEOS2POSTGIS(g3, geom1->is3d);
if (result == NULL)
{
GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
- elog(ERROR,"GEOS difference() threw an error (result postgis geometry formation)!");
+ elog(ERROR,"GEOS pointonsurface() threw an error (result postgis geometry formation)!");
PG_RETURN_NULL(); //never get here
}
GEOSdeleteGeometry(g1);
- GEOSdeleteGeometry(g2);
GEOSdeleteGeometry(g3);
+ compressType(result); // convert multi* to single item if appropriate
+
PG_RETURN_POINTER(result);
}
PG_RETURN_POINTER(result);
}
+//==============================
+
+PG_FUNCTION_INFO_V1(geomequals);
+Datum geomequals(PG_FUNCTION_ARGS)
+{
+ GEOMETRY *geom1 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ GEOMETRY *geom2 = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+
+ Geometry *g1,*g2;
+ bool result;
+
+ errorIfGeometryCollection(geom1,geom2);
+ initGEOS(MAXIMUM_ALIGNOF);
+
+ g1 = POSTGIS2GEOS(geom1 );
+ g2 = POSTGIS2GEOS(geom2 );
+
+
+ result = GEOSequals(g1,g2);
+ GEOSdeleteGeometry(g1);
+ GEOSdeleteGeometry(g2);
+
+ if (result == 2)
+ {
+ elog(ERROR,"GEOS equals() threw an error!");
+ PG_RETURN_NULL(); //never get here
+ }
+
+ PG_RETURN_BOOL(result);
+}
+
+PG_FUNCTION_INFO_V1(issimple);
+Datum issimple(PG_FUNCTION_ARGS)
+{
+ GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+ Geometry *g1;
+ int result;
+
+ if (geom->nobjs == 0)
+ PG_RETURN_BOOL(true);
+
+ initGEOS(MAXIMUM_ALIGNOF);
+
+ //elog(NOTICE,"GEOS init()");
+
+ g1 = POSTGIS2GEOS(geom );
+
+ result = GEOSisSimple(g1);
+ GEOSdeleteGeometry(g1);
+
+
+ if (result == 2)
+ {
+ elog(ERROR,"GEOS issimple() threw an error!");
+ PG_RETURN_NULL(); //never get here
+ }
+
+ PG_RETURN_BOOL(result);
+}
+
+PG_FUNCTION_INFO_V1(isring);
+Datum isring(PG_FUNCTION_ARGS)
+{
+ GEOMETRY *geom = (GEOMETRY *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+ Geometry *g1;
+ int result;
+
+ if (geom->type != LINETYPE)
+ {
+ elog(ERROR,"isring() should only be called on a LINE");
+ }
+
+ if (geom->nobjs == 0)
+ PG_RETURN_BOOL(false);
+
+ initGEOS(MAXIMUM_ALIGNOF);
+
+ //elog(NOTICE,"GEOS init()");
+
+ g1 = POSTGIS2GEOS(geom );
+
+ result = GEOSisRing(g1);
+ GEOSdeleteGeometry(g1);
+
+
+ if (result == 2)
+ {
+ elog(ERROR,"GEOS isring() threw an error!");
+ PG_RETURN_NULL(); //never get here
+ }
+
+ PG_RETURN_BOOL(result);
+}
+
+
+
+//===================================================
POLYGON3D *PolyFromGeometry(Geometry *g, int *size)
{
ngeoms = GEOSGetNumGeometries(g);
if (ngeoms ==0)
{
- return NULL;
+ result = makeNullGeometry(GEOSGetSRID(g));
+ result->type = MULTIPOINTTYPE;
+ return result;
}
pts = GEOSGetCoordinates(g);
ngeoms = GEOSGetNumGeometries(g);
if (ngeoms ==0)
{
- return NULL;
+ result = makeNullGeometry(GEOSGetSRID(g));
+ result->type = MULTILINETYPE;
+ return result;
}
for (t=0;t<ngeoms;t++)
{
ngeoms = GEOSGetNumGeometries(g);
if (ngeoms ==0)
{
- return NULL;
+ result = makeNullGeometry(GEOSGetSRID(g));
+ result->type = MULTIPOLYGONTYPE;
+ return result;
}
for (t=0;t<ngeoms;t++)
{
if (ngeoms ==0)
{
- return NULL;
+ result = makeNullGeometry(GEOSGetSRID(g));
+ return result;
}
if (ngeoms == 1)
{
break;
case MULTIPOLYGONTYPE:
//make an array of POLYGON3Ds
- polys = (POLYGON3D**) palloc(sizeof (POLYGON3D*) * g->nobjs);
+ polys = NULL;
+ if (g->nobjs >0)
+ polys = (POLYGON3D**) palloc(sizeof (POLYGON3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
polys[t] = (POLYGON3D*) ((char *) g +offsets1[t]) ;
}
geos= PostGIS2GEOS_multipolygon(polys, g->nobjs, g->SRID,g->is3d);
- pfree(polys);
+ if (polys != NULL)
+ pfree(polys);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
break;
case MULTILINETYPE:
//make an array of POLYGON3Ds
- lines = (LINE3D**) palloc(sizeof (LINE3D*) * g->nobjs);
+ lines = NULL;
+ if (g->nobjs >0)
+ lines = (LINE3D**) palloc(sizeof (LINE3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
lines[t] = (LINE3D*) ((char *) g +offsets1[t]) ;
break;
case MULTIPOINTTYPE:
//make an array of POINT3Ds
- points = (POINT3D**) palloc(sizeof (POINT3D*) * g->nobjs);
+ points = NULL;
+ if (g->nobjs >0)
+ points = (POINT3D**) palloc(sizeof (POINT3D*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
points[t] = (POINT3D*) ((char *) g +offsets1[t]) ;
break;
case COLLECTIONTYPE:
//make an array of GEOS Geometrys
- geoms = (Geometry**) palloc(sizeof (Geometry*) * g->nobjs);
+ geoms = NULL;
+ if (g->nobjs >0)
+ geoms = (Geometry**) palloc(sizeof (Geometry*) * g->nobjs);
for (t=0;t<g->nobjs;t++)
{
obj = ((char *) g +offsets1[t]);
}
}
geos= PostGIS2GEOS_collection(geoms,g->nobjs,g->SRID,g->is3d);
- pfree(geoms);
+ if (geoms != NULL)
+ pfree(geoms);
if (geos == NULL)
{
elog(ERROR,"Couldnt convert the postgis geometry to GEOS!");
PG_RETURN_NULL(); // never get here
}
+PG_FUNCTION_INFO_V1(issimple);
+Datum issimple(PG_FUNCTION_ARGS)
+{
+ elog(ERROR,"issimple:: operation not implemented - compile PostGIS with GEOS support");
+ PG_RETURN_NULL(); // never get here
+}
+PG_FUNCTION_INFO_V1(geomequals);
+Datum geomequals(PG_FUNCTION_ARGS)
+{
+ elog(ERROR,"geomequals:: operation not implemented - compile PostGIS with GEOS support");
+ PG_RETURN_NULL(); // never get here
+}
+PG_FUNCTION_INFO_V1(isring);
+Datum isring(PG_FUNCTION_ARGS)
+{
+ elog(ERROR,"isring:: operation not implemented - compile PostGIS with GEOS support");
+ PG_RETURN_NULL(); // never get here
+}
+
+
#endif
extern "C" int GEOSGetSRID(Geometry *g1);
extern "C" int GEOSGetNumGeometries(Geometry *g1);
+extern "C" char GEOSisSimple(Geometry *g1);
+extern "C" char GEOSequals(Geometry *g1, Geometry*g2);
+
+extern "C" char GEOSisRing(Geometry *g1);
+
+extern "C" Geometry *GEOSpointonSurface(Geometry *g1);
+
+
//###########################################################
for (t =0; t< ngeoms; t++)
{
- subGeos->push_back(geoms[t]);
+ subGeos->push_back(geoms[t]);
}
g = geomFactory->buildGeometry(subGeos);
if (g==NULL)
Coordinate *c;
if (is3d)
- c = new Coordinate(point->x, point->y);
+ c = new Coordinate(point->x, point->y);
else
c = new Coordinate(point->x, point->y, point->z);
Geometry *g = geomFactory->createPoint(*c);
for (t =0; t< npolys; t++)
{
- subPolys->push_back(PostGIS2GEOS_polygon(polygons[t], SRID,is3d ));
+ subPolys->push_back(PostGIS2GEOS_polygon(polygons[t], SRID,is3d ));
}
g = geomFactory->createMultiPolygon(subPolys);
if (g== NULL)
for (t =0; t< nlines; t++)
{
- subLines->push_back(PostGIS2GEOS_linestring(lines[t], SRID,is3d ));
+ subLines->push_back(PostGIS2GEOS_linestring(lines[t], SRID,is3d ));
}
g = geomFactory->createMultiLineString(subLines);
if (g==NULL)
for (t =0; t< npoints; t++)
{
- subPoints->push_back(PostGIS2GEOS_point(points[t], SRID,is3d ));
+ subPoints->push_back(PostGIS2GEOS_point(points[t], SRID,is3d ));
}
g = geomFactory->createMultiPoint(subPoints);
if (g==NULL)
pts = (POINT3D *) ( (char *)&(polygon->npoints[polygon->nrings] ) );
pts = (POINT3D *) MAXALIGN(pts);
-
+
// make outerRing
cl = new BasicCoordinateList(polygon->npoints[0]);
if (is3d)
}
}
-// call g1->contains(g2)
+// call g1->contains(g2)
// returns 0 = false
// 1 = true
// 2 = error was trapped
// general purpose
//-----------------------------------------------------------------
+char GEOSequals(Geometry *g1, Geometry*g2)
+{
+ try {
+ bool result;
+ result = g1->equals(g2);
+ return result;
+ }
+ catch (...)
+ {
+ return 2;
+ }
+}
+
+
+
char *GEOSasText(Geometry *g1)
{
try
}
}
+char GEOSisSimple(Geometry *g1)
+{
+ try
+ {
+ return g1->isSimple();
+ }
+ catch (...)
+ {
+ return 2;
+ }
+}
+
+char GEOSisRing(Geometry *g1)
+{
+ try
+ {
+ return (( (LinearRing*)g1)->isRing());
+ }
+ catch (...)
+ {
+ return 2;
+ }
+}
+
+
+
+
char *GEOSGeometryType(Geometry *g1)
{
try
}
-
+Geometry *GEOSpointonSurface(Geometry *g1)
+{
+ try
+ {
+ Geometry *g3 = g1->getInteriorPoint();
+ return g3;
+ }
+ catch (...)
+ {
+ return NULL;
+ }
+}
try{
POINT3D *result = (POINT3D*) malloc (sizeof(POINT3D));
Coordinate *c =g1->getCoordinate();
-
+
result->x = c->x;
result->y = c->y;
result->z = c->z;
{
return NULL;
}
-
+
}
for (t=0;t<numPoints;t++)
{
c =cl->getAt(t);
-
+
result[t].x = c.x;
result[t].y = c.y;
result[t].z = c.z;
}
-
+
return result;
}
catch(...)
}
-//only call on GCs
+//only call on GCs (or multi*)
int GEOSGetNumGeometries(Geometry *g1)
{
try{
}
+
*
* This is free software; you can redistribute and/or modify it under
* the terms of hte GNU General Public Licence. See the COPYING file.
- *
+ *
**********************************************************************
* $Log$
+ * Revision 1.3 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.2 2003/07/01 18:30:55 pramsey
* Added CVS revision headers.
*
#include "utils/elog.h"
//Norman Vine found this problem for compiling under cygwin
-// it defines BYTE_ORDER and LITTLE_ENDIAN
+// it defines BYTE_ORDER and LITTLE_ENDIAN
#ifdef __CYGWIN__
#include <sys/param.h> // FOR ENDIAN DEFINES
#endif
in = (GEOMETRY*)PG_DETOAST_DATUM(PointerGetDatum(entry->pred));
+
+ if (in->nobjs ==0) // this is the EMPTY geometry
+ {
+ //elog(NOTICE,"found an empty geometry");
+ // dont bother adding this to the index
+ PG_RETURN_POINTER(entry);
+ }
+
r = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
r->size = sizeof(GEOMETRYKEY);
r->SRID = in->SRID;
thebox = convert_box3d_to_box(&in->bvol);
memcpy( (void*)&(r->key), (void*)thebox, sizeof(BOX) );
- if ( (char*)in != entry->pred )
+ if ( (char*)in != entry->pred )
{
pfree( in );
pfree(thebox);
} else {
gistentryinit(*retval, NULL, entry->rel, entry->page,
entry->offset, 0,FALSE);
- }
+ }
} else {
retval = entry;
}
PG_RETURN_BOOL(FALSE);
}
- PG_RETURN_BOOL(rtree_internal_consistent((BOX*)&( ((GEOMETRYKEY *)(entry->pred))->key ),
+ PG_RETURN_BOOL(rtree_internal_consistent((BOX*)&( ((GEOMETRYKEY *)(entry->pred))->key ),
thebox, strategy));
}
printf("GIST: ggeometry_union called\n");
#endif
- result = (GEOMETRYKEY*)
+ result = (GEOMETRYKEY*)
rtree_union(
(bytea*) PG_GETARG_POINTER(0),
(int*) PG_GETARG_POINTER(1),
if ( b1 && b2 )
- *result = DatumGetBool( DirectFunctionCall2( box_same,
- PointerGetDatum(&(b1->key)),
+ *result = DatumGetBool( DirectFunctionCall2( box_same,
+ PointerGetDatum(&(b1->key)),
PointerGetDatum(&(b2->key))) );
else
- *result = ( b1==NULL && b2==NULL ) ? TRUE : FALSE;
+ *result = ( b1==NULL && b2==NULL ) ? TRUE : FALSE;
return(result);
}
rt_box_inter,
PointerGetDatum( &(b1->key) ),
PointerGetDatum( &(b2->key) )) );
-
+
if (interd) {
GEOMETRYKEY *tmp = (GEOMETRYKEY*)palloc( sizeof(GEOMETRYKEY) );
tmp->size = sizeof(GEOMETRYKEY);
-
+
memcpy( (void*)&(tmp->key), (void*)interd, sizeof(BOX) );
tmp->SRID = b1->SRID;
pfree( interd );
PG_RETURN_POINTER( tmp );
- } else
+ } else
PG_RETURN_POINTER( NULL );
}
} else {
*sizep = 0;
retval = NULL;
- }
+ }
} else {
BOX *key = (BOX*)DatumGetPointer( DirectFunctionCall2(
rt_box_union,
printf("GIST: rtree_union called\n");
#endif
- numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY);
+ numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY);
tmp = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[0]).pred;
out = NULL;
#endif
-
+
ud = (*bu)( origentry->pred, newentry->pred, &sizep );
- tmp1 = (*sb)( ud );
+ tmp1 = (*sb)( ud );
if (ud) pfree(ud);
*result = tmp1 - (*sb)( origentry->pred );
/*
** The GiST PickSplit method
-** We use Guttman's poly time split algorithm
+** We use Guttman's poly time split algorithm
*/
GIST_SPLITVEC *rtree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, int keylen, BINARY_UNION bu, RDF interop, SIZE_BOX sb)
{
nbytes = (maxoff + 2) * sizeof(OffsetNumber);
v->spl_left = (OffsetNumber *) palloc(nbytes);
v->spl_right = (OffsetNumber *) palloc(nbytes);
-
+
firsttime = true;
waste = 0.0;
-
+
for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) {
datum_alpha = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) {
datum_beta = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[j].pred);
-
+
/* compute the wasted space by unioning these guys */
- /* size_waste = size_union - size_inter; */
+ /* size_waste = size_union - size_inter; */
union_d = (*bu)( datum_alpha, datum_beta, &sizep );
if ( union_d ) {
size_union = (*sb)(union_d);
if ( inter_d ) {
size_inter = (*sb)(inter_d);
pfree(inter_d);
- } else
+ } else
size_inter = 0.0;
} else
size_inter = 0.0;
size_waste = size_union - size_inter;
-
+
/*
* are these a more promising split that what we've
* already seen?
*/
-
+
if (size_waste > waste || firsttime) {
waste = size_waste;
seed_1 = i;
}
}
}
-
+
left = v->spl_left;
v->spl_nleft = 0;
right = v->spl_right;
v->spl_nright = 0;
-
+
if ( ((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred ) {
datum_l = (char*) palloc( keylen );
memcpy( (void*)datum_l, (void*)(((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred ), keylen );
- } else
- datum_l = NULL;
- size_l = (*sb)( datum_l );
+ } else
+ datum_l = NULL;
+ size_l = (*sb)( datum_l );
if ( ((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred ) {
datum_r = (char*) palloc( keylen );
memcpy( (void*)datum_r, (void*)(((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred ), keylen );
- } else
- datum_r = NULL;
- size_r = (*sb)( datum_r );
-
+ } else
+ datum_r = NULL;
+ size_r = (*sb)( datum_r );
+
/*
* Now split up the regions between the two seeds. An important
* property of this split algorithm is that the split vector v
* This is handled at the very end, when we have placed all the
* existing tuples and i == maxoff + 1.
*/
-
+
maxoff = OffsetNumberNext(maxoff);
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
-
+
/*
* If we've already decided where to place this item, just
* put it on the right list. Otherwise, we need to figure
* out which page needs the least enlargement in order to
* store the item.
*/
-
+
if (i == seed_1) {
*left++ = i;
v->spl_nleft++;
v->spl_nright++;
continue;
}
-
- /* okay, which page needs least enlargement? */
+
+ /* okay, which page needs least enlargement? */
datum_alpha = (char *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
union_dl = (*bu)( datum_l, datum_alpha, &sizep );
union_dr = (*bu)( datum_r, datum_alpha, &sizep );
- size_alpha = (*sb)( union_dl );
- size_beta = (*sb)( union_dr );
-
+ size_alpha = (*sb)( union_dl );
+ size_beta = (*sb)( union_dr );
+
/* pick which page to add it to */
if (size_alpha - size_l < size_beta - size_r) {
pfree(datum_l);
}
}
*left = *right = FirstOffsetNumber; /* sentinel value, see dosplit() */
-
+
v->spl_ldatum = datum_l;
v->spl_rdatum = datum_r;
*
* This is free software; you can redistribute and/or modify it under
* the terms of hte GNU General Public Licence. See the COPYING file.
- *
+ *
**********************************************************************
* $Log$
+ * Revision 1.6 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.5 2003/07/01 18:30:55 pramsey
* Added CVS revision headers.
*
if ( entry->leafkey)
{
retval = palloc(sizeof(GISTENTRY));
- if ( DatumGetPointer(entry->key) != NULL ) {
+ if ( DatumGetPointer(entry->key) != NULL )
+ {
GEOMETRY *in;
BOX *r;
#ifdef DEBUG_GIST
- printf("GIST: ggeometry_compress called on geometry\n");
+ elog(NOTICE,"GIST: ggeometry_compress called on geometry\n");
fflush( stdout );
#endif
in = (GEOMETRY*)PG_DETOAST_DATUM( entry->key );
- r = convert_box3d_to_box(&in->bvol);
- if ( in != (GEOMETRY*)DatumGetPointer(entry->key) )
+
+ if (in->nobjs ==0) // this is the EMPTY geometry
{
- pfree( in );
+ //elog(NOTICE,"found an empty geometry");
+ // dont bother adding this to the index
+ PG_RETURN_POINTER(entry);
}
+ else
+ {
+ r = convert_box3d_to_box(&in->bvol);
+ if ( in != (GEOMETRY*)DatumGetPointer(entry->key) )
+ {
+ pfree( in );
+ }
- gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
- entry->offset, sizeof(BOX), FALSE);
+ gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page,
+ entry->offset, sizeof(BOX), FALSE);
+ }
- } else {
+ }
+ else
+ {
gistentryinit(*retval, (Datum) 0, entry->rel, entry->page,
entry->offset, 0,FALSE);
}
- } else {
+ }
+ else
+ {
retval = entry;
}
PG_RETURN_POINTER(retval);
*/
#ifdef DEBUG_GIST
- printf("GIST: ggeometry_consistent called\n");
+ elog(NOTICE,"GIST: ggeometry_consistent called\n");
fflush( stdout );
#endif
bool retval;
#ifdef DEBUG_GIST
- printf("GIST: rtree_internal_consist called\n");
+ elog(NOTICE,"GIST: rtree_internal_consist called\n");
fflush( stdout );
#endif
*pageunion;
#ifdef DEBUG_GIST
- printf("GIST: gbox_union called\n");
+ elog(NOTICE,"GIST: gbox_union called\n");
fflush( stdout );
#endif
float tmp1;
#ifdef DEBUG_GIST
- printf("GIST: gbox_penalty called\n");
+ elog(NOTICE,"GIST: gbox_penalty called\n");
fflush( stdout );
#endif
int nbytes;
#ifdef DEBUG_GIST
- printf("GIST: gbox_picksplit called\n");
+ elog(NOTICE,"GIST: gbox_picksplit called\n");
fflush( stdout );
#endif
bool *result = (bool *) PG_GETARG_POINTER(2);
#ifdef DEBUG_GIST
- printf("GIST: gbox_same called\n");
+ elog(NOTICE,"GIST: gbox_same called\n");
fflush( stdout );
#endif
{
#ifdef DEBUG_GIST
- printf("GIST: size_box called\n");
+ elog(NOTICE,"GIST: size_box called\n");
fflush( stdout );
#endif
*
**********************************************************************
* $Log$
+ * Revision 1.25 2003/08/08 18:19:20 dblasby
+ * Conformance changes.
+ * Removed junk from postgis_debug.c and added the first run of the long
+ * transaction locking support. (this will change - dont use it)
+ * conformance tests were corrected
+ * some dos cr/lf removed
+ * empty geometries i.e. GEOMETRYCOLLECT(EMPTY) added (with indexing support)
+ * pointN(<linestring>,1) now returns the first point (used to return 2nd)
+ *
* Revision 1.24 2003/08/06 19:31:18 dblasby
* Added the WKB parser. Added all the functions like
* PolyFromWKB(<WKB>,[<SRID>]).
//printf("str=%s\n",str);
+
+
//trim white
while (isspace((unsigned char) *str))
str++;
str++;
}
+
+ if (strstr(str,"EMPTY"))
+ {
+ GEOMETRY *result=makeNullGeometry( SRID);
+ if (strstr(str,"MULTIPOLYGON"))
+ result->type = MULTIPOLYGONTYPE;
+ if (strstr(str,"MULTILINESTRING"))
+ result->type = MULTILINETYPE;
+ if (strstr(str,"MULTIPOINT"))
+ result->type = MULTIPOINTTYPE;
+ PG_RETURN_POINTER( result );
+ }
+
if (strstr(str,"BOX3D") != NULL ) // bbox only
{
int mem_size,npts;
+ if (geometry->nobjs == 0)
+ {
+ //empty geometry
+ result = (char*) palloc(30);
+
+ sprintf(result,"GEOMETRYCOLLECTION(EMPTY)");
+
+ if (geometry->type == MULTILINETYPE)
+ sprintf(result,"MULTILINESTRING(EMPTY)");
+ if (geometry->type == MULTIPOINTTYPE)
+ sprintf(result,"MULTIPOINT(EMPTY)");
+ if (geometry->type == MULTIPOLYGONTYPE)
+ sprintf(result,"MULTIPOLYGON(EMPTY)");
+ return result;
+ }
+
+
//printf("in geom_out(%p)\n",geometry);
size = 30; //just enough to put in object type
BOX3D *result;
+ if (geom->nobjs == 0)
+ PG_RETURN_NULL();
+
//make a copy of it
result = palloc ( sizeof(BOX3D) );
// we make a list of smaller wkb chunks in sub_result[]
// and that wkb chunk's size in sizes[]
-
- sub_result = palloc( sizeof(char *) * geom->nobjs);
- sizes = palloc( sizeof(int) * geom->nobjs);
+ sub_result = NULL;
+ if (geom->nobjs >0)
+ sub_result = palloc( sizeof(char *) * geom->nobjs);
+ sizes = NULL;
+ if (geom->nobjs >0)
+ sizes = palloc( sizeof(int) * geom->nobjs);
- for (t=0; t<=geom->nobjs; t++) //for each part of the collections, do the work in another function
+ for (t=0; t<geom->nobjs; t++) //for each part of the collections, do the work in another function
{
type = geom->objType[t];
}
//free temp structures
- pfree( sub_result);
- pfree( sizes);
+ if (sub_result != NULL)
+ pfree( sub_result);
+ if (sizes != NULL)
+ pfree( sizes);
//total size of the wkb
*end_size = total_size+9;
if (geom->type == MULTILINETYPE)
{
//make a list of lines
- linelist = palloc( sizeof(LINE3D *) * geom->nobjs);
+ linelist = NULL;
+ if (geom->nobjs >0)
+ linelist = palloc( sizeof(LINE3D *) * geom->nobjs);
for (t=0;t<geom->nobjs; t++)
{
linelist[t] = (LINE3D *) ((char *) geom +offsets1[t] ) ;
if (geom->type == MULTIPOLYGONTYPE)
{
//make a list of polygons
- polylist = palloc( sizeof(POLYGON3D *) * geom->nobjs);
+ polylist = NULL;
+ if (geom->nobjs >0)
+ polylist = palloc( sizeof(POLYGON3D *) * geom->nobjs);
for (t=0;t<geom->nobjs; t++)
{
polylist[t] = (POLYGON3D *) ((char *) geom +offsets1[t] ) ;
WKB+=4;
(*bytes_read)+=4;
if (ngeoms ==0)
- return NULL;
+ {
+ GEOMETRY *result= makeNullGeometry(-1);
+ result->type = MULTIPOINTTYPE;
+ return result;
+ }
mybytes_read = *bytes_read;
so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
WKB+=4;
(*bytes_read)+=4;
if (ngeoms ==0)
- return NULL;
+ {
+ GEOMETRY *result= makeNullGeometry(-1);
+ result->type = MULTILINETYPE;
+ return result;
+ }
mybytes_read = *bytes_read;
so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
WKB+=4;
(*bytes_read)+=4;
if (ngeoms ==0)
- return NULL;
+ {
+ GEOMETRY *result= makeNullGeometry(-1);
+ result->type = MULTIPOLYGONTYPE;
+ return result;
+ }
mybytes_read = *bytes_read;
so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
WKB+=4;
(*bytes_read)+=4;
if (ngeoms ==0)
- return NULL;
+ {
+ GEOMETRY *result= makeNullGeometry(-1);
+ return result;
+ }
mybytes_read = *bytes_read;
so_far = WKBtoGeometry(WKB, length - mybytes_read, &other_bytes_read);
}
PG_RETURN_POINTER(geom);
}
+
+
+//returns a GEOMETRYCOLLECTION(EMPTY)
+// bbox of this object is BOX3D(0 0 0, 0 0 0)
+// but should be treated as NULL
+GEOMETRY *makeNullGeometry(int SRID)
+{
+ int size = sizeof(GEOMETRY);
+ GEOMETRY *result = palloc(size);
+
+
+ memset(result,0, size ); // init to 0s
+
+ result->size = size;
+ result->nobjs = 0;
+ result->type = COLLECTIONTYPE;
+ result->is3d = false;
+
+
+ result->SRID = SRID;
+ result->scale = 1.0;
+ result->offsetX = 0;
+ result->offsetY = 0;
+
+ memset(&result->bvol,0, sizeof(BOX3D) ); //make bbox :: BOX3D(0 0 0, 0 0 0)
+
+ return result;
+}