jts-1.11/0000755000000000000000000000000011360675476010751 5ustar rootrootjts-1.11/bin/0000755000000000000000000000000011334103352011475 5ustar rootrootjts-1.11/bin/testbuilder.bat0000644000000000000000000000102711334103352014513 0ustar rootroot@echo off rem A batch file to run the JTS Test Builder set CLASSPATH= for %%i in (..\lib\*.*) do ( set jarfile=%%i rem If we append to a variable inside the for, only the last entry will rem be kept. So append to the variable outside the for. rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html. rem [Jon Aquino] call :setclass ) start javaw com.vividsolutions.jtstest.testbuilder.JTSTestBuilder goto :eof :setclass set CLASSPATH=%jarfile%;%CLASSPATH% set jarfile= :eofjts-1.11/bin/test_stmlf.bat0000644000000000000000000000120211334103352014344 0ustar rootroot@echo off rem A batch file to run a XML test files set CLASSPATH= for %%i in (..\lib\*.*) do ( set jarfile=%%i rem If we append to a variable inside the for, only the last entry will rem be kept. So append to the variable outside the for. rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html. rem [Jon Aquino] call :setclass ) java com.vividsolutions.jtstest.testrunner.TopologyTestApp -Files ..\testxml\stmlf -geomop com.vividsolutions.jtstest.testrunner.geomop.OverlayValidatedGeometryOperation pause goto :eof :setclass set CLASSPATH=%jarfile%;%CLASSPATH% set jarfile= :eofjts-1.11/bin/test.bat0000644000000000000000000000114211334103352013142 0ustar rootroot@echo off rem A batch file to run the XML test files written by Geographic Data BC. set CLASSPATH= for %%i in (..\lib\*.*) do ( set jarfile=%%i rem If we append to a variable inside the for, only the last entry will rem be kept. So append to the variable outside the for. rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html. rem [Jon Aquino] call :setclass ) java com.vividsolutions.jtstest.testrunner.TopologyTestApp -Files ..\testxml\validate ..\testxml\general pause goto :eof :setclass set CLASSPATH=%jarfile%;%CLASSPATH% set jarfile= :eofjts-1.11/bin/test_robust.bat0000644000000000000000000000105411334103352014542 0ustar rootroot@echo off rem A batch file to run a XML test files set CLASSPATH= for %%i in (..\lib\*.*) do ( set jarfile=%%i rem If we append to a variable inside the for, only the last entry will rem be kept. So append to the variable outside the for. rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html. rem [Jon Aquino] call :setclass ) java com.vividsolutions.jtstest.testrunner.TopologyTestApp -Files ..\testxml\robust pause goto :eof :setclass set CLASSPATH=%jarfile%;%CLASSPATH% set jarfile= :eofjts-1.11/bin/testrunner.bat0000644000000000000000000000107611334103352014402 0ustar rootroot@echo off rem A batch file to run the JTS test runner. set CLASSPATH= for %%i in (..\lib\*.*) do ( set jarfile=%%i rem If we append to a variable inside the for, only the last entry will rem be kept. So append to the variable outside the for. rem See http://www.experts-exchange.com/Operating_Systems/MSDOS/Q_20561701.html. rem [Jon Aquino] call :setclass ) start javaw com.vividsolutions.jtstest.testrunner.TopologyTestApp -Properties testrunner.properties -GUI goto :eof :setclass set CLASSPATH=%jarfile%;%CLASSPATH% set jarfile= :eofjts-1.11/bin/testrunner.properties0000644000000000000000000000027311334103352016026 0ustar rootroot#Properties file for class com.vividsolutions.jtstest.testrunner.TopologyTestApp #Wed Dec 06 16:08:49 PST 2006 TestFiles=\ Z\:\\proj\\jts\\robust\\tests\\unit\\cmp-5966094-2025063.xml jts-1.11/doc/0000755000000000000000000000000011360675476011516 5ustar rootrootjts-1.11/doc/LICENSE.txt0000644000000000000000000006446611334103350013333 0ustar rootroot GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jts-1.11/doc/JTS Version History.html0000644000000000000000000011052711343017562016065 0ustar rootroot JTS Version History

JTS TOPOLOGY SUITE
Version History

This document lists the change history of release versions of the JTS Topology Suite


Version 1.11

Release Date: March 1, 2010

Functionality Improvements

  • Added CoordinateArrays.isRing
  • Added CGAlgorithms.signedArea(CoordinateSequence)
  • Added CoordinateArrays.copyDeep(...) method to copy sections of arrays
  • Added CoordinateList.add(Coordinate[], boolean, int, int) method to add sections of arrays
  • Added LineSegment.toGeometry(), LineSegment.lineIntersection()()
  • Added LineSegment.hashCode()
  • Added geometric similarity classes (HausdorffSimilarityMeasure, AreaSimilarityMeasure)
  • Added MinimumDiameter.getMinimumRectangle()
  • Added MinimumBoundingCircle class
  • Added Densifier class
  • Added triangulation API, including QuadEdgeSubdivision, IncrementalDelaunayTriangulator, ConformingDelaunayTriangulator and supporting classes
  • Added VoronoiDiagramBuilder to perform Voronoi diagram generation
  • Added scaleInstance(scaleX, scaleY, x, y) to AffineTransformation
  • Added AffineTransformationFactory to allow generating transformations from various kinds of control inputs
  • Added BinTree.remove() method
  • Fixed BinTree.query() to allow null interval arguments
  • Added ShapeReader API to convert Java2D Shapes into JTS Geometry
  • Added ShapeWriter API to convert JTS geometry into Java2D Shapes
  • Added FontGlyphReader API to render Java2D text font glyphs into geometry
  • Added SdeReader to jtsio library
  • Added Debug break methods
  • Added Memory utility for reporting memory statistics
  • Added ObjectCounter utility for counting objects
  • Added createSquircle and createSuperCircle to GeometricShapeFactory

Performance Improvements

  • Improved performance of Geometry.getArea() and Geometry.getLength() when used with custom CoordinateSequences

API Changes

  • Deprecated WKBWriter.bytesToHex in favour of WKBWriter.toHexto regularize and simplify method name

Bug Fixes

  • Fixed Point.isValid() to check for invalid coordinates (ie with Nan ordinates)
  • Fixed Geometry.distance() and DistanceOp to return 0.0 for empty inputs
  • Fixed Buffer to handle degenerate polygons with too few distinct points correctly
  • Added illegal state check in LineSegment.pointAlongOffset()
  • Fixed exception strategy in BufferSubgraph to handle certain robustness failures correctly
  • Fixed robustness problem in OffsetCurveBuilder in computing mitred joins for nearly parallel segments
  • Fixed minor bug in BufferInputLineSimplifier which prevented simplification of some situations
  • Fixed bug in BufferInputLineSimplifier which caused over-simplification for large tolerances
  • Fixed bug in Angle.normalizePositive to handle values > 2PI correctly
  • Fixed WKTWriter to emit correct syntax for MULTIPOINTs
  • Fixed WKTReader to accept correct syntax for MULTIPOINTs
  • CGAlgorithms.isCCW now checks for too few points in the ring and throws an IllegalArgumentException
  • Fixed bug in AffineTransformation#eqals (logic bug)
  • Fixed bug in CoordinateList#closeRing (cloning closing Coordinate)

JTS TestBuilder

Functionality Improvements

  • WKT input is cleaned automatically when loaded (illegal chars are removed)
  • Added WKT-Formatted option to Test Case View dialog
  • Many new geometry functions added
  • Geometry functions are displayed in tree
  • Geometry functions can be implemented as Java static class methods.
  • Geometry function classes can be loaded dynamically from command-line
  • Improved handling of very large geometry inputs and results
  • Threaded rendering allows display of very large geometries without limiting usability
  • Added Draw Rectangle tool
  • Added Drag-n-drop loading of .SHP files
  • Added Info tool to provide persistent display of geometry point/segment information
  • Added display of memory usage

Version 1.10

Release Date: December 31, 2008

Functionality Improvements

  • Added Geometry.reverse() method for all geometry types
  • Added setSrsName, setNamespace, setCustomRootElements methods to GMLWriter
  • Added Envelope.getArea method
  • Added copy, copyCoord methods to CoordinateSequences
  • Added area method to Envelope
  • Added extractPoint(pt, offset) methods to LengthIndexedLine and LocationIndexedLine
  • Added CoordinatePrecisionReducerFilter
  • Added UnaryUnionOp(Collection, GeometryFactory) constructor to handle empty inputs more automatically
  • Added DiscreteHausdorffDistance class
  • Made LineMerger able to be called incrementally
  • Added GeometricShapeFactory.createArcPolygon to create a polygonal arc
  • Enhanced Geometry.buffer() to preserve SRID

Performance Improvements

  • Improved performance for EdgeList (by using a more efficient technique for detecting duplicate edges)
  • Improved performance for ByteArrayInStream (by avoiding use of java.io.ByteArrayInputStream)
  • Unrolled intersection computation in HCoordinate to avoid object allocation
  • Improved performance for buffering via better offset curve generation and simplification.
  • Improved performance for IsValipOp by switching to use STRtree for nested hole checking

Bug Fixes

  • Fixed Geometry.getClassSortIndex() to lazily initialize the sorted class list. This fixes a threading bug.
  • Fixed RectangleContains to return correct result for points on the boundary of the rectangle
  • Fixed error in com.vividsolutions.jts.simplify.LineSegmentIndex which caused polygons simplified using TopologyPreservingSimplifier to be invalid in certain situations
  • Fixed error in DouglasPeuckerSimplifier which caused empty polygons to be returned when they contained a very small hole
  • Fixed PackedCoordinateSequence to return NaN for null ordinate values
  • Fixed Geometry.centroid() (CentroidArea) so that it handles degenerate (zero-area) polygons
  • Fixed Geometry.buffer() (OffsetCurveBuilder) so that it handles JOIN_MITRE cases with nearly collinear lines correctly
  • Fixed GeometryFactory.toGeometry(Envelope) to return a CW polygon
  • Fixed UnaryUnionOp to correctly handle heterogeneous inputs with P/L/A components
  • Fixed UnaryUnionOp to accept LINEARRINGs
  • Fixed CentroidArea to handle zero-area polygons correctly
  • Fixed WKBWriter to always output 3D when requested, and to handle 2D PackedCoordinateSequences correctly in this case
  • Fixed NodedSegmentString to handle zero-length line segments correctly (via safeOctant)
  • Cleaned up code to remove unneeded CGAlgorithms objects
  • Fixed GeometricShapeFactory.createArc to ensure arc has requested number of vertices

API Changes

  • Moved GML I/O classes into core JTS codebase
  • Changed GMLWriter to not write the srsName attribute by default
  • In DistanceOp switched to using nearestPoints method names
  • Exposed STRtree.getRoot() method

JTS TestBuilder

UI Improvements

  • Added ability to read GML from input panel
  • Added GML output to View dialog
  • Added file drag'n'drop to Geometry Input text areas
  • Add display of computation time
  • Added Stats panel
  • Added Scalar functions panel, with extensible function list
  • Added Save as PNG...

JTS TestRunner

Functionality Improvements

  • Added -testCaseIndex command-line option

Version 1.9

Release Date: January 2, 2008

Functionality Improvements

  • Added Polygonal, Lineal, Puntal tag interfaces to better categorize geometry classes
  • Added Geometry.union() method, UnaryUnionOp class for efficient unioning of geometrys
  • Added Triangle.area3D method
  • Added LineSegment.pointAlongOffset method
  • Added LineSegment.orientationIndex(Coordinate) method
  • Added PreparedGeometry classes and methods to optimize some geometry functions in batch situations
  • Added Envelope.covers methods, for preciseness
  • Added OctagonalEnvelope class
  • Improved CGAlgorithms.isPointInRing method to handle case where point lies on the ring
  • Added CGAlgorithms.locatePointInRing method
  • Added PointInAreaLocator interface, enhanced SimplePointInAreaLocator to extend this
  • Added RayCrossingCounter, IndexedPointInAreaLocator classes for more efficient Point-In-Polygon testing
  • Added GeometryCombiner class
  • Enhanced BufferOp with join styles
  • Enhanced WKTReader to accept any case for NaN number symbols
  • Added WKTFileReader class
  • Improved performance of CoordinateList constructors
  • Added CascadedPolygonUnion class
  • Added LinearLocation.isOnSameSegment method
  • Added LinearLocation.getSegment method
  • Added LocationIndexedLine.indexOfAfter method
  • Added interpolation of Z value to linear referencing methods
  • Added methods to rotate around a given point to AffineTransformation
  • Allowed GeometricShapeFactory to be subclassed to add new shapes
  • Added SineStarFactory (primarily to support testing)
  • Added SortedPackedIntervalRTree class
  • Added SegmentSetMutualIntersector interface and implementations
  • Added Node.remove(DirectedEdge) method in planargraph package

Performance Improvements

  • Improved performance for SimplePointInAreaLocator (by checking ring envelopes as a filter)

Bug Fixes

  • Geometry.buffer operation fixed to always return polygonal geometries
  • Fixed bug in Geometry.buffer(distance, quadrantSegs) causing failure for some cases with quadrantSegs = 1
  • Fixed bug in GeometryFactory.toGeometry(Envelope) which was returning invalid Polygons for "linear" envelopes
  • Fixed bug in MonotoneChainBuilder which caused failures in situations with segments of zero length
  • Fixed PointLocator to handle locating in Point geometries
  • Fixed GeometricShapeFactory to always use provided PrecisionModel
  • Fixed LinearLocation.clone method
  • Fixed LinearLocation.isValid method
  • Fixed Polygonizer to accept single-point linestrings (which are ignored)

API Changes

  • Deprecated RobustCGAlgorithms
  • Deprecated BufferOp cap style constants (these are now provided in BufferParameters)
  • Removed SIRPointInRing

JTS TestRunner

New Features

  • Added ability to specify GeometryOperation in XML file
  • Added BufferValidatedGeometryOperation
  • Added ability to specify custom result matching via resultMatcher parameter in XML files
  • Added BufferResultMatcher

JTS TestBuilder

UI Improvements

  • Improved rendering of geometries
  • Improved symbology for orientation
  • Simplified Geometry creation
  • Improved vertex move/add
  • Added tooltip for coordinate location
  • Added more geometry functions
  • Added Copy Result to Test button

Code Improvements

  • Restructured code for more flexibility, better Swing functionality
  • Made it easier to add geometry functions

Version 1.8

Release Date: December 19, 2006

Functionality Improvements

  • Improved robustness for overlay operations, via using geometry snapping
  • Added Angle class
  • Added methods to Triangle class
  • Added LineSegment.midPoint method
  • Added ability to specify output of Z values to WKTWriter
  • Added setFormatted, setTab, setMaxCoordinatesPerLine methods to WKTWriter
  • Added BoundaryNodeRule classes, and ability to specify a Boundary Node Rule in RelateOp, IsSimpleOp, BoundaryOp
  • Added ability to get the failure location to IsSimpleOp
  • Added BoundaryOp with improved algorithm for lineal geometries. Changed lineal Geometry classes to use it.
  • Enhanced Geometry overlay methods to accept empty GeometryCollections.
  • Enhanced Error Handling for WKTReader
  • Added CoordinateSequenceFilter
  • Added AffineTransformation and AffineTransformationBuilder

API Changes

  • Changed API for IsSimpleOp (required to support returning failure location)

Bug Fixes

  • Fixed bug in GeometryFactory.buildGeometry causing failure if input contained all GeometryCollections of the same subclass
  • Changed AssertFailure to TopologyException in PolygonBuilder
  • Improved correctness of RobustLineIntersector in certain cases where segment endpoints intersect
  • Eliminated duplicate method execution in TestRunner

JTS TestBuilder

New Features

  • Zoom tool can now draw zoom box as well as click
  • Cut, Copy and Paste buttons for Input WKT
  • added ability to specify custom Geometry Operations

JTS TestRunner

New Features

  • added ability to specify custom Geometry Operations

Bug Fixes

  • Eliminated duplicate method execution

Version 1.7.2

Release Date: June 22, 2006

Functionality Improvements

  • Added support for EWKB (SRIDs only) to WKBReader

Bug Fixes

  • Fixed bug in CoordinateArrays.ptNotInList. Changed polygonize.EdgeRing to used corrected code.
  • Fixed bug causing duplicate points in ScaledNoder
  • Fixed bug causing Null Pointer for empty geometries in OraWriter
  • Changed AssertFailure to TopologyException in EdgeNode

Version 1.7.1

Release Date: March 20, 2006

Functionality Improvements

  • Added Hex string conversion to WKBReader and WKBWriter

Bug Fixes

  • Fixed null point cloning bug in TopologyValidationError (thanks to Markus Gebhard)
  • Fixed bug in PointLocator fix for LinearRings
  • Fixed bug in Geometry.isValid and IsValidOp causing some valid polygons to be reported as having a Disconnected Interior (specifically, polygons containing holes touching at a single point, where the point is the highest point in the hole rings, and where the holes have a specific orientation)
  • Fixed bug in Polygon.isRectangle, which reported some valid rectangles as false

Performance Improvements

  • Improved performance for Geometry#withinDistance (via short-circuiting)

Contributors

  • Dave Blasby
  • Koen van Dijken

Version 1.7

Release Date: December 7, 2005

Functionality Improvements

  • Added JTSVersion class to provide access to the API version information
  • Added covers and coveredBy predicates to Geometry
  • Added Geometry#buffer(distance, quadSegs, endCapStyle) method to expose buffer end cap styles
  • Added LineString#reverse and MultiLineString#reverse methods
  • Added centre, intersection, translate, expandBy(distance), expandBy(dx, dy) methods to Envelope
  • Added CollectionUtil class for performing operations over collections
  • Added CoordinateArrays comparators
  • Added CoordinateSequence#getDimension
  • Added convenience methods toPoint and toLineString to WKTWriter
  • Added WKB API (WKBReader and WKBWriter classes in com.vividsolutions.jts.io
  • WKTReader has better handling of numeric parsing, including support for scientific notation
  • Added IsValidOp#setSelfTouchingRingFormingHoleValid to allow validating SDE-style polygons
  • Added check for non-closed rings in IsValidOp
  • Added Linear Referencing API (com.vividsolutions.jts.linearref
  • Added LineSequencer class to com.vividsolutions.jts.operation.linemerge
  • Added Subgraph class to com.vividsolutions.jts.planargraph
  • Added isRemoved method to GraphComponent
  • Added ConnectedSubgraphFinder class to com.vividsolutions.jts.planargraph.algorithm
  • Added setVisited, getComponentWithVisitedState, setVisited, getComponentWithVisitedState methods to com.vividsolutions.jts.planargraph.GraphComponent
  • Added classes to perform Snap Rounding (in com.vividsolutions.jts.noding.snapround>
  • Improved buffering speed and robustness by using Snap Rounding
  • Added buffer optimization for results with large numbers of polygons and/or holes
  • Added STRtree#query(Envelope, ItemVisitor) method
  • Added Debug#toLine methods
  • Added ConvexHull(Coordinate[]) constructor

Bug Fixes

  • Fixed decimal formatting in WKTWriter to force a leading 0 in decimal numbers
  • Fixed bug in CoordinateArraySequence#setOrdinate
  • Fixed bug when checking validity of polygon with hole (IsValidOp#checkHolesInShell)
  • Improved correctness of computated intersections in RobustLineIntersector
  • Fixed bugs in CoordinateList.clone (thanks to Matthias Bobzien)
  • Fixed bug in Envelope.equals (thanks to John Cartwright)
  • Fixed PointLocator for LinearRings

Performance Improvements

  • Improved performance for overlay operations (point inclusion, identical edge detection)
  • Improved Convex Hull performance

API Changes

  • Added SpatiaIndex#query(Envelope, ItemVisitor) method signature
  • Added CoordinateSequence#getDimension() method signature
  • Marked GeometryEditor.CoordinateOperation#edit(Geometry, GeometryFactory) method as final, to prevent incorrect use

Semantics Changes

  • CoordinateArraySequence#setOrdinate now checks that the ordinate index is in range

Version 1.6

Release Date: February 3, 2005

API Changes

  • Changed to using CoordinateArraySequence instead of DefaultCoordinateSequence (to provide a more descriptive name).

Semantics Changes

  • PrecisionModel#makePrecise changed to use Symmetric Arithmetic Rounding rather than Banker's Rounding

Functionality Improvements

  • Added ability to enable Debug methods by setting a system property
  • Added getNumGeometries and getGeometryN methods to Geometry class, to make API more uniform
  • Improved API for CoordinateSequence allows more options for improving memory usage and handling custom coordinate storage methods
  • Added PackedCoordinateSequence to provide reduced memory footprint for geometry objects if desired
  • Added optimized spatial predicates for rectangles
  • Added Debug#isDebugging method

Bug Fixes

  • Fixed bug in Geometry#within() short circuiting
  • Fixed bug causing Geometry#isValid to throw IllegalArgumentException for certain kinds of holes with invalid rings
  • Fixed bug causing redundant linestrings to be returned in the result of overlaying polygons containing holes touching their shell.
  • Polygon#getBoundary now returns a LinearRing if the polygon does not have holes

Architecture Changes

  • Removed a proliferation of references to the default CoordinateSequenceFactory

Contributors

  • Andrea Aime

Version 1.5

Release Date: September 22, 2004

This version is upwards compatible with Version 1.4

API Changes

  • None

Semantics Changes

  • None

Functionality Improvements

  • CGAlgorithms#isCCW now handles coordinate lists with repeated points. Also throws an IllegalArgumentException if the input ring does not have 3 distinct points
  • isValid now checks for invalid coordinates (e.g. ones with Nan or infinite numbers)
  • added copyDeep() method to CoordinateArrays
  • added geometry simplification operations DouglasPeuckerSimplifier and TopologyPreservingSimplifier
  • added methods to Quadtree and STRtree to remove items and query using the Visitor pattern

Performance Improvements

  • Added short-circuit tests in geometry named predicates based on envelope tests

Bug Fixes

  • Fixed bugs in Geometry serialization
  • Fixed bug in ValidOp which reported some MultiPolygons with shells nested inside a hole as invalid
  • Fixed bug in buffer which caused buffers of some polygons with small & large holes to not contain any holes
  • Fixed bug in Polygonizer which caused exception if no lines were supplied

Architecture Changes

  • Basic CG algorithm methods made static in the CGAlgorithms class
  • Various utility methods made public in CoordinateArrays class

Documentation

  • More examples provided in com.vividsolutions.jtsexamples package

Version 1.4

Release Date: November 4, 2003

Semantics Changes

  • none

Functionality Improvements

  • Added "LINEARRING" tag to WKT syntax
  • Added GeometryEditor class to allow easy copy/modify of Geometrys
  • Added GeometricShapeFactory class to easily create standard geometric shapes
  • Geometries can now carry arbitrary user-defined data objects (via Geometry#get/setUserData(Object) method)
  • Added CoordinateSequence and CoordinateSequenceFactory interfaces, and default implementations (BasicCoordinateSequence, BasicCoordinateSequenceFactory)
  • Added Geometry#getFactory
  • Added new PrecisionModel type of FLOATING_SINGLE, for rounding to single precision floating point
  • Added DistanceOp#getClosestPoints method, which returns the closest points between two Geometries
  • Added com.vividsolutions.jts.noding package containing classes to perform fast indexed noding of linestrings
  • Added com.vividsolutions.jts.operation.polygonize package containing classes to perform polygonization
  • Added com.vividsolutions.jts.operation.linemerge package containing classes to perform line merging
  • Added SimpleGeometryPrecisionReducer to allow reducing precision of coordinates of a Geometry
  • Added LineSegment#closestPoints method to compute the closest points between two line segments
  • Added MinimumDiameter class to compute minimum diameters of Geometries
  • Added geom.Triangle class to contain algorithms for Triangles
  • BufferOp now allows end cap styles to be specified. Three types are supported: round, butt and square.

Performance Improvements

  • EdgeList now provides a findEqualEdge method which is substantially faster than findEdgeIndex, for large lists
  • Buffering is now faster and much more robust
  • Overlap operations are now more robust

Bug Fixes

  • Envelope#init(Envelope) now handles null Envelopes correctly
  • CoordinateList#add() now correctly ignores the z-value of Coordinates in determining equality
  • Geometry#isValid now correctly handles checking validity of LinearRings
  • Fixed infinite loop bug causing Out Of Memory errors during polygon intersection
  • Geometry#clone now correctly clones the Geometry's Envelope
  • LineIntersector#computeEdgeDistance now correctly computes a non-zero edge distance in certain situations when a fixed precision model was being used and the line segment was a single unit in length
  • Fixed incorrect calculation of depths in DirectedEdgeStar#computeDepths
  • Fixed BufferSubgraph#addReachable to use explicit stack to avoid stack overflow problems
  • Fixed various bugs causing some kinds of buffers to be computed incorrectly

API Changes

  • WKTReader/Writer: changed protected members to private
  • PrecisionModel type is now an object rather than an int
  • ConvexHull API changed to remove requirement to pass in CGAlgorithms object

Code Architecture Changes

  • geom.util package added for utility classes which parse and modify geometries

Documentation

  • More examples provided in com.vividsolutions.jtsexamples package
  • Added JTS Developers Guide

Version 1.3

Release Date: April 4, 2003

Semantics Changes

  • all Geometry methods are now reentrant (thread-safe)
  • Fixed-precision coordinates are now stored in a rounded but non-scaled form. This makes them compatible with non-precise (Floating) coordinates, and simplifies working with precise coordinates directly. Mixed precision models are now supported in Geometry methods; method results are in the more precise of the input precision models.
  • Offsets are no longer supported in the Fixed precision model. This is necessary to allow storing fixed precision coordinates in a non-scaled form. This does not reduce the total precision available, since coordinates are stored in a floating-point format.
  • SRID and Precision Model are no longer checked for equality during Geometry operations. This removes a limitation which provided little semantic benefit.

Functionality Improvements

  • added Geometry.isWithinDistance(Geometry g, double distance) method, to provide optimized proximity queries
  • added Geometry.buffer(double distance, int quadrantSegments) method, allowing control over accuracy of buffer approximation
  • added Geometry.getCentroid() method
  • added Geometry.getInteriorPoint() method, which uses heuristic methods to return a point in the interior of a Geometry
  • GeometryFactory.toGeometryArray now returns null if the argument is null

Performance Improvements

  • Removed unnecessary string construction in EdgeEndStar.propagateSideLabels()
  • Eliminated unnecessary computation of self-intersections in rings during relate and spatial functions. This provides a large increase in speed when working with large rings and polygons. (Note that IsValid still checks for these self-intersections, which are illegal in LinearRings)
  • Add short-circuit code to RobustLineIntersector to detect non-intersections more efficiently

Bug Fixes

  • Fixed ClassCastException occurring in GeometryCollection.getLength()
  • Fixed bug in Edge Intersection insertion (replaced Coordinate#equals with equals2D to ensure that intersection creation is not sensitive to Z-value).
  • Fixed handling LineStrings with too few points in GeometryGraph.addLineString
  • Fixed: was not checking that MultiPolygons don't contain components with too few points.
  • Fixed Envelope.distance() to return correct distance for all envelopes.
  • Fixed a few Geometry methods to make them re-entrant.
  • Fixed CoordinateList.closeRing() to ensure endpoints are not duplicated
  • Fixed CGAlgorithms.signedArea() to use a simpler algorithm which is more robust and faster.
  • Fixed bug preventing validating Rings containing an initial repeated point.

API Changes

  • Added default constructor to WKTReader. It uses the default GeometryFactory
  • Add two static intersects() methods to Envelope, to allow computing intersections with envelopes defined by points only.
  • Dropped BinaryPower; its functionality is provided by DoubleBits in a more robust fashion.
  • Removed a couple of redundant private static methods from Geometry; they have been replaced by methods in CoordinateArrays
  • The Geometry class is now marked as Serializable

Version 1.2

Release Date: 7 October 2002

Semantics Changes

  • JTS now allows Geometrys to have repeated points. All operations will continue to perform as before. This removes a significant incompatibility with the OGC spatial data model.
  • TopologyExceptions may now be thrown by spatial overlay methods. This helps to distinguish between code bugs and known robustness problems. It also provides a machine-readable coordinate for the error location.

Functionality Improvements

  • RobustLineIntersector now uses "normalized" coordinates to maximize the accuracy of intersection computation.
  • Upgraded Quadtree with more robust implementation
  • Replaced IntervalTree with a more robust implementation of BinTree
  • Added STRTree 2-D spatial index, which exhibits better performance than QuadTrees in many situations.
  • Added EnhancePrecisionOp, which uses precisioning enhancing techniques to reduce the number of failure cases due to robustness problems.

Bug Fixes

  • fixed ConvexHull to use TreeSet instead of HashSet for coordinates
  • Fixed isValid for GeometryCollections containing Polygons, which were sometimes erroneously returning a validity failure for correct Geometrys.
  • Fixed bug in LineSegment.distancePointLine() which would return the incorrect distance for a LineSegment with two identical points
  • Improved error handling in CGAlgorithms.isCCW()
  • IsValid now checks for too few points in a geometry component (e.g. due to repeated points in a ring)

API Changes

  • added Stopwatch class
  • added Geometry.getArea() and Geometry.getLength() methods
  • added CGAlgorithms.signedArea() method
  • added methods to LineSegment - closestPoint(), getLength()
  • added CoordinateArrrays and CoordinateLists utility classes
  • Added TopologyValidationError.getErrorType() method
  • Added Envelope#intersects; deprecated Envelope#overlaps.
  • Added Geometry#geometryChanged() method to allow signaling when Geometry coordinates have been mutated by a client class
  • Added STRTree class implementing a Sort-Tile-Recursive spatial index (a variant of a packed R-tree)
  • Deleted IntervalTree 1-D spatial index (replaced by BinTree)
  • Add BinTree 1-D spatial index

Version 1.1.1

Release Date: 9 April 2002

Bug Fixes

  • fixed decimal-point symbol localization bug in WKTWriter
  • fixed bug in Envelope.int(Envelope env)
  • fixed filename case of SFSMultiLineString.java and IntervalTree.java

API Changes

  • deleted TopologyException class
  • renamed CGAlgorithms.isPointInPolygon to isPointInRing (a more accurate description of what the method computes)

API Additions

  • added Geometry.getCoordinate() method
  • added Geometry.distance() method
  • added GeometryComponentFilter interface and Geometry.apply(GeometryComponentFilter) method

Version 1.1

Release Date: 28 March 2002

New Features

  • added Geometry.isSimple() and Geometry.isValid() methods
  • improved design of topological data structures
  • added Geometry.setSRID() method
  • improved functionality of the Envelope class
  • added ability to write to an arbitrary java.io.Writer object to WKTWriter
  • added Validate and Mark Location functionality to TestBuilder

Version 1.0

Release Date: 1 February 2002
  • Removed some non-compatibilities with Java 1.1
  • Fixed bug in constructing buffer outline around inside of angles
  • In TestBuilder vertices are now displayed with fixed size in view units
  • Improved code for WKTWriter.writeFormatted()
  • Fixed bug in constructor for LinearRing
  • Improved implementation of sweepline intersection algorithm to avoid use of dynamic set.
  • Fixed bug in ConvexHull.cleanRing()
  • Refactored RobustLineIntersector and NonRobustLineIntersector

Version 0.0

Release Date: 30 May 2001

Baseline version jts-1.11/src/0000755000000000000000000000000011343017562011523 5ustar rootrootjts-1.11/src/com/0000755000000000000000000000000011343017562012301 5ustar rootrootjts-1.11/src/com/vividsolutions/0000755000000000000000000000000011343017562015402 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/0000755000000000000000000000000011343017562016202 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/io/0000755000000000000000000000000011343017562016611 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/io/gml2/0000755000000000000000000000000011343017562017452 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/io/gml2/GeometryStrategies.java0000644000000000000000000004214011343017562024144 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io.gml2; import java.util.*; import java.util.regex.Pattern; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.io.gml2.GMLHandler.Handler; /** * Container for GML2 Geometry parsing strategies which can be represented in JTS. * * @author David Zwiers, Vivid Solutions. */ public class GeometryStrategies{ /** * This set of strategies is not expected to be used directly outside of this distribution. * * The implementation of this class are intended to be used as static function points in C. These strategies should be associated with an element when the element begins. The strategy is utilized at the end of the element to create an object of value to the user. * * In this case all the objects are either java.lang.* or JTS Geometry objects * * @author David Zwiers, Vivid Solutions. */ static interface ParseStrategy{ /** * @param arg Value to interpret * @param gf GeometryFactory * @return The interpreted value * @throws SAXException */ Object parse(Handler arg, GeometryFactory gf) throws SAXException; } private static HashMap strategies = loadStrategies(); private static HashMap loadStrategies(){ HashMap strats = new HashMap(); // point strats.put(GMLConstants.GML_POINT.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()!=1) throw new SAXException("Cannot create a point without exactly one coordinate"); int srid = getSrid(arg.attrs,gf.getSRID()); Object c = arg.children.get(0); Point p = null; if(c instanceof Coordinate){ p = gf.createPoint((Coordinate)c); }else{ p = gf.createPoint((CoordinateSequence)c); } if(p.getSRID()!=srid) p.setSRID(srid); return p; } }); // linestring strats.put(GMLConstants.GML_LINESTRING.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence"); int srid = getSrid(arg.attrs,gf.getSRID()); LineString ls = null; if(arg.children.size() == 1){ // coord set try{ CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); ls = gf.createLineString(cs); }catch(ClassCastException e){ throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e); } }else{ try{ Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]); ls = gf.createLineString(coords); }catch(ClassCastException e){ throw new SAXException("Cannot create a linestring without atleast two coordinates or one coordinate sequence",e); } } if(ls.getSRID()!=srid) ls.setSRID(srid); return ls; } }); // linearring strats.put(GMLConstants.GML_LINEARRING.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()!=1 && arg.children.size()<4) throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence"); int srid = getSrid(arg.attrs,gf.getSRID()); LinearRing ls = null; if(arg.children.size() == 1){ // coord set try{ CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); ls = gf.createLinearRing(cs); }catch(ClassCastException e){ throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e); } }else{ try{ Coordinate[] coords = (Coordinate[]) arg.children.toArray(new Coordinate[arg.children.size()]); ls = gf.createLinearRing(coords); }catch(ClassCastException e){ throw new SAXException("Cannot create a linear ring without atleast four coordinates or one coordinate sequence",e); } } if(ls.getSRID()!=srid) ls.setSRID(srid); return ls; } }); // polygon strats.put(GMLConstants.GML_POLYGON.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a polygon without atleast one linear ring"); int srid = getSrid(arg.attrs,gf.getSRID()); LinearRing outer = (LinearRing) arg.children.get(0); // will be the first List t = arg.children.size()>1?arg.children.subList(1,arg.children.size()):null; LinearRing[] inner = t==null?null:(LinearRing[]) t.toArray(new LinearRing[t.size()]); Polygon p = gf.createPolygon(outer,inner); if(p.getSRID()!=srid) p.setSRID(srid); return p; } }); // box strats.put(GMLConstants.GML_BOX.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1 || arg.children.size()>2) throw new SAXException("Cannot create a box without either two coords or one coordinate sequence"); // int srid = getSrid(arg.attrs,gf.getSRID()); Envelope box = null; if(arg.children.size() == 1){ CoordinateSequence cs = (CoordinateSequence) arg.children.get(0); box = cs.expandEnvelope(new Envelope()); }else{ box = new Envelope((Coordinate)arg.children.get(0),(Coordinate)arg.children.get(1)); } return box; } }); // multi-point strats.put(GMLConstants.GML_MULTI_POINT.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a multi-point without atleast one point"); int srid = getSrid(arg.attrs,gf.getSRID()); Point[] pts = (Point[]) arg.children.toArray(new Point[arg.children.size()]); MultiPoint mp = gf.createMultiPoint(pts); if(mp.getSRID()!=srid) mp.setSRID(srid); return mp; } }); // multi-linestring strats.put(GMLConstants.GML_MULTI_LINESTRING.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a multi-linestring without atleast one linestring"); int srid = getSrid(arg.attrs,gf.getSRID()); LineString[] lns = (LineString[]) arg.children.toArray(new LineString[arg.children.size()]); MultiLineString mp = gf.createMultiLineString(lns); if(mp.getSRID()!=srid) mp.setSRID(srid); return mp; } }); // multi-poly strats.put(GMLConstants.GML_MULTI_POLYGON.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a multi-polygon without atleast one polygon"); int srid = getSrid(arg.attrs,gf.getSRID()); Polygon[] plys = (Polygon[]) arg.children.toArray(new Polygon[arg.children.size()]); MultiPolygon mp = gf.createMultiPolygon(plys); if(mp.getSRID()!=srid) mp.setSRID(srid); return mp; } }); // multi-geom strats.put(GMLConstants.GML_MULTI_GEOMETRY.toLowerCase(),new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.children.size()<1) throw new SAXException("Cannot create a multi-polygon without atleast one geometry"); Geometry[] geoms = (Geometry[]) arg.children.toArray(new Geometry[arg.children.size()]); GeometryCollection gc = gf.createGeometryCollection(geoms); return gc; } }); // coordinates strats.put(GMLConstants.GML_COORDINATES.toLowerCase(),new ParseStrategy(){ private WeakHashMap patterns = new WeakHashMap(); public Object parse(Handler arg, GeometryFactory gf) throws SAXException { // one child, either a coord // or a coordinate sequence if(arg.text == null || "".equals(arg.text)) throw new SAXException("Cannot create a coordinate sequence without text to parse"); String decimal = "."; String coordSeperator = ","; String toupleSeperator = " "; // get overides from coordinates if(arg.attrs.getIndex("decimal")>=0) decimal = arg.attrs.getValue("decimal"); else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"decimal")>=0) decimal = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"decimal"); if(arg.attrs.getIndex("cs")>=0) coordSeperator = arg.attrs.getValue("cs"); else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"cs")>=0) coordSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"cs"); if(arg.attrs.getIndex("ts")>=0) toupleSeperator = arg.attrs.getValue("ts"); else if(arg.attrs.getIndex(GMLConstants.GML_NAMESPACE,"ts")>=0) toupleSeperator = arg.attrs.getValue(GMLConstants.GML_NAMESPACE,"ts"); // now to start parse String t = arg.text.toString(); t = t.replaceAll("\\s"," "); Pattern ptn = (Pattern) patterns.get(toupleSeperator); if(ptn == null){ String ts = new String(toupleSeperator); if(ts.indexOf('\\')>-1){ // need to escape it ts = ts.replaceAll("\\","\\\\"); } if(ts.indexOf('.')>-1){ // need to escape it ts = ts.replaceAll("\\.","\\\\."); } ptn = Pattern.compile(ts); patterns.put(toupleSeperator,ptn); } String[] touples = ptn.split(t.trim());// t.trim().split(toupleSeperator); if(touples.length == 0) throw new SAXException("Cannot create a coordinate sequence without a touple to parse"); // we may have null touples, so calculate the num first int numNonNullTouples = 0; for(int i=0;i-1){ // need to escape it ts = ts.replaceAll("\\","\\\\"); } if(ts.indexOf('.')>-1){ // need to escape it ts = ts.replaceAll("\\.","\\\\."); } ptn = Pattern.compile(ts); patterns.put(coordSeperator,ptn); } String[] coords = ptn.split(touples[i]);// touples[i].split(coordSeperator); int dimIndex = 0; for(int j=0;j3) throw new SAXException("Cannot create a coordinate with more than 3 axis"); Double[] axis = (Double[]) arg.children.toArray(new Double[arg.children.size()]); Coordinate c = new Coordinate(); c.x = axis[0].doubleValue(); if(axis.length>1) c.y = axis[1].doubleValue(); if(axis.length>2) c.z = axis[2].doubleValue(); return c; } }); ParseStrategy coord_child = new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { if(arg.text == null) return null; return new Double((arg.text.toString())); } }; // coord-x strats.put(GMLConstants.GML_COORD_X.toLowerCase(),coord_child); // coord-y strats.put(GMLConstants.GML_COORD_Y.toLowerCase(),coord_child); // coord-z strats.put(GMLConstants.GML_COORD_Z.toLowerCase(),coord_child); ParseStrategy member = new ParseStrategy(){ public Object parse(Handler arg, GeometryFactory gf) throws SAXException { if(arg.children.size()!=1) throw new SAXException("Geometry Members may only contain one geometry."); // type checking will occur in the parent geom collection. // may wish to add this in the future return arg.children.get(0); } }; // outerBoundary - linear ring member strats.put(GMLConstants.GML_OUTER_BOUNDARY_IS.toLowerCase(),member); // innerBoundary - linear ring member strats.put(GMLConstants.GML_INNER_BOUNDARY_IS.toLowerCase(),member); // point member strats.put(GMLConstants.GML_POINT_MEMBER.toLowerCase(),member); // line string member strats.put(GMLConstants.GML_LINESTRING_MEMBER.toLowerCase(),member); // polygon member strats.put(GMLConstants.GML_POLYGON_MEMBER.toLowerCase(),member); return strats; } static int getSrid(Attributes attrs, int defaultValue){ String srs = null; if(attrs.getIndex(GMLConstants.GML_ATTR_SRSNAME)>=0) srs = attrs.getValue(GMLConstants.GML_ATTR_SRSNAME); else if(attrs.getIndex(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME)>=0) srs = attrs.getValue(GMLConstants.GML_NAMESPACE,GMLConstants.GML_ATTR_SRSNAME); if(srs != null){ srs = srs.trim(); if(srs != null && !"".equals(srs)){ try{ return Integer.parseInt(srs); }catch(NumberFormatException e){ // rip out the end, uri's are used here sometimes int index = srs.lastIndexOf('#'); if(index > -1) srs = srs.substring(index); try{ return Integer.parseInt(srs); }catch(NumberFormatException e2){ // ignore } } } } return defaultValue; } /** * @param uri Not currently used, included for future work * @param localName Used to look up an appropriate parse strategy * @return The ParseStrategy which should be employed * * @see ParseStrategy */ public static ParseStrategy findStrategy(String uri,String localName){ return localName == null?null:(ParseStrategy) strategies.get(localName.toLowerCase()); } } jts-1.11/src/com/vividsolutions/jts/io/gml2/GMLConstants.java0000644000000000000000000000564011343017562022636 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io.gml2; /** * Various constant strings associated with GML format. */ final public class GMLConstants{ // Namespace constants public static final String GML_NAMESPACE = "http://www.opengis.net/gml"; public static final String GML_PREFIX = "gml"; // Source Coordinate System public static final String GML_ATTR_SRSNAME = "srsName"; // GML associative types public static final String GML_GEOMETRY_MEMBER = "geometryMember"; public static final String GML_POINT_MEMBER = "pointMember"; public static final String GML_POLYGON_MEMBER = "polygonMember"; public static final String GML_LINESTRING_MEMBER = "lineStringMember"; public static final String GML_OUTER_BOUNDARY_IS = "outerBoundaryIs"; public static final String GML_INNER_BOUNDARY_IS = "innerBoundaryIs"; // Primitive Geometries public static final String GML_POINT = "Point"; public static final String GML_LINESTRING = "LineString"; public static final String GML_LINEARRING = "LinearRing"; public static final String GML_POLYGON = "Polygon"; public static final String GML_BOX = "Box"; // Aggregate Ggeometries public static final String GML_MULTI_GEOMETRY = "MultiGeometry"; public static final String GML_MULTI_POINT = "MultiPoint"; public static final String GML_MULTI_LINESTRING = "MultiLineString"; public static final String GML_MULTI_POLYGON = "MultiPolygon"; // Coordinates public static final String GML_COORDINATES = "coordinates"; public static final String GML_COORD = "coord"; public static final String GML_COORD_X = "X"; public static final String GML_COORD_Y = "Y"; public static final String GML_COORD_Z = "Z"; }jts-1.11/src/com/vividsolutions/jts/io/gml2/GMLHandler.java0000644000000000000000000002043711343017562022240 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io.gml2; import java.util.*; import org.xml.sax.*; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.io.gml2.GeometryStrategies.ParseStrategy; /** * A SAX {@link DefaultHandler} which builds {@link Geometry}s * from GML2-formatted geometries. * An XML parser can delegate SAX events to this handler * to parse and building Geometrys. *

* This handler currently ignores both namespaces and prefixes. * * Hints: *

    *
  • If your parent handler is a DefaultHandler register the parent handler to receive the errors and locator calls. *
  • Use {@link GeometryStrategies#findStrategy(String, String)} to help check for applicability *
* * @see DefaultHandler * * @author David Zwiers, Vivid Solutions. */ public class GMLHandler extends DefaultHandler { /** * This class is intended to log the SAX acitivity within a given element until its termination. * At this time, a new object of value is created and passed to the parent. * An object of value is typically either java.lang.* or a JTS Geometry * This class is not intended for use outside this distribution, * and may change in subsequent versions. * * @author David Zwiers, Vivid Solutions. */ static class Handler { protected Attributes attrs = null; protected ParseStrategy strategy; /** * @param strategy * @param attributes Nullable */ public Handler(ParseStrategy strategy, Attributes attributes) { if (attributes != null) this.attrs = new AttributesImpl(attributes); this.strategy = strategy; } protected StringBuffer text = null; /** * Caches text for the future * @param str */ public void addText(String str) { if (text == null) text = new StringBuffer(); text.append(str); } protected List children = null; /** * Store param for the future * * @param obj */ public void keep(Object obj) { if (children == null) children = new LinkedList(); children.add(obj); } /** * @param gf GeometryFactory * @return Parsed Object * @throws SAXException */ public Object create(GeometryFactory gf) throws SAXException { return strategy.parse(this, gf); } } private Stack stack = new Stack(); private ErrorHandler delegate = null; private GeometryFactory gf = null; /** * Creates a new handler. * Allows the user to specify a delegate object for error / warning messages. * If the delegate also implements ContentHandler then the document Locator will be passed on. * * @param gf Geometry Factory * @param delegate Nullable * * @see ErrorHandler * @see ContentHandler * @see ContentHandler#setDocumentLocator(org.xml.sax.Locator) * @see org.xml.sax.Locator * */ public GMLHandler(GeometryFactory gf, ErrorHandler delegate) { this.delegate = delegate; this.gf = gf; stack.push(new Handler(null, null)); } /** * Tests whether this handler has completed parsing * a geometry. * If this is the case, {@link getGeometry()} can be called * to get the value of the parsed geometry. * * @return */ public boolean isGeometryComplete() { if (stack.size() > 1) return false; // top level node on stack needs to have at least one child Handler h = (Handler) stack.peek(); if (h.children.size() < 1) return false; return true; } /** * Gets the geometry parsed by this handler. * This method should only be called AFTER the parser has completed execution * * @return the parsed Geometry, or a GeometryCollection if more than one geometry was parsed * @throws IllegalStateException if called before the parse is complete */ public Geometry getGeometry() { if (stack.size() == 1) { Handler h = (Handler) stack.peek(); if (h.children.size() == 1) return (Geometry) h.children.get(0); return gf.createGeometryCollection( (Geometry[]) h.children.toArray(new Geometry[stack.size()])); } throw new IllegalStateException( "Parse did not complete as expected, there are " + stack.size() + " elements on the Stack"); } ////////////////////////////////////////////// // Parsing Methods /** * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) */ public void characters(char[] ch, int start, int length) throws SAXException { if (!stack.isEmpty()) ((Handler) stack.peek()).addText(new String(ch, start, length)); } /** * @see org.xml.sax.helpers.DefaultHandler#ignorableWhitespace(char[], int, int) */ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { if (!stack.isEmpty()) ((Handler) stack.peek()).addText(" "); } /** * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String) */ public void endElement(String uri, String localName, String qName) throws SAXException { Handler thisAction = (Handler) stack.pop(); ((Handler) stack.peek()).keep(thisAction.create(gf)); } /** * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // create a handler ParseStrategy ps = GeometryStrategies.findStrategy(uri, localName); if (ps == null) { String qn = qName.substring(qName.indexOf(':') + 1, qName.length()); ps = GeometryStrategies.findStrategy(null, qn); } Handler h = new Handler(ps, attributes); // and add it to the stack stack.push(h); } ////////////////////////////////////////////// // Logging Methods /** * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator) */ public void setDocumentLocator(Locator locator) { this.locator = locator; if (delegate != null && delegate instanceof ContentHandler) ((ContentHandler) delegate).setDocumentLocator(locator); } private Locator locator = null; protected Locator getDocumentLocator() { return locator; } ////////////////////////////////////////////// // ERROR Methods /** * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException) */ public void fatalError(SAXParseException e) throws SAXException { if (delegate != null) delegate.fatalError(e); else super.fatalError(e); } /** * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException) */ public void error(SAXParseException e) throws SAXException { if (delegate != null) delegate.error(e); else super.error(e); } /** * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException) */ public void warning(SAXParseException e) throws SAXException { if (delegate != null) delegate.warning(e); else super.warning(e); } } jts-1.11/src/com/vividsolutions/jts/io/gml2/GMLReader.java0000644000000000000000000001103611343017562022060 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io.gml2; import java.io.*; import javax.xml.parsers.*; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; /** * Reads a GML2 geometry from an XML fragment into a {@link Geometry}. *

* An example of the GML2 format handled is: *

 *   
 *  	24824.045318333192,38536.15071012041
 *  		26157.378651666528,37567.42733944659 26666.666,36000.0
 *  		26157.378651666528,34432.57266055341
 *  		24824.045318333192,33463.84928987959
 *  		23175.954681666804,33463.84928987959
 *  		21842.621348333472,34432.57266055341 21333.333,36000.0
 *  		21842.621348333472,37567.42733944659
 *  		23175.954681666808,38536.15071012041 
 *  
 * 
* * The reader ignores namespace prefixes, * and disables both the validation and namespace options on the SAXParser. * This class requires the presence of a SAX Parser available via the * {@link javax.xml.parsers.SAXParserFactory#newInstance()} * method. *

* A specification of the GML XML format * can be found at the OGC web site: http://www.opengeospatial.org/. *

* It is the caller's responsibility to ensure that the supplied {@link PrecisionModel} * matches the precision of the incoming data. * If a lower precision for the data is required, a subsequent * process must be run on the data to reduce its precision. *

* To parse and build geometry directly from a SAX stream, see {@link GMLHandler}. * * @author David Zwiers, Vivid Solutions. * * @see GMLHandler */ public class GMLReader { /** * Reads a GML2 Geometry from a String into a single {@link Geometry} * * If a collection of geometries is found, a {@link GeometryCollection} is returned. * * @param gml The GML String to parse * @param geometryFactory When null, a default will be used. * @return the resulting JTS Geometry * * @throws ParserConfigurationException * @throws IOException * @throws SAXException * * @see #read(Reader, GeometryFactory) */ public Geometry read(String gml, GeometryFactory geometryFactory) throws SAXException, IOException, ParserConfigurationException{ return read(new StringReader(gml),geometryFactory); } /** * Reads a GML2 Geometry from a {@link Reader} into a single {@link Geometry} * * If a collection of Geometries is found, a {@link GeometryCollection} is returned. * * @param reader The input source * @param geometryFactory When null, a default will be used. * @return The resulting JTS Geometry * @throws SAXException * @throws IOException */ public Geometry read(Reader reader, GeometryFactory geometryFactory) throws SAXException, IOException, ParserConfigurationException{ SAXParserFactory fact = SAXParserFactory.newInstance(); fact.setNamespaceAware(false); fact.setValidating(false); SAXParser parser = fact.newSAXParser(); if(geometryFactory == null) geometryFactory = new GeometryFactory(); GMLHandler gh = new GMLHandler(geometryFactory,null); parser.parse(new InputSource(reader), (DefaultHandler)gh); return gh.getGeometry(); } } jts-1.11/src/com/vividsolutions/jts/io/gml2/GMLWriter.java0000644000000000000000000003546511343017562022146 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io.gml2; import java.io.*; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.util.Assert; /** * Writes {@link Geometry}s as XML fragments in GML2 format. * Allows specifying the XML prefix, namespace and srsName * of the emitted GML. * Also allows adding custom root elements * to support GML extensions such as KML. * With appropriate settings for prefix (none) and custom root elements * this class can be used to write out geometry in KML format. *

* An example of the output that can be generated is: * *

 * 
 *   
 *     6.03,8.17 7.697,6.959 8.333,5.0 7.697,3.041 6.03,1.83 3.97,1.83 2.303,3.041 1.667,5.0 2.303,6.959 3.97,8.17 
 *   
 * 
 * 
* *

* This class does not rely on any external XML libraries. * * @author David Zwiers, Vivid Solutions * @author Martin Davis */ public class GMLWriter { private final String INDENT = " "; private int startingIndentIndex = 0; private int maxCoordinatesPerLine = 10; private boolean emitNamespace = false; private boolean isRootTag = false; private String prefix = GMLConstants.GML_PREFIX; private String namespace = GMLConstants.GML_NAMESPACE; private String srsName = null; private String[] customElements = null; /** * Creates a writer which outputs GML with default settings. * The defaults are: *

    *
  • the namespace prefix is gml: *
  • no namespace prefix declaration is written *
  • no srsName attribute is written *
*/ public GMLWriter() { } /** * Creates a writer which may emit the GML namespace prefix * declaration in the geometry root element. * * @param emitNamespace trueif the GML namespace prefix declaration should be written * in the geometry root element */ public GMLWriter(boolean emitNamespace) { this.setNamespace(emitNamespace); } /** * Specifies the namespace prefix to write on each GML tag. * A null or blank prefix may be used to indicate no prefix. *

* The default is to write gml: as the namespace prefix. * * @param prefix the namespace prefix to use (null or blank if none) */ public void setPrefix(String prefix) { this.prefix = prefix; } /** * Sets the value of the srsName attribute * to be written into the root geometry tag. * If the value is null or blank no srsName attribute will be written. * The provided value must be a valid XML attribute value * - it will not be XML-escaped. *

* The default is not to write the srsName attribute. * * @param srsName the srsName attribute value */ public void setSrsName(String srsName) { this.srsName = srsName; } /** * Determines whether a GML namespace declaration will be written in the * opening tag of geometries. Useful in XML-aware environments which * parse the geometries before use, such as XSLT. * * @param namespaceMode true if the GML namespace prefix declaration * should be written in the root geometry element */ public void setNamespace(boolean emitNamespace) { this.emitNamespace = emitNamespace; } /** * Specifies a list of custom elements * which are written after the opening tag * of the root element. * The text contained in the string sequence should form valid XML markup. * The specified strings are written one per line immediately after * the root geometry tag line. *

* For instance, this is useful for adding KML-specific geometry parameters * such as <extrude> * * @param customElements a list of the custom element strings, or null if none */ public void setCustomElements(String[] customElements) { this.customElements = customElements; } /** * Sets the starting column index for pretty printing * * @param arg */ public void setStartingIndentIndex(int indent) { if (indent < 0) indent = 0; startingIndentIndex = indent; } /** * Sets the number of coordinates printed per line. * * @param arg */ public void setMaxCoordinatesPerLine(int num) { if (num < 1) throw new IndexOutOfBoundsException( "Invalid coordinate count per line, must be > 0"); maxCoordinatesPerLine = num; } /** * Writes a {@link Geometry} in GML2 format to a String. * * @param geom * @return String GML2 Encoded Geometry * @throws IOException */ public String write(Geometry geom) { StringWriter writer = new StringWriter(); try { write(geom, writer); } catch (IOException ex) { Assert.shouldNeverReachHere(); } return writer.toString(); } /** * Writes a {@link Geometry} in GML2 format into a {@link Writer}. * * @param geom Geometry to encode * @param writer Stream to encode to. * @throws IOException */ public void write(Geometry geom, Writer writer) throws IOException { write(geom, writer, startingIndentIndex); } private void write(Geometry geom, Writer writer, int level) throws IOException { isRootTag = true; if (geom instanceof Point) { writePoint((Point) geom, writer, level); } else if (geom instanceof LineString) { writeLineString((LineString) geom, writer, level); } else if (geom instanceof Polygon) { writePolygon((Polygon) geom, writer, level); } else if (geom instanceof MultiPoint) { writeMultiPoint((MultiPoint) geom, writer, level); } else if (geom instanceof MultiLineString) { writeMultiLineString((MultiLineString) geom, writer, level); } else if (geom instanceof MultiPolygon) { writeMultiPolygon((MultiPolygon) geom, writer, level); } else if (geom instanceof GeometryCollection) { writeGeometryCollection((GeometryCollection) geom, writer, startingIndentIndex); } else { throw new IllegalArgumentException("Unhandled geometry type: " + geom.getGeometryType()); } writer.flush(); } // 1195156.78946687,382069.533723461 private void writePoint(Point p, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_POINT, p, writer); write(new Coordinate[] { p.getCoordinate() }, writer, level + 1); startLine(level, writer); endGeomTag(GMLConstants.GML_POINT, writer); } //1195123.37289257,381985.763974674 1195120.22369473,381964.660533343 1195118.14929823,381942.597718511 private void writeLineString(LineString ls, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_LINESTRING, ls, writer); write(ls.getCoordinates(), writer, level + 1); startLine(level, writer); endGeomTag(GMLConstants.GML_LINESTRING, writer); } //1226890.26761027,1466433.47430292 1226880.59239079,1466427.03208053...> private void writeLinearRing(LinearRing lr, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_LINEARRING, lr, writer); write(lr.getCoordinates(), writer, level + 1); startLine(level, writer); endGeomTag(GMLConstants.GML_LINEARRING, writer); } private void writePolygon(Polygon p, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_POLYGON, p, writer); startLine(level + 1, writer); startGeomTag(GMLConstants.GML_OUTER_BOUNDARY_IS, null, writer); writeLinearRing((LinearRing) p.getExteriorRing(), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_OUTER_BOUNDARY_IS, writer); for (int t = 0; t < p.getNumInteriorRing(); t++) { startLine(level + 1, writer); startGeomTag(GMLConstants.GML_INNER_BOUNDARY_IS, null, writer); writeLinearRing((LinearRing) p.getInteriorRingN(t), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_INNER_BOUNDARY_IS, writer); } startLine(level, writer); endGeomTag(GMLConstants.GML_POLYGON, writer); } private void writeMultiPoint(MultiPoint mp, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_MULTI_POINT, mp, writer); for (int t = 0; t < mp.getNumGeometries(); t++) { startLine(level + 1, writer); startGeomTag(GMLConstants.GML_POINT_MEMBER, null, writer); writePoint((Point) mp.getGeometryN(t), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_POINT_MEMBER, writer); } startLine(level, writer); endGeomTag(GMLConstants.GML_MULTI_POINT, writer); } private void writeMultiLineString(MultiLineString mls, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_MULTI_LINESTRING, mls, writer); for (int t = 0; t < mls.getNumGeometries(); t++) { startLine(level + 1, writer); startGeomTag(GMLConstants.GML_LINESTRING_MEMBER, null, writer); writeLineString((LineString) mls.getGeometryN(t), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_LINESTRING_MEMBER, writer); } startLine(level, writer); endGeomTag(GMLConstants.GML_MULTI_LINESTRING, writer); } private void writeMultiPolygon(MultiPolygon mp, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_MULTI_POLYGON, mp, writer); for (int t = 0; t < mp.getNumGeometries(); t++) { startLine(level + 1, writer); startGeomTag(GMLConstants.GML_POLYGON_MEMBER, null, writer); writePolygon((Polygon) mp.getGeometryN(t), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_POLYGON_MEMBER, writer); } startLine(level, writer); endGeomTag(GMLConstants.GML_MULTI_POLYGON, writer); } private void writeGeometryCollection(GeometryCollection gc, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_MULTI_GEOMETRY, gc, writer); for (int t = 0; t < gc.getNumGeometries(); t++) { startLine(level + 1, writer); startGeomTag(GMLConstants.GML_GEOMETRY_MEMBER, null, writer); write(gc.getGeometryN(t), writer, level + 2); startLine(level + 1, writer); endGeomTag(GMLConstants.GML_GEOMETRY_MEMBER, writer); } startLine(level, writer); endGeomTag(GMLConstants.GML_MULTI_GEOMETRY, writer); } private static final String coordinateSeparator = ","; private static final String tupleSeparator = " "; /** * Takes a list of coordinates and converts it to GML.
* 2d and 3d aware. * * @param coords array of coordinates * @throws IOException */ private void write(Coordinate[] coords, Writer writer, int level) throws IOException { startLine(level, writer); startGeomTag(GMLConstants.GML_COORDINATES, null, writer); int dim = 2; if (coords.length > 0) { if (!(Double.isNaN(coords[0].z))) dim = 3; } boolean isNewLine = true; for (int i = 0; i < coords.length; i++) { if (isNewLine) { startLine(level + 1, writer); isNewLine = false; } if (dim == 2) { writer.write("" + coords[i].x); writer.write(coordinateSeparator); writer.write("" + coords[i].y); } else if (dim == 3) { writer.write("" + coords[i].x); writer.write(coordinateSeparator); writer.write("" + coords[i].y); writer.write(coordinateSeparator); writer.write("" + coords[i].z); } writer.write(tupleSeparator); // break output lines to prevent them from getting too long if ((i + 1) % maxCoordinatesPerLine == 0 && i < coords.length - 1) { writer.write("\n"); isNewLine = true; } } if (!isNewLine) writer.write("\n"); startLine(level, writer); endGeomTag(GMLConstants.GML_COORDINATES, writer); } private void startLine(int level, Writer writer) throws IOException { for (int i = 0; i < level; i++) writer.write(INDENT); } private void startGeomTag(String geometryName, Geometry g, Writer writer) throws IOException { writer.write("<" + ((prefix == null || "".equals(prefix)) ? "" : prefix + ":")); writer.write(geometryName); writeAttributes(g, writer); writer.write(">\n"); writeCustomElements(g, writer); isRootTag = false; } private void writeAttributes(Geometry geom, Writer writer) throws IOException { if (geom == null) return; if (! isRootTag) return; if (emitNamespace) { writer.write(" xmlns" + ((prefix == null || "".equals(prefix)) ? "" : ":"+prefix ) + "='" + namespace + "'"); } if (srsName != null && srsName.length() > 0) { writer.write(" " + GMLConstants.GML_ATTR_SRSNAME + "='" + srsName + "'"); // MD - obsoleted // writer.write(geom.getSRID() + ""); } } private void writeCustomElements(Geometry geom, Writer writer) throws IOException { if (geom == null) return; if (! isRootTag) return; if (customElements == null) return; for (int i = 0; i < customElements.length; i++) { writer.write(customElements[i]); writer.write("\n"); } } private void endGeomTag(String geometryName, Writer writer) throws IOException { writer.write("\n"); } private String prefix() { if (prefix == null || prefix.length() == 0) return ""; return prefix + ":"; } } jts-1.11/src/com/vividsolutions/jts/io/gml2/package.html0000644000000000000000000000024011343017562021727 0ustar rootroot JTS IO: Java Topology Suite IO Library Classes to read and write the GML2 geometry format. jts-1.11/src/com/vividsolutions/jts/io/ByteOrderDataInStream.java0000644000000000000000000000530011343017562023606 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.IOException; /** * Allows reading a stream of Java primitive datatypes from an underlying * {@link InStream}, * with the representation being in either common byte ordering. */ public class ByteOrderDataInStream { private int byteOrder = ByteOrderValues.BIG_ENDIAN; private InStream stream; // buffers to hold primitive datatypes private byte[] buf1 = new byte[1]; private byte[] buf4 = new byte[4]; private byte[] buf8 = new byte[8]; public ByteOrderDataInStream() { this.stream = null; } public ByteOrderDataInStream(InStream stream) { this.stream = stream; } /** * Allows a single ByteOrderDataInStream to be reused * on multiple InStreams. * * @param stream */ public void setInStream(InStream stream) { this.stream = stream; } public void setOrder(int byteOrder) { this.byteOrder = byteOrder; } /** * * * @return */ public byte readByte() throws IOException { stream.read(buf1); return buf1[0]; } public int readInt() throws IOException { stream.read(buf4); return ByteOrderValues.getInt(buf4, byteOrder); } public long readLong() throws IOException { stream.read(buf8); return ByteOrderValues.getLong(buf8, byteOrder); } public double readDouble() throws IOException { stream.read(buf8); return ByteOrderValues.getDouble(buf8, byteOrder); } } jts-1.11/src/com/vividsolutions/jts/io/WKBConstants.java0000644000000000000000000000304711343017562022000 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; /** * Constant values used by the WKB format */ public interface WKBConstants { int wkbXDR = 0; int wkbNDR = 1; int wkbPoint = 1; int wkbLineString = 2; int wkbPolygon = 3; int wkbMultiPoint = 4; int wkbMultiLineString = 5; int wkbMultiPolygon = 6; int wkbGeometryCollection = 7; } jts-1.11/src/com/vividsolutions/jts/io/WKTReader.java0000644000000000000000000006452311343017562021256 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.util.*; import com.vividsolutions.jts.io.ParseException; import java.io.IOException; import java.io.Reader; import java.io.StreamTokenizer; import java.io.StringReader; import java.util.ArrayList; /** * Converts a geometry in Well-Known Text format to a {@link Geometry}. *

* WKTReader supports * extracting Geometry objects from either {@link Reader}s or * {@link String}s. This allows it to function as a parser to read Geometry * objects from text blocks embedded in other data formats (e.g. XML).

*

* A WKTReader is parameterized by a GeometryFactory, * to allow it to create Geometry objects of the appropriate * implementation. In particular, the GeometryFactory * determines the PrecisionModel and SRID that is * used.

* * The WKTReader converts all input numbers to the precise * internal representation. * *

Notes:

*
    *
  • The reader supports non-standard "LINEARRING" tags. *
  • The reader uses Double.parseDouble to perform the conversion of ASCII * numbers to floating point. This means it supports the Java * syntax for floating point literals (including scientific notation). *
* *

Syntax

* The following syntax specification describes the version of Well-Known Text * supported by JTS. * (The specification uses a syntax language similar to that used in * the C and Java language specifications.) *

* *

 * WKTGeometry: one of
 *
 *       WKTPoint  WKTLineString  WKTLinearRing  WKTPolygon
 *       WKTMultiPoint  WKTMultiLineString  WKTMultiPolygon
 *       WKTGeometryCollection
 *
 * WKTPoint: POINT ( Coordinate )
 *
 * WKTLineString: LINESTRING CoordinateSequence
 *
 * WKTLinearRing: LINEARRING CoordinateSequence
 *
 * WKTPolygon: POLYGON CoordinateSequenceList
 *
 * WKTMultiPoint: MULTIPOINT CoordinateSingletonList
 *
 * WKTMultiLineString: MULTILINESTRING CoordinateSequenceList
 *
 * WKTMultiPolygon:
 *         MULTIPOLYGON ( CoordinateSequenceList { , CoordinateSequenceList } )
 *
 * WKTGeometryCollection: 
 *         GEOMETRYCOLLECTION ( WKTGeometry { , WKTGeometry } )
 *
 * CoordinateSingletonList:
 *         ( CoordinateSingleton { , CoordinateSingleton } )
 *         | EMPTY
 *         
 * CoordinateSingleton:
 *         ( Coordinate )
 *         | EMPTY
 *
 * CoordinateSequenceList:
 *         ( CoordinateSequence { , CoordinateSequence } )
 *         | EMPTY
 *
 * CoordinateSequence:
 *         ( Coordinate { , Coordinate } )
 *         | EMPTY
 *
 * Coordinate:
 *         Number Number Numberopt
 *
 * Number: A Java-style floating-point number (including NaN, with arbitrary case)
 *
 * 
* * *@version 1.7 * @see WKTWriter */ public class WKTReader { private static final String EMPTY = "EMPTY"; private static final String COMMA = ","; private static final String L_PAREN = "("; private static final String R_PAREN = ")"; private static final String NAN_SYMBOL = "NaN"; private GeometryFactory geometryFactory; private PrecisionModel precisionModel; private StreamTokenizer tokenizer; /** * Creates a reader that creates objects using the default {@link GeometryFactory}. */ public WKTReader() { this(new GeometryFactory()); } /** * Creates a reader that creates objects using the given * {@link GeometryFactory}. * *@param geometryFactory the factory used to create Geometrys. */ public WKTReader(GeometryFactory geometryFactory) { this.geometryFactory = geometryFactory; precisionModel = geometryFactory.getPrecisionModel(); } /** * Reads a Well-Known Text representation of a {@link Geometry} * from a {@link String}. * * @param wellKnownText * one or more strings (see the OpenGIS * Simple Features Specification) separated by whitespace * @return a Geometry specified by wellKnownText * @throws ParseException * if a parsing problem occurs */ public Geometry read(String wellKnownText) throws ParseException { StringReader reader = new StringReader(wellKnownText); try { return read(reader); } finally { reader.close(); } } /** * Reads a Well-Known Text representation of a {@link Geometry} * from a {@link Reader}. * *@param reader a Reader which will return a * string (see the OpenGIS Simple Features Specification) *@return a Geometry read from reader *@throws ParseException if a parsing problem occurs */ public Geometry read(Reader reader) throws ParseException { tokenizer = new StreamTokenizer(reader); // set tokenizer to NOT parse numbers tokenizer.resetSyntax(); tokenizer.wordChars('a', 'z'); tokenizer.wordChars('A', 'Z'); tokenizer.wordChars(128 + 32, 255); tokenizer.wordChars('0', '9'); tokenizer.wordChars('-', '-'); tokenizer.wordChars('+', '+'); tokenizer.wordChars('.', '.'); tokenizer.whitespaceChars(0, ' '); tokenizer.commentChar('#'); try { return readGeometryTaggedText(); } catch (IOException e) { throw new ParseException(e.toString()); } } /** * Returns the next array of Coordinates in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next element returned by the stream should be L_PAREN (the * beginning of "(x1 y1, x2 y2, ..., xn yn)") or EMPTY. *@return the next array of Coordinates in the * stream, or an empty array if EMPTY is the next element returned by * the stream. *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private Coordinate[] getCoordinates() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return new Coordinate[] {}; } ArrayList coordinates = new ArrayList(); coordinates.add(getPreciseCoordinate()); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { coordinates.add(getPreciseCoordinate()); nextToken = getNextCloserOrComma(); } Coordinate[] array = new Coordinate[coordinates.size()]; return (Coordinate[]) coordinates.toArray(array); } private Coordinate[] getCoordinatesNoLeftParen() throws IOException, ParseException { String nextToken = null; ArrayList coordinates = new ArrayList(); coordinates.add(getPreciseCoordinate()); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { coordinates.add(getPreciseCoordinate()); nextToken = getNextCloserOrComma(); } Coordinate[] array = new Coordinate[coordinates.size()]; return (Coordinate[]) coordinates.toArray(array); } private Coordinate getPreciseCoordinate() throws IOException, ParseException { Coordinate coord = new Coordinate(); coord.x = getNextNumber(); coord.y = getNextNumber(); if (isNumberNext()) { coord.z = getNextNumber(); } precisionModel.makePrecise(coord); return coord; } private boolean isNumberNext() throws IOException { int type = tokenizer.nextToken(); tokenizer.pushBack(); return type == StreamTokenizer.TT_WORD; } /** * Parses the next number in the stream. * Numbers with exponents are handled. * NaN values are handled correctly, and * the case of the "NaN" symbol is not significant. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be a number. *@return the next number in the stream *@throws ParseException if the next token is not a valid number *@throws IOException if an I/O error occurs */ private double getNextNumber() throws IOException, ParseException { int type = tokenizer.nextToken(); switch (type) { case StreamTokenizer.TT_WORD: { if (tokenizer.sval.equalsIgnoreCase(NAN_SYMBOL)) { return Double.NaN; } else { try { return Double.parseDouble(tokenizer.sval); } catch (NumberFormatException ex) { throw new ParseException("Invalid number: " + tokenizer.sval); } } } } parseError("number"); return 0.0; } /** * Returns the next EMPTY or L_PAREN in the stream as uppercase text. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be EMPTY or L_PAREN. *@return the next EMPTY or L_PAREN in the stream as uppercase * text. *@throws ParseException if the next token is not EMPTY or L_PAREN *@throws IOException if an I/O error occurs */ private String getNextEmptyOrOpener() throws IOException, ParseException { String nextWord = getNextWord(); if (nextWord.equals(EMPTY) || nextWord.equals(L_PAREN)) { return nextWord; } parseError(EMPTY + " or " + L_PAREN); return null; } /** * Returns the next R_PAREN or COMMA in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be R_PAREN or COMMA. *@return the next R_PAREN or COMMA in the stream *@throws ParseException if the next token is not R_PAREN or COMMA *@throws IOException if an I/O error occurs */ private String getNextCloserOrComma() throws IOException, ParseException { String nextWord = getNextWord(); if (nextWord.equals(COMMA) || nextWord.equals(R_PAREN)) { return nextWord; } parseError(COMMA + " or " + R_PAREN); return null; } /** * Returns the next R_PAREN in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be R_PAREN. *@return the next R_PAREN in the stream *@throws ParseException if the next token is not R_PAREN *@throws IOException if an I/O error occurs */ private String getNextCloser() throws IOException, ParseException { String nextWord = getNextWord(); if (nextWord.equals(R_PAREN)) { return nextWord; } parseError(R_PAREN); return null; } /** * Returns the next word in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be a word. *@return the next word in the stream as uppercase text *@throws ParseException if the next token is not a word *@throws IOException if an I/O error occurs */ private String getNextWord() throws IOException, ParseException { int type = tokenizer.nextToken(); switch (type) { case StreamTokenizer.TT_WORD: String word = tokenizer.sval; if (word.equalsIgnoreCase(EMPTY)) return EMPTY; return word; case '(': return L_PAREN; case ')': return R_PAREN; case ',': return COMMA; } parseError("word"); return null; } /** * Returns the next word in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next token must be a word. *@return the next word in the stream as uppercase text *@throws ParseException if the next token is not a word *@throws IOException if an I/O error occurs */ private String lookaheadWord() throws IOException, ParseException { String nextWord = getNextWord(); tokenizer.pushBack(); return nextWord; } /** * Throws a formatted ParseException for the current token. * * @param expected a description of what was expected * @throws ParseException * @throws AssertionFailedException if an invalid token is encountered */ private void parseError(String expected) throws ParseException { // throws Asserts for tokens that should never be seen if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) Assert.shouldNeverReachHere("Unexpected NUMBER token"); if (tokenizer.ttype == StreamTokenizer.TT_EOL) Assert.shouldNeverReachHere("Unexpected EOL token"); String tokenStr = tokenString(); throw new ParseException("Expected " + expected + " but found " + tokenStr); } /** * Gets a description of the current token * * @return a description of the current token */ private String tokenString() { switch (tokenizer.ttype) { case StreamTokenizer.TT_NUMBER: return ""; case StreamTokenizer.TT_EOL: return "End-of-Line"; case StreamTokenizer.TT_EOF: return "End-of-Stream"; case StreamTokenizer.TT_WORD: return "'" + tokenizer.sval + "'"; } return "'" + (char) tokenizer.ttype + "'"; } /** * Creates a Geometry using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <Geometry Tagged Text>. *@return a Geometry specified by the next token * in the stream *@throws ParseException if the coordinates used to create a Polygon * shell and holes do not form closed linestrings, or if an unexpected * token was encountered *@throws IOException if an I/O error occurs */ private Geometry readGeometryTaggedText() throws IOException, ParseException { String type = null; try{ type = getNextWord(); }catch(IOException e){ return null; }catch(ParseException e){ return null; } if (type.equalsIgnoreCase("POINT")) { return readPointText(); } else if (type.equalsIgnoreCase("LINESTRING")) { return readLineStringText(); } else if (type.equalsIgnoreCase("LINEARRING")) { return readLinearRingText(); } else if (type.equalsIgnoreCase("POLYGON")) { return readPolygonText(); } else if (type.equalsIgnoreCase("MULTIPOINT")) { return readMultiPointText(); } else if (type.equalsIgnoreCase("MULTILINESTRING")) { return readMultiLineStringText(); } else if (type.equalsIgnoreCase("MULTIPOLYGON")) { return readMultiPolygonText(); } else if (type.equalsIgnoreCase("GEOMETRYCOLLECTION")) { return readGeometryCollectionText(); } throw new ParseException("Unknown geometry type: " + type); } /** * Creates a Point using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <Point Text>. *@return a Point specified by the next token in * the stream *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private Point readPointText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createPoint((Coordinate)null); } Point point = geometryFactory.createPoint(getPreciseCoordinate()); getNextCloser(); return point; } /** * Creates a LineString using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <LineString Text>. *@return a LineString specified by the next * token in the stream *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private LineString readLineStringText() throws IOException, ParseException { return geometryFactory.createLineString(getCoordinates()); } /** * Creates a LinearRing using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <LineString Text>. *@return a LinearRing specified by the next * token in the stream *@throws IOException if an I/O error occurs *@throws ParseException if the coordinates used to create the LinearRing * do not form a closed linestring, or if an unexpected token was * encountered */ private LinearRing readLinearRingText() throws IOException, ParseException { return geometryFactory.createLinearRing(getCoordinates()); } /* private MultiPoint OLDreadMultiPointText() throws IOException, ParseException { return geometryFactory.createMultiPoint(toPoints(getCoordinates())); } */ private static final boolean ALLOW_OLD_JTS_MULTIPOINT_SYNTAX = true; /** * Creates a MultiPoint using the next tokens in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <MultiPoint Text>. *@return a MultiPoint specified by the next * token in the stream *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private MultiPoint readMultiPointText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createMultiPoint(new Point[0]); } // check for old-style JTS syntax and parse it if present // MD 2009-02-21 - this is only provided for backwards compatibility for a few versions if (ALLOW_OLD_JTS_MULTIPOINT_SYNTAX) { String nextWord = lookaheadWord(); if (nextWord != L_PAREN) { return geometryFactory.createMultiPoint(toPoints(getCoordinatesNoLeftParen())); } } ArrayList points = new ArrayList(); Point point = readPointText(); points.add(point); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { point = readPointText(); points.add(point); nextToken = getNextCloserOrComma(); } Point[] array = new Point[points.size()]; return geometryFactory.createMultiPoint((Point[]) points.toArray(array)); } /** * Creates an array of Points having the given Coordinate * s. * *@param coordinates the Coordinates with which to create the * Points *@return Points created using this WKTReader * s GeometryFactory */ private Point[] toPoints(Coordinate[] coordinates) { ArrayList points = new ArrayList(); for (int i = 0; i < coordinates.length; i++) { points.add(geometryFactory.createPoint(coordinates[i])); } return (Point[]) points.toArray(new Point[]{}); } /** * Creates a Polygon using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <Polygon Text>. *@return a Polygon specified by the next token * in the stream *@throws ParseException if the coordinates used to create the Polygon * shell and holes do not form closed linestrings, or if an unexpected * token was encountered. *@throws IOException if an I/O error occurs */ private Polygon readPolygonText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createPolygon(geometryFactory.createLinearRing( new Coordinate[]{}), new LinearRing[]{}); } ArrayList holes = new ArrayList(); LinearRing shell = readLinearRingText(); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { LinearRing hole = readLinearRingText(); holes.add(hole); nextToken = getNextCloserOrComma(); } LinearRing[] array = new LinearRing[holes.size()]; return geometryFactory.createPolygon(shell, (LinearRing[]) holes.toArray(array)); } /** * Creates a MultiLineString using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <MultiLineString Text>. *@return a MultiLineString specified by the * next token in the stream *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private com.vividsolutions.jts.geom.MultiLineString readMultiLineStringText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createMultiLineString(new LineString[]{}); } ArrayList lineStrings = new ArrayList(); LineString lineString = readLineStringText(); lineStrings.add(lineString); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { lineString = readLineStringText(); lineStrings.add(lineString); nextToken = getNextCloserOrComma(); } LineString[] array = new LineString[lineStrings.size()]; return geometryFactory.createMultiLineString((LineString[]) lineStrings.toArray(array)); } /** * Creates a MultiPolygon using the next token in the stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <MultiPolygon Text>. *@return a MultiPolygon specified by the next * token in the stream, or if if the coordinates used to create the * Polygon shells and holes do not form closed linestrings. *@throws IOException if an I/O error occurs *@throws ParseException if an unexpected token was encountered */ private MultiPolygon readMultiPolygonText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createMultiPolygon(new Polygon[]{}); } ArrayList polygons = new ArrayList(); Polygon polygon = readPolygonText(); polygons.add(polygon); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { polygon = readPolygonText(); polygons.add(polygon); nextToken = getNextCloserOrComma(); } Polygon[] array = new Polygon[polygons.size()]; return geometryFactory.createMultiPolygon((Polygon[]) polygons.toArray(array)); } /** * Creates a GeometryCollection using the next token in the * stream. * *@param tokenizer tokenizer over a stream of text in Well-known Text * format. The next tokens must form a <GeometryCollection Text>. *@return a GeometryCollection specified by the * next token in the stream *@throws ParseException if the coordinates used to create a Polygon * shell and holes do not form closed linestrings, or if an unexpected * token was encountered *@throws IOException if an I/O error occurs */ private GeometryCollection readGeometryCollectionText() throws IOException, ParseException { String nextToken = getNextEmptyOrOpener(); if (nextToken.equals(EMPTY)) { return geometryFactory.createGeometryCollection(new Geometry[]{}); } ArrayList geometries = new ArrayList(); Geometry geometry = readGeometryTaggedText(); geometries.add(geometry); nextToken = getNextCloserOrComma(); while (nextToken.equals(COMMA)) { geometry = readGeometryTaggedText(); geometries.add(geometry); nextToken = getNextCloserOrComma(); } Geometry[] array = new Geometry[geometries.size()]; return geometryFactory.createGeometryCollection((Geometry[]) geometries.toArray(array)); } } jts-1.11/src/com/vividsolutions/jts/io/WKTFileReader.java0000644000000000000000000000726711343017562022060 0ustar rootrootpackage com.vividsolutions.jts.io; import java.io.*; import java.util.*; import com.vividsolutions.jts.geom.*; /** * Reads a sequence of {@link Geometry}s in WKT format * from a text file. * The geometries in the file may be separated by any amount * of whitespace and newlines. * * @author Martin Davis * */ public class WKTFileReader { private File file = null; private Reader reader; // private Reader fileReader = new FileReader(file); private WKTReader wktReader; private int count = 0; private int limit = -1; private int offset = 0; /** * Creates a new WKTFileReader given the File to read from * and a WKTReader to use to parse the geometries. * * @param file the File to read from * @param wktReader the geometry reader to use */ public WKTFileReader(File file, WKTReader wktReader) { this.file = file; this.wktReader = wktReader; } /** * Creates a new WKTFileReader, given the name of the file to read from. * * @param filename the name of the file to read from * @param wktReader the geometry reader to use */ public WKTFileReader(String filename, WKTReader wktReader) { this(new File(filename), wktReader); } /** * Creates a new WKTFileReader, given a {@link Reader} to read from. * * @param reader the reader to read from * @param wktReader the geometry reader to use */ public WKTFileReader(Reader reader, WKTReader wktReader) { this.reader = reader; this.wktReader = wktReader; } /** * Sets the maximum number of geometries to read. * * @param limit the maximum number of geometries to read */ public void setLimit(int limit) { this.limit = limit; } /** * Sets the number of geometries to skip before storing. * * @param offset the number of geometries to skip */ public void setOffset(int offset) { this.offset = offset; } /** * Reads a sequence of geometries. * If an offset is specified, geometries read up to the offset count are skipped. * If a limit is specified, no more than limit geometries are read. * * @return the list of geometries read * @throws IOException if an I/O exception was encountered * @throws ParseException if an error occured reading a geometry */ public List read() throws IOException, ParseException { // do this here so that constructors don't throw exceptions if (file != null) reader = new FileReader(file); count = 0; try { BufferedReader bufferedReader = new BufferedReader(reader); try { return read(bufferedReader); } finally { bufferedReader.close(); } } finally { reader.close(); } } private List read(BufferedReader bufferedReader) throws IOException, ParseException { List geoms = new ArrayList(); while (! isAtEndOfFile(bufferedReader) && ! isAtLimit(geoms)) { Geometry g = wktReader.read(bufferedReader); if (count >= offset) geoms.add(g); count++; } return geoms; } private boolean isAtLimit(List geoms) { if (limit < 0) return false; if (geoms.size() < limit) return false; return true; } private static final int MAX_LOOKAHEAD = 1000; /** * Tests if reader is at EOF. */ private boolean isAtEndOfFile(BufferedReader bufferedReader) throws IOException { bufferedReader.mark(MAX_LOOKAHEAD); StreamTokenizer tokenizer = new StreamTokenizer(bufferedReader); int type = tokenizer.nextToken(); if (type == StreamTokenizer.TT_EOF) { return true; } bufferedReader.reset(); return false; } } jts-1.11/src/com/vividsolutions/jts/io/ByteOrderValues.java0000644000000000000000000001064411343017562022540 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; /** * Methods to read and write primitive Java datatypes from/to byte * sequences, allowing the byte order to be specified *

* Similar to the standard Java ByteBuffer class. */ public class ByteOrderValues { public static final int BIG_ENDIAN = 1; public static final int LITTLE_ENDIAN = 2; public static int getInt(byte[] buf, int byteOrder) { if (byteOrder == BIG_ENDIAN) { return ( (int) (buf[0] & 0xff) << 24) | ( (int) (buf[1] & 0xff) << 16) | ( (int) (buf[2] & 0xff) << 8) | (( int) (buf[3] & 0xff) ); } else {// LITTLE_ENDIAN return ( (int) (buf[3] & 0xff) << 24) | ( (int) (buf[2] & 0xff) << 16) | ( (int) (buf[1] & 0xff) << 8) | ( (int) (buf[0] & 0xff) ); } } public static void putInt(int intValue, byte[] buf, int byteOrder) { if (byteOrder == BIG_ENDIAN) { buf[0] = (byte)(intValue >> 24); buf[1] = (byte)(intValue >> 16); buf[2] = (byte)(intValue >> 8); buf[3] = (byte) intValue; } else {// LITTLE_ENDIAN buf[0] = (byte) intValue; buf[1] = (byte)(intValue >> 8); buf[2] = (byte)(intValue >> 16); buf[3] = (byte)(intValue >> 24); } } public static long getLong(byte[] buf, int byteOrder) { if (byteOrder == BIG_ENDIAN) { return (long) (buf[0] & 0xff) << 56 | (long) (buf[1] & 0xff) << 48 | (long) (buf[2] & 0xff) << 40 | (long) (buf[3] & 0xff) << 32 | (long) (buf[4] & 0xff) << 24 | (long) (buf[5] & 0xff) << 16 | (long) (buf[6] & 0xff) << 8 | (long) (buf[7] & 0xff); } else {// LITTLE_ENDIAN return (long) (buf[7] & 0xff) << 56 | (long) (buf[6] & 0xff) << 48 | (long) (buf[5] & 0xff) << 40 | (long) (buf[4] & 0xff) << 32 | (long) (buf[3] & 0xff) << 24 | (long) (buf[2] & 0xff) << 16 | (long) (buf[1] & 0xff) << 8 | (long) (buf[0] & 0xff); } } public static void putLong(long longValue, byte[] buf, int byteOrder) { if (byteOrder == BIG_ENDIAN) { buf[0] = (byte)(longValue >> 56); buf[1] = (byte)(longValue >> 48); buf[2] = (byte)(longValue >> 40); buf[3] = (byte)(longValue >> 32); buf[4] = (byte)(longValue >> 24); buf[5] = (byte)(longValue >> 16); buf[6] = (byte)(longValue >> 8); buf[7] = (byte) longValue; } else { // LITTLE_ENDIAN buf[0] = (byte) longValue; buf[1] = (byte)(longValue >> 8); buf[2] = (byte)(longValue >> 16); buf[3] = (byte)(longValue >> 24); buf[4] = (byte)(longValue >> 32); buf[5] = (byte)(longValue >> 40); buf[6] = (byte)(longValue >> 48); buf[7] = (byte)(longValue >> 56); } } public static double getDouble(byte[] buf, int byteOrder) { long longVal = getLong(buf, byteOrder); return Double.longBitsToDouble(longVal); } public static void putDouble(double doubleValue, byte[] buf, int byteOrder) { long longVal = Double.doubleToLongBits(doubleValue); putLong(longVal, buf, byteOrder); } }jts-1.11/src/com/vividsolutions/jts/io/OutStream.java0000644000000000000000000000305611343017562021403 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.IOException; /** * A interface for classes providing an output stream of bytes. * This interface is similar to the Java {@link OutputStream}, * but with a narrower interface to make it easier to implement. */ public interface OutStream { void write(byte[] buf, int len) throws IOException; } jts-1.11/src/com/vividsolutions/jts/io/WKTWriter.java0000644000000000000000000005744311343017562021333 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.util.*; import java.io.*; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; /** * Writes the Well-Known Text representation of a {@link Geometry}. * The Well-Known Text format is defined in the * * OGC Simple Features Specification for SQL. *

* The WKTWriter outputs coordinates rounded to the precision * model. Only the maximum number of decimal places * necessary to represent the ordinates to the required precision will be * output. *

* The SFS WKT spec does not define a special tag for {@link LinearRing}s. * Under the spec, rings are output as LINESTRINGs. * In order to allow precisely specifying constructed geometries, * JTS supports a non-standard LINEARRING tag which is used * to output LinearRings. * * @version 1.7 * @see WKTReader */ public class WKTWriter { /** * Generates the WKT for a Point. * * @param p0 the point coordinate * * @return the WKT */ public static String toPoint(Coordinate p0) { return "POINT ( " + p0.x + " " + p0.y + " )"; } /** * Generates the WKT for a N-point LineString. * * @param seq the sequence to outpout * * @return the WKT */ public static String toLineString(CoordinateSequence seq) { StringBuffer buf = new StringBuffer(); buf.append("LINESTRING "); if (seq.size() == 0) buf.append(" EMPTY"); else { buf.append("("); for (int i = 0; i < seq.size(); i++) { if (i > 0) buf.append(", "); buf.append(seq.getX(i) + " " + seq.getY(i)); } buf.append(")"); } return buf.toString(); } /** * Generates the WKT for a 2-point LineString. * * @param p0 the first coordinate * @param p1 the second coordinate * * @return the WKT */ public static String toLineString(Coordinate p0, Coordinate p1) { return "LINESTRING ( " + p0.x + " " + p0.y + ", " + p1.x + " " + p1.y + " )"; } private static int INDENT = 2; /** * Creates the DecimalFormat used to write doubles * with a sufficient number of decimal places. * *@param precisionModel the PrecisionModel used to determine * the number of decimal places to write. *@return a DecimalFormat that write double * s without scientific notation. */ private static DecimalFormat createFormatter(PrecisionModel precisionModel) { // the default number of decimal places is 16, which is sufficient // to accomodate the maximum precision of a double. int decimalPlaces = precisionModel.getMaximumSignificantDigits(); // specify decimal separator explicitly to avoid problems in other locales DecimalFormatSymbols symbols = new DecimalFormatSymbols(); symbols.setDecimalSeparator('.'); return new DecimalFormat("0" + (decimalPlaces > 0 ? "." : "") + stringOfChar('#', decimalPlaces), symbols); } /** * Returns a String of repeated characters. * *@param ch the character to repeat *@param count the number of times to repeat the character *@return a String of characters */ public static String stringOfChar(char ch, int count) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < count; i++) { buf.append(ch); } return buf.toString(); } private int outputDimension = 2; private DecimalFormat formatter; private boolean isFormatted = false; private boolean useFormatting = false; private int level = 0; private int coordsPerLine = -1; private String indentTabStr = " "; /** * Creates a new WKTWriter with default settings */ public WKTWriter() { } /** * Creates a writer that writes {@link Geometry}s with * the given output dimension (2 or 3). * If the specified output dimension is 3, the Z value * of coordinates will be written if it is present * (i.e. if it is not Double.NaN). * * @param outputDimension the coordinate dimension to output (2 or 3) */ public WKTWriter(int outputDimension) { this.outputDimension = outputDimension; if (outputDimension < 2 || outputDimension > 3) throw new IllegalArgumentException("Invalid output dimension (must be 2 or 3)"); } /** * Sets whether the output will be formatted. * * @param isFormatted true if the output is to be formatted */ public void setFormatted(boolean isFormatted) { this.isFormatted = isFormatted; } /** * Sets the maximum number of coordinates per line * written in formatted output. * If the provided coordinate number is <= 0, * coordinates will be written all on one line. * * @param coordsPerLine the number of coordinates per line to output. */ public void setMaxCoordinatesPerLine(int coordsPerLine) { this.coordsPerLine = coordsPerLine; } /** * Sets the tab size to use for indenting. * * @param size the number of spaces to use as the tab string * @throws IllegalArgumentException if the size is non-positive */ public void setTab(int size) { if(size <= 0) throw new IllegalArgumentException("Tab count must be positive"); this.indentTabStr = stringOfChar(' ', size); } /** * Converts a Geometry to its Well-known Text representation. * *@param geometry a Geometry to process *@return a string (see the OpenGIS Simple * Features Specification) */ public String write(Geometry geometry) { Writer sw = new StringWriter(); try { writeFormatted(geometry, isFormatted, sw); } catch (IOException ex) { Assert.shouldNeverReachHere(); } return sw.toString(); } /** * Converts a Geometry to its Well-known Text representation. * *@param geometry a Geometry to process *@return a string (see the OpenGIS Simple * Features Specification) */ public void write(Geometry geometry, Writer writer) throws IOException { writeFormatted(geometry, false, writer); } /** * Same as write, but with newlines and spaces to make the * well-known text more readable. * *@param geometry a Geometry to process *@return a string (see the OpenGIS Simple * Features Specification), with newlines and spaces */ public String writeFormatted(Geometry geometry) { Writer sw = new StringWriter(); try { writeFormatted(geometry, true, sw); } catch (IOException ex) { Assert.shouldNeverReachHere(); } return sw.toString(); } /** * Same as write, but with newlines and spaces to make the * well-known text more readable. * *@param geometry a Geometry to process *@return a string (see the OpenGIS Simple * Features Specification), with newlines and spaces */ public void writeFormatted(Geometry geometry, Writer writer) throws IOException { writeFormatted(geometry, true, writer); } /** * Converts a Geometry to its Well-known Text representation. * *@param geometry a Geometry to process *@return a string (see the OpenGIS Simple * Features Specification) */ private void writeFormatted(Geometry geometry, boolean useFormatting, Writer writer) throws IOException { this.useFormatting = useFormatting; formatter = createFormatter(geometry.getPrecisionModel()); appendGeometryTaggedText(geometry, 0, writer); } /** * Converts a Geometry to <Geometry Tagged Text> format, * then appends it to the writer. * *@param geometry the Geometry to process *@param writer the output writer to append to */ private void appendGeometryTaggedText(Geometry geometry, int level, Writer writer) throws IOException { indent(level, writer); if (geometry instanceof Point) { Point point = (Point) geometry; appendPointTaggedText(point.getCoordinate(), level, writer, point.getPrecisionModel()); } else if (geometry instanceof LinearRing) { appendLinearRingTaggedText((LinearRing) geometry, level, writer); } else if (geometry instanceof LineString) { appendLineStringTaggedText((LineString) geometry, level, writer); } else if (geometry instanceof Polygon) { appendPolygonTaggedText((Polygon) geometry, level, writer); } else if (geometry instanceof MultiPoint) { appendMultiPointTaggedText((MultiPoint) geometry, level, writer); } else if (geometry instanceof MultiLineString) { appendMultiLineStringTaggedText((MultiLineString) geometry, level, writer); } else if (geometry instanceof MultiPolygon) { appendMultiPolygonTaggedText((MultiPolygon) geometry, level, writer); } else if (geometry instanceof GeometryCollection) { appendGeometryCollectionTaggedText((GeometryCollection) geometry, level, writer); } else { Assert.shouldNeverReachHere("Unsupported Geometry implementation:" + geometry.getClass()); } } /** * Converts a Coordinate to <Point Tagged Text> format, * then appends it to the writer. * *@param coordinate the Coordinate to process *@param writer the output writer to append to *@param precisionModel the PrecisionModel to use to convert * from a precise coordinate to an external coordinate */ private void appendPointTaggedText(Coordinate coordinate, int level, Writer writer, PrecisionModel precisionModel) throws IOException { writer.write("POINT "); appendPointText(coordinate, level, writer, precisionModel); } /** * Converts a LineString to <LineString Tagged Text> * format, then appends it to the writer. * *@param lineString the LineString to process *@param writer the output writer to append to */ private void appendLineStringTaggedText(LineString lineString, int level, Writer writer) throws IOException { writer.write("LINESTRING "); appendLineStringText(lineString, level, false, writer); } /** * Converts a LinearRing to <LinearRing Tagged Text> * format, then appends it to the writer. * *@param linearRing the LinearRing to process *@param writer the output writer to append to */ private void appendLinearRingTaggedText(LinearRing linearRing, int level, Writer writer) throws IOException { writer.write("LINEARRING "); appendLineStringText(linearRing, level, false, writer); } /** * Converts a Polygon to <Polygon Tagged Text> format, * then appends it to the writer. * *@param polygon the Polygon to process *@param writer the output writer to append to */ private void appendPolygonTaggedText(Polygon polygon, int level, Writer writer) throws IOException { writer.write("POLYGON "); appendPolygonText(polygon, level, false, writer); } /** * Converts a MultiPoint to <MultiPoint Tagged Text> * format, then appends it to the writer. * *@param multipoint the MultiPoint to process *@param writer the output writer to append to */ private void appendMultiPointTaggedText(MultiPoint multipoint, int level, Writer writer) throws IOException { writer.write("MULTIPOINT "); appendMultiPointText(multipoint, level, writer); } /** * Converts a MultiLineString to <MultiLineString Tagged * Text> format, then appends it to the writer. * *@param multiLineString the MultiLineString to process *@param writer the output writer to append to */ private void appendMultiLineStringTaggedText(MultiLineString multiLineString, int level, Writer writer) throws IOException { writer.write("MULTILINESTRING "); appendMultiLineStringText(multiLineString, level, false, writer); } /** * Converts a MultiPolygon to <MultiPolygon Tagged Text> * format, then appends it to the writer. * *@param multiPolygon the MultiPolygon to process *@param writer the output writer to append to */ private void appendMultiPolygonTaggedText(MultiPolygon multiPolygon, int level, Writer writer) throws IOException { writer.write("MULTIPOLYGON "); appendMultiPolygonText(multiPolygon, level, writer); } /** * Converts a GeometryCollection to <GeometryCollection * Tagged Text> format, then appends it to the writer. * *@param geometryCollection the GeometryCollection to process *@param writer the output writer to append to */ private void appendGeometryCollectionTaggedText(GeometryCollection geometryCollection, int level, Writer writer) throws IOException { writer.write("GEOMETRYCOLLECTION "); appendGeometryCollectionText(geometryCollection, level, writer); } /** * Converts a Coordinate to <Point Text> format, then * appends it to the writer. * *@param coordinate the Coordinate to process *@param writer the output writer to append to *@param precisionModel the PrecisionModel to use to convert * from a precise coordinate to an external coordinate */ private void appendPointText(Coordinate coordinate, int level, Writer writer, PrecisionModel precisionModel) throws IOException { if (coordinate == null) { writer.write("EMPTY"); } else { writer.write("("); appendCoordinate(coordinate, writer); writer.write(")"); } } /** * Appends the i'th coordinate from the sequence to the writer * * @param seq the CoordinateSequence to process * @param i the index of the coordinate to write * @param writer the output writer to append to */ private void appendCoordinate(CoordinateSequence seq, int i, Writer writer) throws IOException { writer.write(writeNumber(seq.getX(i)) + " " + writeNumber(seq.getY(i))); if (outputDimension >= 3 && seq.getDimension() >= 3) { double z = seq.getOrdinate(i, 3); if (! Double.isNaN(z)) { writer.write(" "); writer.write(writeNumber(z)); } } } /** * Converts a Coordinate to <Point> format, * then appends it to the writer. * *@param coordinate the Coordinate to process *@param writer the output writer to append to */ private void appendCoordinate(Coordinate coordinate, Writer writer) throws IOException { writer.write(writeNumber(coordinate.x) + " " + writeNumber(coordinate.y)); if (outputDimension >= 3 && ! Double.isNaN(coordinate.z)) { writer.write(" "); writer.write(writeNumber(coordinate.z)); } } /** * Converts a double to a String, not in scientific * notation. * *@param d the double to convert *@return the double as a String, not in * scientific notation */ private String writeNumber(double d) { return formatter.format(d); } /** * Converts a LineString to <LineString Text> format, then * appends it to the writer. * *@param lineString the LineString to process *@param writer the output writer to append to */ private void appendSequenceText(CoordinateSequence seq, int level, boolean doIndent, Writer writer) throws IOException { if (seq.size() == 0) { writer.write("EMPTY"); } else { if (doIndent) indent(level, writer); writer.write("("); for (int i = 0; i < seq.size(); i++) { if (i > 0) { writer.write(", "); if (coordsPerLine > 0 && i % coordsPerLine == 0) { indent(level + 1, writer); } } appendCoordinate(seq, i, writer); } writer.write(")"); } } /** * Converts a LineString to <LineString Text> format, then * appends it to the writer. * *@param lineString the LineString to process *@param writer the output writer to append to */ private void appendLineStringText(LineString lineString, int level, boolean doIndent, Writer writer) throws IOException { if (lineString.isEmpty()) { writer.write("EMPTY"); } else { if (doIndent) indent(level, writer); writer.write("("); for (int i = 0; i < lineString.getNumPoints(); i++) { if (i > 0) { writer.write(", "); if (coordsPerLine > 0 && i % coordsPerLine == 0) { indent(level + 1, writer); } } appendCoordinate(lineString.getCoordinateN(i), writer); } writer.write(")"); } } /** * Converts a Polygon to <Polygon Text> format, then * appends it to the writer. * *@param polygon the Polygon to process *@param writer the output writer to append to */ private void appendPolygonText(Polygon polygon, int level, boolean indentFirst, Writer writer) throws IOException { if (polygon.isEmpty()) { writer.write("EMPTY"); } else { if (indentFirst) indent(level, writer); writer.write("("); appendLineStringText(polygon.getExteriorRing(), level, false, writer); for (int i = 0; i < polygon.getNumInteriorRing(); i++) { writer.write(", "); appendLineStringText(polygon.getInteriorRingN(i), level + 1, true, writer); } writer.write(")"); } } /** * Converts a MultiPoint to <MultiPoint Text> format, then * appends it to the writer. * *@param multiPoint the MultiPoint to process *@param writer the output writer to append to */ private void appendMultiPointText(MultiPoint multiPoint, int level, Writer writer) throws IOException { if (multiPoint.isEmpty()) { writer.write("EMPTY"); } else { writer.write("("); for (int i = 0; i < multiPoint.getNumGeometries(); i++) { if (i > 0) { writer.write(", "); indentCoords(i, level + 1, writer); } writer.write("("); appendCoordinate(((Point) multiPoint.getGeometryN(i)).getCoordinate(), writer); writer.write(")"); } writer.write(")"); } } /** * Converts a MultiLineString to <MultiLineString Text> * format, then appends it to the writer. * *@param multiLineString the MultiLineString to process *@param writer the output writer to append to */ private void appendMultiLineStringText(MultiLineString multiLineString, int level, boolean indentFirst, Writer writer) throws IOException { if (multiLineString.isEmpty()) { writer.write("EMPTY"); } else { int level2 = level; boolean doIndent = indentFirst; writer.write("("); for (int i = 0; i < multiLineString.getNumGeometries(); i++) { if (i > 0) { writer.write(", "); level2 = level + 1; doIndent = true; } appendLineStringText((LineString) multiLineString.getGeometryN(i), level2, doIndent, writer); } writer.write(")"); } } /** * Converts a MultiPolygon to <MultiPolygon Text> format, * then appends it to the writer. * *@param multiPolygon the MultiPolygon to process *@param writer the output writer to append to */ private void appendMultiPolygonText(MultiPolygon multiPolygon, int level, Writer writer) throws IOException { if (multiPolygon.isEmpty()) { writer.write("EMPTY"); } else { int level2 = level; boolean doIndent = false; writer.write("("); for (int i = 0; i < multiPolygon.getNumGeometries(); i++) { if (i > 0) { writer.write(", "); level2 = level + 1; doIndent = true; } appendPolygonText((Polygon) multiPolygon.getGeometryN(i), level2, doIndent, writer); } writer.write(")"); } } /** * Converts a GeometryCollection to <GeometryCollectionText> * format, then appends it to the writer. * *@param geometryCollection the GeometryCollection to process *@param writer the output writer to append to */ private void appendGeometryCollectionText(GeometryCollection geometryCollection, int level, Writer writer) throws IOException { if (geometryCollection.isEmpty()) { writer.write("EMPTY"); } else { int level2 = level; writer.write("("); for (int i = 0; i < geometryCollection.getNumGeometries(); i++) { if (i > 0) { writer.write(", "); level2 = level + 1; } appendGeometryTaggedText(geometryCollection.getGeometryN(i), level2, writer); } writer.write(")"); } } private void indentCoords(int coordIndex, int level, Writer writer) throws IOException { if (coordsPerLine <= 0 || coordIndex % coordsPerLine != 0) return; indent(level, writer); } private void indent(int level, Writer writer) throws IOException { if (! useFormatting || level <= 0) return; writer.write("\n"); for (int i = 0; i < level; i++) { writer.write(indentTabStr); } } } jts-1.11/src/com/vividsolutions/jts/io/OutputStreamOutStream.java0000644000000000000000000000322311343017562023774 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.IOException; import java.io.OutputStream; /** * An adapter to allow an {@link OutputStream} to be used as an {@link OutStream} */ public class OutputStreamOutStream implements OutStream { private OutputStream os; public OutputStreamOutStream(OutputStream os) { this.os = os; } public void write(byte[] buf, int len) throws IOException { os.write(buf, 0, len); } } jts-1.11/src/com/vividsolutions/jts/io/WKBReader.java0000644000000000000000000002324611343017562021231 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.IOException; import com.vividsolutions.jts.geom.*; /** * Reads a {@link Geometry}from a byte stream in Well-Known Binary format. * Supports use of an {@link InStream}, which allows easy use * with arbitary byte stream sources. *

* This class reads the format describe in {@link WKBWriter}. * It also partiually handles * the Extended WKB format used by PostGIS, by parsing and storing SRID values. *

* This class is designed to support reuse of a single instance to read multiple * geometries. This class is not thread-safe; each thread should create its own * instance. * * @see WKBWriter */ public class WKBReader { /** * Converts a hexadecimal string to a byte array. * The hexadecimal digit symbols are case-insensitive. * * @param hex a string containing hex digits * @return an array of bytes with the value of the hex string */ public static byte[] hexToBytes(String hex) { int byteLen = hex.length() / 2; byte[] bytes = new byte[byteLen]; for (int i = 0; i < hex.length() / 2; i++) { int i2 = 2 * i; if (i2 + 1 > hex.length()) throw new IllegalArgumentException("Hex string has odd length"); int nib1 = hexToInt(hex.charAt(i2)); int nib0 = hexToInt(hex.charAt(i2 + 1)); byte b = (byte) ((nib1 << 4) + (byte) nib0); bytes[i] = b; } return bytes; } private static int hexToInt(char hex) { int nib = Character.digit(hex, 16); if (nib < 0) throw new IllegalArgumentException("Invalid hex digit: '" + hex + "'"); return nib; } private static final String INVALID_GEOM_TYPE_MSG = "Invalid geometry type encountered in "; private GeometryFactory factory; private PrecisionModel precisionModel; // default dimension - will be set on read private int inputDimension = 2; private boolean hasSRID = false; private int SRID = 0; private ByteOrderDataInStream dis = new ByteOrderDataInStream(); private double[] ordValues; public WKBReader() { this(new GeometryFactory()); } public WKBReader(GeometryFactory geometryFactory) { this.factory = geometryFactory; precisionModel = factory.getPrecisionModel(); } /** * Reads a single {@link Geometry} in WKB format from a byte array. * * @param bytes the byte array to read from * @return the geometry read * @throws ParseException if the WKB is ill-formed */ public Geometry read(byte[] bytes) throws ParseException { // possibly reuse the ByteArrayInStream? // don't throw IOExceptions, since we are not doing any I/O try { return read(new ByteArrayInStream(bytes)); } catch (IOException ex) { throw new RuntimeException("Unexpected IOException caught: " + ex.getMessage()); } } /** * Reads a {@link Geometry} in binary WKB format from an {@link InStream). * * @param is the stream to read from * @return the Geometry read * @throws IOException if the underlying stream creates an error * @throws ParseException if the WKB is ill-formed */ public Geometry read(InStream is) throws IOException, ParseException { dis.setInStream(is); Geometry g = readGeometry(); setSRID(g); return g; } private Geometry readGeometry() throws IOException, ParseException { // determine byte order byte byteOrder = dis.readByte(); // default is big endian if (byteOrder == WKBConstants.wkbNDR) dis.setOrder(ByteOrderValues.LITTLE_ENDIAN); int typeInt = dis.readInt(); int geometryType = typeInt & 0xff; // determine if Z values are present boolean hasZ = (typeInt & 0x80000000) != 0; inputDimension = hasZ ? 3 : 2; // determine if SRIDs are present hasSRID = (typeInt & 0x20000000) != 0; if (hasSRID) { SRID = dis.readInt(); } // only allocate ordValues buffer if necessary if (ordValues == null || ordValues.length < inputDimension) ordValues = new double[inputDimension]; switch (geometryType) { case WKBConstants.wkbPoint : return readPoint(); case WKBConstants.wkbLineString : return readLineString(); case WKBConstants.wkbPolygon : return readPolygon(); case WKBConstants.wkbMultiPoint : return readMultiPoint(); case WKBConstants.wkbMultiLineString : return readMultiLineString(); case WKBConstants.wkbMultiPolygon : return readMultiPolygon(); case WKBConstants.wkbGeometryCollection : return readGeometryCollection(); } throw new ParseException("Unknown WKB type " + geometryType); //return null; } /** * Sets the SRID, if it was specified in the WKB * * @param g the geometry to update * @return the geometry with an updated SRID value, if required */ private Geometry setSRID(Geometry g) { if (SRID != 0) g.setSRID(SRID); return g; } private Point readPoint() throws IOException { CoordinateSequence pts = readCoordinateSequence(1); return factory.createPoint(pts); } private LineString readLineString() throws IOException { int size = dis.readInt(); CoordinateSequence pts = readCoordinateSequence(size); return factory.createLineString(pts); } private LinearRing readLinearRing() throws IOException { int size = dis.readInt(); CoordinateSequence pts = readCoordinateSequence(size); return factory.createLinearRing(pts); } private Polygon readPolygon() throws IOException { int numRings = dis.readInt(); LinearRing[] holes = null; if (numRings > 1) holes = new LinearRing[numRings - 1]; LinearRing shell = readLinearRing(); for (int i = 0; i < numRings - 1; i++) { holes[i] = readLinearRing(); } return factory.createPolygon(shell, holes); } private MultiPoint readMultiPoint() throws IOException, ParseException { int numGeom = dis.readInt(); Point[] geoms = new Point[numGeom]; for (int i = 0; i < numGeom; i++) { Geometry g = readGeometry(); if (! (g instanceof Point)) throw new ParseException(INVALID_GEOM_TYPE_MSG + "MultiPoint"); geoms[i] = (Point) g; } return factory.createMultiPoint(geoms); } private MultiLineString readMultiLineString() throws IOException, ParseException { int numGeom = dis.readInt(); LineString[] geoms = new LineString[numGeom]; for (int i = 0; i < numGeom; i++) { Geometry g = readGeometry(); if (! (g instanceof LineString)) throw new ParseException(INVALID_GEOM_TYPE_MSG + "MultiLineString"); geoms[i] = (LineString) g; } return factory.createMultiLineString(geoms); } private MultiPolygon readMultiPolygon() throws IOException, ParseException { int numGeom = dis.readInt(); Polygon[] geoms = new Polygon[numGeom]; for (int i = 0; i < numGeom; i++) { Geometry g = readGeometry(); if (! (g instanceof Polygon)) throw new ParseException(INVALID_GEOM_TYPE_MSG + "MultiPolygon"); geoms[i] = (Polygon) g; } return factory.createMultiPolygon(geoms); } private GeometryCollection readGeometryCollection() throws IOException, ParseException { int numGeom = dis.readInt(); Geometry[] geoms = new Geometry[numGeom]; for (int i = 0; i < numGeom; i++) { geoms[i] = readGeometry(); } return factory.createGeometryCollection(geoms); } private CoordinateSequence readCoordinateSequence(int size) throws IOException { CoordinateSequence seq = factory.getCoordinateSequenceFactory().create(size, inputDimension); int targetDim = seq.getDimension(); if (targetDim > inputDimension) targetDim = inputDimension; for (int i = 0; i < size; i++) { readCoordinate(); for (int j = 0; j < targetDim; j++) { seq.setOrdinate(i, j, ordValues[j]); } } return seq; } /** * Reads a coordinate value with the specified dimensionality. * Makes the X and Y ordinates precise according to the precision model * in use. */ private void readCoordinate() throws IOException { for (int i = 0; i < inputDimension; i++) { if (i <= 1) { ordValues[i] = precisionModel.makePrecise(dis.readDouble()); } else { ordValues[i] = dis.readDouble(); } } } }jts-1.11/src/com/vividsolutions/jts/io/ByteArrayInStream.java0000644000000000000000000000462311343017562023026 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; /** * Allows an array of bytes to be used as an {@link InStream}. * To optimize memory usage, instances can be reused * with different byte arrays. */ public class ByteArrayInStream implements InStream { /* * Implementation improvement suggested by Andrea Aime - Dec 15 2007 */ private byte[] buffer; private int position; /** * Creates a new stream based on the given buffer. * * @param buffer the bytes to read */ public ByteArrayInStream(final byte[] buffer) { setBytes(buffer); } /** * Sets this stream to read from the given buffer * * @param buffer the bytes to read */ public void setBytes(final byte[] buffer) { this.buffer = buffer; this.position = 0; } /** * Reads up to buf.length bytes from the stream * into the given byte buffer. * * @param buf the buffer to place the read bytes into */ public void read(final byte[] buf) { int size = buf.length; // don't try and copy past the end of the input if ((position + size) > buffer.length) { size = buffer.length - position; } System.arraycopy(buffer, position, buf, 0, size); position += size; } } jts-1.11/src/com/vividsolutions/jts/io/InStream.java0000644000000000000000000000341711343017562021203 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.IOException; /** * A interface for classes providing an input stream of bytes. * This interface is similar to the Java {@link InputStream}, * but with a narrower interface to make it easier to implement. * */ public interface InStream { /** * Reads buf.length bytes from the input stream * and stores them in the supplied buffer. * * @param buf the buffer to receive the bytes * * @throws IOException if an I/O error occurs */ void read(byte[] buf) throws IOException; } jts-1.11/src/com/vividsolutions/jts/io/ParseException.java0000644000000000000000000000364111343017562022411 0ustar rootroot /* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; /** * Thrown by a WKTReader when a parsing problem occurs. * *@version 1.7 */ public class ParseException extends Exception { /** * Creates a ParseException with the given detail message. * *@param message a description of this ParseException */ public ParseException(String message) { super(message); } /** * Creates a ParseException with es detail message. * *@param e an exception that occurred while a WKTReader was * parsing a Well-known Text string */ public ParseException(Exception e) { this(e.toString()); } } jts-1.11/src/com/vividsolutions/jts/io/WKBWriter.java0000644000000000000000000002257111343017562021303 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.*; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.util.Assert; /** * Writes a {@link Geometry} into Well-Known Binary format. * Supports use of an {@link OutStream}, which allows easy use * with arbitary byte stream sinks. *

* The WKB format is specified in the OGC Simple Features for SQL specification. * This implementation supports the extended WKB standard for representing * 3-dimensional coordinates. The presence of 3D coordinates is signified * by setting the high bit of the wkbType word. *

* Empty Points cannot be represented in WKB; an * {@link IllegalArgumentException} will be thrown if one is * written. The WKB specification does not support representing {@link LinearRing}s; * they will be written as {@link LineString}s. *

* This class is designed to support reuse of a single instance to read multiple * geometries. This class is not thread-safe; each thread should create its own * instance. * * @see WKBReader */ public class WKBWriter { /** * Converts a byte array to a hexadecimal string. * * @param bytes * @return * * @deprecated */ public static String bytesToHex(byte[] bytes) { return toHex(bytes); } /** * Converts a byte array to a hexadecimal string. * * @param bytes a byte array * @return a string of hexadecimal digits */ public static String toHex(byte[] bytes) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { byte b = bytes[i]; buf.append(toHexDigit((b >> 4) & 0x0F)); buf.append(toHexDigit(b & 0x0F)); } return buf.toString(); } private static char toHexDigit(int n) { if (n < 0 || n > 15) throw new IllegalArgumentException("Nibble value out of range: " + n); if (n <= 9) return (char) ('0' + n); return (char) ('A' + (n - 10)); } private int outputDimension = 2; private int byteOrder; private ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream(); private OutStream byteArrayOutStream = new OutputStreamOutStream(byteArrayOS); // holds output data values private byte[] buf = new byte[8]; /** * Creates a writer that writes {@link Geometry}s with * output dimension = 2 and BIG_ENDIAN byte order */ public WKBWriter() { this(2, ByteOrderValues.BIG_ENDIAN); } /** * Creates a writer that writes {@link Geometry}s with * the given dimension (2 or 3) for output coordinates * and {@link BIG_ENDIAN} byte order. * If the input geometry has a small coordinate dimension, * coordinates will be padded with {@link NULL_ORDINATE}. * * @param outputDimension the coordinate dimension to output (2 or 3) */ public WKBWriter(int outputDimension) { this(outputDimension, ByteOrderValues.BIG_ENDIAN); } /** * Creates a writer that writes {@link Geometry}s with * the given dimension (2 or 3) for output coordinates * and byte order * If the input geometry has a small coordinate dimension, * coordinates will be padded with {@link NULL_ORDINATE}. * * @param outputDimension the coordinate dimension to output (2 or 3) * @param byteOrder the byte ordering to use */ public WKBWriter(int outputDimension, int byteOrder) { this.outputDimension = outputDimension; this.byteOrder = byteOrder; if (outputDimension < 2 || outputDimension > 3) throw new IllegalArgumentException("Output dimension must be 2 or 3"); } /** * Writes a {@link Geometry} into a byte array. * * @param geom the geometry to write * @return the byte array containing the WKB */ public byte[] write(Geometry geom) { try { byteArrayOS.reset(); write(geom, byteArrayOutStream); } catch (IOException ex) { throw new RuntimeException("Unexpected IO exception: " + ex.getMessage()); } return byteArrayOS.toByteArray(); } /** * Writes a {@link Geometry} to an {@link OutStream}. * * @param geom the geometry to write * @param os the out stream to write to * @throws IOException if an I/O error occurs */ public void write(Geometry geom, OutStream os) throws IOException { if (geom instanceof Point) writePoint((Point) geom, os); // LinearRings will be written as LineStrings else if (geom instanceof LineString) writeLineString((LineString) geom, os); else if (geom instanceof Polygon) writePolygon((Polygon) geom, os); else if (geom instanceof MultiPoint) writeGeometryCollection(WKBConstants.wkbMultiPoint, (MultiPoint) geom, os); else if (geom instanceof MultiLineString) writeGeometryCollection(WKBConstants.wkbMultiLineString, (MultiLineString) geom, os); else if (geom instanceof MultiPolygon) writeGeometryCollection(WKBConstants.wkbMultiPolygon, (MultiPolygon) geom, os); else if (geom instanceof GeometryCollection) writeGeometryCollection(WKBConstants.wkbGeometryCollection, (GeometryCollection) geom, os); else { Assert.shouldNeverReachHere("Unknown Geometry type"); } } private void writePoint(Point pt, OutStream os) throws IOException { if (pt.getCoordinateSequence().size() == 0) throw new IllegalArgumentException("Empty Points cannot be represented in WKB"); writeByteOrder(os); writeGeometryType(WKBConstants.wkbPoint, os); writeCoordinateSequence(pt.getCoordinateSequence(), false, os); } private void writeLineString(LineString line, OutStream os) throws IOException { writeByteOrder(os); writeGeometryType(WKBConstants.wkbLineString, os); writeCoordinateSequence(line.getCoordinateSequence(), true, os); } private void writePolygon(Polygon poly, OutStream os) throws IOException { writeByteOrder(os); writeGeometryType(WKBConstants.wkbPolygon, os); writeInt(poly.getNumInteriorRing() + 1, os); writeCoordinateSequence(poly.getExteriorRing().getCoordinateSequence(), true, os); for (int i = 0; i < poly.getNumInteriorRing(); i++) { writeCoordinateSequence(poly.getInteriorRingN(i).getCoordinateSequence(), true, os); } } private void writeGeometryCollection(int geometryType, GeometryCollection gc, OutStream os) throws IOException { writeByteOrder(os); writeGeometryType(geometryType, os); writeInt(gc.getNumGeometries(), os); for (int i = 0; i < gc.getNumGeometries(); i++) { write(gc.getGeometryN(i), os); } } private void writeByteOrder(OutStream os) throws IOException { if (byteOrder == ByteOrderValues.LITTLE_ENDIAN) buf[0] = WKBConstants.wkbNDR; else buf[0] = WKBConstants.wkbXDR; os.write(buf, 1); } private void writeGeometryType(int geometryType, OutStream os) throws IOException { int flag3D = (outputDimension == 3) ? 0x80000000 : 0; int typeInt = geometryType | flag3D; writeInt(typeInt, os); } private void writeInt(int intValue, OutStream os) throws IOException { ByteOrderValues.putInt(intValue, buf, byteOrder); os.write(buf, 4); } private void writeCoordinateSequence(CoordinateSequence seq, boolean writeSize, OutStream os) throws IOException { if (writeSize) writeInt(seq.size(), os); for (int i = 0; i < seq.size(); i++) { writeCoordinate(seq, i, os); } } private void writeCoordinate(CoordinateSequence seq, int index, OutStream os) throws IOException { ByteOrderValues.putDouble(seq.getX(index), buf, byteOrder); os.write(buf, 8); ByteOrderValues.putDouble(seq.getY(index), buf, byteOrder); os.write(buf, 8); // only write 3rd dim if caller has requested it for this writer if (outputDimension >= 3) { // if 3rd dim is requested, only access and write it if the CS provides is double ordVal = Coordinate.NULL_ORDINATE; if (seq.getDimension() >= 3) ordVal = seq.getOrdinate(index, 2); ByteOrderValues.putDouble(ordVal, buf, byteOrder); os.write(buf, 8); } } }jts-1.11/src/com/vividsolutions/jts/io/package.html0000644000000000000000000000207211343017562021073 0ustar rootroot Contains the interfaces for converting JTS objects to and from other formats.

The Java Topology Suite (JTS) is a Java API that implements a core set of spatial data operations using an explicit precision model and robust geometric algorithms. JTS is intended to be used in the development of applications that support the validation, cleaning, integration and querying of spatial datasets.

JTS attempts to implement the OpenGIS Simple Features Specification (SFS) as accurately as possible. In some cases the SFS is unclear or omits a specification; in this case JTS attempts to choose a reasonable and consistent alternative. Differences from and elaborations of the SFS are documented in this specification.

Package Specification

jts-1.11/src/com/vividsolutions/jts/io/InputStreamInStream.java0000644000000000000000000000312111343017562023367 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.io; import java.io.*; /** * An adapter to allow an {@link InputStream} to be used as an {@link InStream} */ public class InputStreamInStream implements InStream { private InputStream is; public InputStreamInStream(InputStream is) { this.is = is; } public void read(byte[] buf) throws IOException { is.read(buf); } } jts-1.11/src/com/vividsolutions/jts/awt/0000755000000000000000000000000011343017562016775 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/awt/PointTransformation.java0000644000000000000000000000361311343017562023663 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.geom.Point2D; import com.vividsolutions.jts.geom.*; /** * Transforms a geometry {@link Coordinate} into a Java2D {@link Point}, * possibly with a mathematical transformation of the ordinate values. * Transformation from a model coordinate system to a view coordinate system * can be efficiently performed by supplying an appropriate transformation. * * @author Martin Davis */ public interface PointTransformation { /** * Transforms a {@link Coordinate} into a Java2D {@link Point}. * * @param src the source Coordinate * @param dest the destination Point */ public void transform(Coordinate src, Point2D dest); }jts-1.11/src/com/vividsolutions/jts/awt/PointShapeFactory.java0000644000000000000000000000340511343017562023244 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Shape; import java.awt.geom.Point2D; /** * An interface for classes which create {@link Shape}s to represent point geometries. * Java2D does not provide an actual point shape, so some other shape * must be used to render points (e.g. such as a Rectangle or Ellipse). * * @author Martin Davis * */ public interface PointShapeFactory { /** * Creates a shape representing a point. * * @param point the location of the point * @return a shape */ Shape createPoint(Point2D point); } jts-1.11/src/com/vividsolutions/jts/awt/FontGlyphReader.java0000644000000000000000000000601211343017562022674 0ustar rootrootpackage com.vividsolutions.jts.awt; import java.util.*; import java.awt.Font; import java.awt.font.*; import com.vividsolutions.jts.geom.*; /** * Provides methods to read {@link Font} glyphs for strings * into {@link Polygonal} geometry. *

* It is suggested to use larger point sizes to render fonts glyphs, * to reduce the effects of scale-dependent hints. * The resulting geometry are in the base coordinate system * of the font. * The geometry can be further transformed as necessary using * {@link AffineTransformation}s. * * @author Martin Davis * */ public class FontGlyphReader { public static final String FONT_SERIF = "Serif"; public static final String FONT_SANSERIF = "SanSerif"; public static final String FONT_MONOSPACED = "Monospaced"; // a flatness factor empirically determined to provide good results private static final double FLATNESS_FACTOR = 400; /** * Converts text rendered in the given font and pointsize to a {@link Geometry} * using a standard flatness factor. * * @param text the text to render * @param fontName the name of the font * @param pointSize the pointSize to render at * @param geomFact the geometryFactory to use to create the result * @return a polygonal geometry representing the rendered text */ public static Geometry read(String text, String fontName, int pointSize, GeometryFactory geomFact) { return read(text, new Font(fontName, Font.PLAIN, pointSize), geomFact); } /** * Converts text rendered in the given {@link Font} to a {@link Geometry} * using a standard flatness factor. * * @param text the text to render * @param font the font to render with * @param geomFact the geometryFactory to use to create the result * @return a polygonal geometry representing the rendered text */ public static Geometry read(String text, Font font, GeometryFactory geomFact) { double flatness = font.getSize() / FLATNESS_FACTOR; return read(text, font, flatness, geomFact); } /** * Converts text rendered in the given {@link Font} to a {@link Geometry} * * @param text the text to render * @param font the font to render with * @param flatness the flatness to use * @param geomFact the geometryFactory to use to create the result * @return a polygonal geometry representing the rendered text */ public static Geometry read(String text, Font font, double flatness, GeometryFactory geomFact) { char[] chs = text.toCharArray(); FontRenderContext fontContext = new FontRenderContext(null, false, true); GlyphVector gv = font.createGlyphVector(fontContext, chs); List polys = new ArrayList(); for (int i = 0; i < gv.getNumGlyphs(); i++) { Geometry geom = ShapeReader.read(gv.getGlyphOutline(i), flatness, geomFact); for (int j = 0; j < geom.getNumGeometries(); j++) { polys.add(geom.getGeometryN(j)); } } return geomFact.buildGeometry(polys); } } jts-1.11/src/com/vividsolutions/jts/awt/ShapeCollectionPathIterator.java0000644000000000000000000000761611343017562025255 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.util.Collection; import java.util.Iterator; /** * A {@link PathIterator} which provides paths for a collection of {@link Shape}s. * * @author Martin Davis */ public class ShapeCollectionPathIterator implements PathIterator { private Iterator shapeIterator; // initialize with a no-op iterator private PathIterator currentPathIterator = new PathIterator() { public int getWindingRule() { throw new UnsupportedOperationException(); } public boolean isDone() { return true; } public void next() { } public int currentSegment(float[] coords) { throw new UnsupportedOperationException(); } public int currentSegment(double[] coords) { throw new UnsupportedOperationException(); } }; private AffineTransform affineTransform; private boolean done = false; /** * Creates a new path iterator for a collection of {@link Shape}s. * * @param shapes the Shapes in the collection * @param affineTransform a optional transformation to be applied to the coordinates in the path (may be null) */ public ShapeCollectionPathIterator(Collection shapes, AffineTransform affineTransform) { shapeIterator = shapes.iterator(); this.affineTransform = affineTransform; next(); } public int getWindingRule() { /** * WIND_NON_ZERO is more accurate than WIND_EVEN_ODD, and can be comparable * in speed. (See http://www.geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm#Winding%20Number) * However, WIND_NON_ZERO requires that the * shell and holes be oriented in a certain way. * So use WIND_EVEN_ODD. */ return PathIterator.WIND_EVEN_ODD; } public boolean isDone() { return done; } public void next() { currentPathIterator.next(); if (currentPathIterator.isDone() && !shapeIterator.hasNext()) { done = true; return; } if (currentPathIterator.isDone()) { currentPathIterator = ((Shape) shapeIterator.next()).getPathIterator(affineTransform); } } public int currentSegment(float[] coords) { return currentPathIterator.currentSegment(coords); } public int currentSegment(double[] coords) { return currentPathIterator.currentSegment(coords); } } jts-1.11/src/com/vividsolutions/jts/awt/PolygonShape.java0000644000000000000000000001152211343017562022251 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import com.vividsolutions.jts.geom.Coordinate; /** * A Shape which represents a polygon which may contain holes. * Provided because the standard AWT Polygon class does not support holes. * * @author Martin Davis * */ public class PolygonShape implements Shape { private java.awt.Polygon shell; private ArrayList holes = new ArrayList(); /** * Creates a new polygon shape. * * @param shellVertices the vertices of the shell * @param holeVerticesCollection a collection of Coordinate[] for each hole */ public PolygonShape(Coordinate[] shellVertices, Collection holeVerticesCollection) { shell = toPolygon(shellVertices); for (Iterator i = holeVerticesCollection.iterator(); i.hasNext();) { Coordinate[] holeVertices = (Coordinate[]) i.next(); holes.add(toPolygon(holeVertices)); } } private java.awt.Polygon toPolygon(Coordinate[] coordinates) { java.awt.Polygon polygon = new java.awt.Polygon(); for (int i = 0; i < coordinates.length; i++) { polygon.addPoint((int) coordinates[i].x, (int) coordinates[i].y); } return polygon; } public Rectangle getBounds() { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method getBounds() not yet implemented."); } public Rectangle2D getBounds2D() { return shell.getBounds2D(); } public boolean contains(double x, double y) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean contains(Point2D p) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean intersects(double x, double y, double w, double h) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method intersects() not yet implemented."); } public boolean intersects(Rectangle2D r) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method intersects() not yet implemented."); } public boolean contains(double x, double y, double w, double h) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean contains(Rectangle2D r) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public PathIterator getPathIterator(AffineTransform at) { ArrayList rings = new ArrayList(); rings.add(shell); rings.addAll(holes); return new ShapeCollectionPathIterator(rings, at); } public PathIterator getPathIterator(AffineTransform at, double flatness) { // since Geomtery are linear, can simply delegate to the simple method return getPathIterator(at); } } jts-1.11/src/com/vividsolutions/jts/awt/ShapeReader.java0000644000000000000000000001161211343017562022024 0ustar rootrootpackage com.vividsolutions.jts.awt; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.util.ArrayList; import java.util.List; import com.vividsolutions.jts.algorithm.*; import com.vividsolutions.jts.geom.*; /** * Converts a Java2D {@link Shape} * or the more general {@link PathIterator} into a {@link Geometry}. *

* The coordinate system for Java2D is typically screen coordinates, * which has the Y axis inverted * relative to the usual JTS coordinate system. * This is rectified during conversion. *

* PathIterators to be converted are expected to be linear or flat. * That is, they should contain only SEG_MOVETO, SEG_LINETO, and SEG_CLOSE segment types. * Any other segment types will cause an exception. * * @author Martin Davis * */ public class ShapeReader { private static AffineTransform INVERT_Y = AffineTransform.getScaleInstance(1, -1); /** * Converts a flat path to a {@link Geometry}. * * @param pathIt the path to convert * @param geomFact the GeometryFactory to use * @return a Geometry representing the path */ public static Geometry read(PathIterator pathIt, GeometryFactory geomFact) { ShapeReader pc = new ShapeReader(geomFact); return pc.read(pathIt); } /** * Converts a Shape to a Geometry, flattening it first. * * @param shp the Java2D shape * @param flatness the flatness parameter to use * @param geomFact the GeometryFactory to use * @return a Geometry representing the shape */ public static Geometry read(Shape shp, double flatness, GeometryFactory geomFact) { PathIterator pathIt = shp.getPathIterator(INVERT_Y, flatness); return ShapeReader.read(pathIt, geomFact); } private GeometryFactory geometryFactory; public ShapeReader(GeometryFactory geometryFactory) { this.geometryFactory = geometryFactory; } /** * Converts a flat path to a {@link Geometry}. * * @param pathIt the path to convert * @return a Geometry representing the path */ public Geometry read(PathIterator pathIt) { List pathPtSeq = toCoordinates(pathIt); List polys = new ArrayList(); int seqIndex = 0; while (seqIndex < pathPtSeq.size()) { // assume next seq is shell // TODO: test this Coordinate[] pts = (Coordinate[]) pathPtSeq.get(seqIndex); LinearRing shell = geometryFactory.createLinearRing(pts); seqIndex++; List holes = new ArrayList(); // add holes as long as rings are CCW while (seqIndex < pathPtSeq.size() && isHole((Coordinate[]) pathPtSeq.get(seqIndex))) { Coordinate[] holePts = (Coordinate[]) pathPtSeq.get(seqIndex); LinearRing hole = geometryFactory.createLinearRing(holePts); holes.add(hole); seqIndex++; } LinearRing[] holeArray = GeometryFactory.toLinearRingArray(holes); polys.add(geometryFactory.createPolygon(shell, holeArray)); } return geometryFactory.buildGeometry(polys); } private boolean isHole(Coordinate[] pts) { return CGAlgorithms.isCCW(pts); } /** * Extracts the points of the paths in a flat {@link PathIterator} into * a list of Coordinate arrays. * * @param pathIt a path iterator * @return a List of Coordinate arrays * @throws IllegalArgumentException if a non-linear segment type is encountered */ public static List toCoordinates(PathIterator pathIt) { List coordArrays = new ArrayList(); while (! pathIt.isDone()) { Coordinate[] pts = nextCoordinateArray(pathIt); if (pts == null) break; coordArrays.add(pts); } return coordArrays; } private static Coordinate[] nextCoordinateArray(PathIterator pathIt) { double[] pathPt = new double[6]; CoordinateList coordList = null; boolean isDone = false; while (! pathIt.isDone()) { int segType = pathIt.currentSegment(pathPt); switch (segType) { case PathIterator.SEG_MOVETO: if (coordList != null) { // don't advance pathIt, to retain start of next path if any isDone = true; } else { coordList = new CoordinateList(); coordList.add(new Coordinate(pathPt[0], pathPt[1])); pathIt.next(); } break; case PathIterator.SEG_LINETO: coordList.add(new Coordinate(pathPt[0], pathPt[1])); pathIt.next(); break; case PathIterator.SEG_CLOSE: coordList.closeRing(); pathIt.next(); isDone = true; break; default: throw new IllegalArgumentException("unhandled (non-linear) segment type encountered"); } if (isDone) break; } return coordList.toCoordinateArray(); } } jts-1.11/src/com/vividsolutions/jts/awt/ShapeWriter.java0000644000000000000000000001465311343017562022106 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Shape; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.util.ArrayList; import com.vividsolutions.jts.geom.*; /** * Writes {@link Geometry}s into Java2D {@link Shape} objects */ public class ShapeWriter { /** * The point transformation used by default. */ public static final PointTransformation DEFAULT_POINT_TRANSFORMATION = new IdentityPointTransformation(); /** * The point shape factory used by default. */ public static final PointShapeFactory DEFAULT_POINT_FACTORY = new SqarePointShapeFactory(3.0); private PointTransformation pointTransformer = DEFAULT_POINT_TRANSFORMATION; private PointShapeFactory pointFactory = DEFAULT_POINT_FACTORY; /** * Creates a new ShapeWriter with a specified point transformation * and point shape factory. * * @param pointTransformer a transformation from model to view space to use * @param pointFactory the PointShapeFactory to use */ public ShapeWriter(PointTransformation pointTransformer, PointShapeFactory pointFactory) { if (pointTransformer != null) this.pointTransformer = pointTransformer; if (pointFactory != null) this.pointFactory = pointFactory; } /** * Creates a new ShapeWriter with a specified point transformation * and the default point shape factory. * * @param pointTransformer a transformation from model to view space to use */ public ShapeWriter(PointTransformation pointTransformer) { this(pointTransformer, null); } /** * Creates a new ShapeWriter with the default (identity) point transformation. * */ public ShapeWriter() { } /** * Creates a {@link Shape} representing a {@link Geometry}, * according to the specified PointTransformation * and PointShapeFactory (if relevant). *

* Note that Shapes do not * preserve information about which elements in heterogeneous collections * are 1D and which are 2D. * For example, a GeometryCollection containing a ring and a * disk will render as two disks if Graphics.fill is used, * or as two rings if Graphics.draw is used. * To avoid this issue use separate shapes for the components. * * @param geometry the geometry to convert * @return a Shape representing the geometry */ public Shape toShape(Geometry geometry) { if (geometry.isEmpty()) return new GeneralPath(); if (geometry instanceof Polygon) return toShape((Polygon) geometry); if (geometry instanceof LineString) return toShape((LineString) geometry); if (geometry instanceof MultiLineString) return toShape((MultiLineString) geometry); if (geometry instanceof Point) return toShape((Point) geometry); if (geometry instanceof GeometryCollection) return toShape((GeometryCollection) geometry); throw new IllegalArgumentException( "Unrecognized Geometry class: " + geometry.getClass()); } private Shape toShape(Polygon p) { ArrayList holeVertexCollection = new ArrayList(); for (int j = 0; j < p.getNumInteriorRing(); j++) { holeVertexCollection.add( toViewCoordinates(p.getInteriorRingN(j).getCoordinates())); } return new PolygonShape( toViewCoordinates(p.getExteriorRing().getCoordinates()), holeVertexCollection); } private Coordinate[] toViewCoordinates(Coordinate[] modelCoordinates) { Coordinate[] viewCoordinates = new Coordinate[modelCoordinates.length]; for (int i = 0; i < modelCoordinates.length; i++) { Point2D point2D = toPoint(modelCoordinates[i]); viewCoordinates[i] = new Coordinate(point2D.getX(), point2D.getY()); } return viewCoordinates; } private Shape toShape(GeometryCollection gc) { GeometryCollectionShape shape = new GeometryCollectionShape(); for (int i = 0; i < gc.getNumGeometries(); i++) { Geometry g = (Geometry) gc.getGeometryN(i); shape.add(toShape(g)); } return shape; } private GeneralPath toShape(MultiLineString mls) { GeneralPath path = new GeneralPath(); for (int i = 0; i < mls.getNumGeometries(); i++) { LineString lineString = (LineString) mls.getGeometryN(i); path.append(toShape(lineString), false); } return path; } private GeneralPath toShape(LineString lineString) { GeneralPath shape = new GeneralPath(); Point2D viewPoint = toPoint(lineString.getCoordinateN(0)); shape.moveTo((float) viewPoint.getX(), (float) viewPoint.getY()); for (int i = 1; i < lineString.getNumPoints(); i++) { viewPoint = toPoint(lineString.getCoordinateN(i)); shape.lineTo((float) viewPoint.getX(), (float) viewPoint.getY()); } return shape; } private Shape toShape(Point point) { Point2D viewPoint = toPoint(point.getCoordinate()); return pointFactory.createPoint(viewPoint); } private Point2D toPoint(Coordinate model) { Point2D view = new Point2D.Double(); pointTransformer.transform(model, view); /** * Do the rounding now instead of relying on Java 2D rounding. * Java2D seems to do rounding differently for drawing and filling, resulting in the draw * being a pixel off from the fill sometimes. */ view.setLocation(Math.round(view.getX()), Math.round(view.getY())); return view; } } jts-1.11/src/com/vividsolutions/jts/awt/IdentityPointTransformation.java0000644000000000000000000000311711343017562025374 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.geom.Point2D; import com.vividsolutions.jts.geom.Coordinate; /** * Copies point ordinates with no transformation. * * @author Martin Davis * */ public class IdentityPointTransformation implements PointTransformation { public void transform(Coordinate model, Point2D view) { view.setLocation(model.x, model.y); } }jts-1.11/src/com/vividsolutions/jts/awt/SqarePointShapeFactory.java0000644000000000000000000000465211343017562024245 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Shape; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** * A factory for generating square shapes to represent points. * * @author Martin Davis * */ public class SqarePointShapeFactory implements PointShapeFactory { /** * The default length of the square's side. */ public static double DEFAULT_SIZE = 3.0; private double squareSize = DEFAULT_SIZE; /** * Creates a new factory for squares with default size. * */ public SqarePointShapeFactory() { } /** * Creates a factory for squares of given size. * * @param squareSize the length of the side of the square */ public SqarePointShapeFactory(double squareSize) { this.squareSize = squareSize; } /** * Creates a shape representing a point. * * @param point the location of the point * @return a shape */ public Shape createPoint(Point2D point) { Rectangle2D.Double pointMarker = new Rectangle2D.Double( 0.0, 0.0, squareSize, squareSize); pointMarker.x = (double) (point.getX() - (squareSize / 2)); pointMarker.y = (double) (point.getY() - (squareSize / 2)); return pointMarker; } } jts-1.11/src/com/vividsolutions/jts/awt/GeometryCollectionShape.java0000644000000000000000000001032311343017562024427 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.awt; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Iterator; /** * A {@link Shape} which contains a heterogeneous collection of other shapes * representing JTS {@link Geometry}s. * * @author Martin Davis * */ public class GeometryCollectionShape implements Shape { private ArrayList shapes = new ArrayList(); public GeometryCollectionShape() { } public void add(Shape shape) { shapes.add(shape); } public Rectangle getBounds() { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method getBounds() not yet implemented."); } public Rectangle2D getBounds2D() { Rectangle2D rectangle = null; for (Iterator i = shapes.iterator(); i.hasNext();) { Shape shape = (Shape) i.next(); if (rectangle == null) { rectangle = shape.getBounds2D(); } else { rectangle.add(shape.getBounds2D()); } } return rectangle; } public boolean contains(double x, double y) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean contains(Point2D p) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean intersects(double x, double y, double w, double h) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method intersects() not yet implemented."); } public boolean intersects(Rectangle2D r) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method intersects() not yet implemented."); } public boolean contains(double x, double y, double w, double h) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public boolean contains(Rectangle2D r) { /**@todo Implement this java.awt.Shape method*/ throw new java.lang.UnsupportedOperationException( "Method contains() not yet implemented."); } public PathIterator getPathIterator(AffineTransform at) { return new ShapeCollectionPathIterator(shapes, at); } public PathIterator getPathIterator(AffineTransform at, double flatness) { // since Geomtery are linear, can simply delegate to the simple method return getPathIterator(at); } } jts-1.11/src/com/vividsolutions/jts/awt/package.html0000644000000000000000000000031011343017562021250 0ustar rootroot Classes to perform conversions from Java2D shape objects. jts-1.11/src/com/vividsolutions/jts/geom/0000755000000000000000000000000011343017562017131 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/geom/impl/0000755000000000000000000000000011343017562020072 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequenceFactory.java0000644000000000000000000001264311343017562027163 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.impl; import com.vividsolutions.jts.geom.*; /** * Builds packed array coordinate sequences. The array data type can be either * double or float, and defaults to float. */ public class PackedCoordinateSequenceFactory implements CoordinateSequenceFactory { public static final int DOUBLE = 0; public static final int FLOAT = 1; public static final PackedCoordinateSequenceFactory DOUBLE_FACTORY = new PackedCoordinateSequenceFactory(DOUBLE); public static final PackedCoordinateSequenceFactory FLOAT_FACTORY = new PackedCoordinateSequenceFactory(FLOAT); private int type = DOUBLE; private int dimension = 3; /** * Creates a new PackedCoordinateSequenceFactory * of type DOUBLE. */ public PackedCoordinateSequenceFactory() { this(DOUBLE); } /** * Creates a new PackedCoordinateSequenceFactory * of the given type. * Acceptable type values are * {@linkplain PackedCoordinateSequenceFactory#Float}or * {@linkplain PackedCoordinateSequenceFactory#Double} */ public PackedCoordinateSequenceFactory(int type) { this(type, 3); } /** * Creates a new PackedCoordinateSequenceFactory * of the given type. * Acceptable type values are * {@linkplain PackedCoordinateSequenceFactory#FLOAT}or * {@linkplain PackedCoordinateSequenceFactory#DOUBLE} */ public PackedCoordinateSequenceFactory(int type, int dimension) { setType(type); setDimension(dimension); } /** * Returns the type of packed coordinate sequences this factory builds, either * {@linkplain PackedCoordinateSequenceFactory#Float} or * {@linkplain PackedCoordinateSequenceFactory#Double} */ public int getType() { return type; } /** * Sets the type of packed coordinate sequences this factory builds, * acceptable values are {@linkplain PackedCoordinateSequenceFactory#Float}or * {@linkplain PackedCoordinateSequenceFactory#Double} */ public void setType(int type) { if (type != DOUBLE && type != FLOAT) throw new IllegalArgumentException("Unknown type " + type); this.type = type; } public int getDimension() { return dimension; } public void setDimension(int dimension) { this.dimension = dimension; } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.Coordinate[]) */ public CoordinateSequence create(Coordinate[] coordinates) { if (type == DOUBLE) { return new PackedCoordinateSequence.Double(coordinates, dimension); } else { return new PackedCoordinateSequence.Float(coordinates, dimension); } } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence) */ public CoordinateSequence create(CoordinateSequence coordSeq) { if (type == DOUBLE) { return new PackedCoordinateSequence.Double(coordSeq.toCoordinateArray(), dimension); } else { return new PackedCoordinateSequence.Float(coordSeq.toCoordinateArray(), dimension); } } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(double[], * int) */ public CoordinateSequence create(double[] packedCoordinates, int dimension) { if (type == DOUBLE) { return new PackedCoordinateSequence.Double(packedCoordinates, dimension); } else { return new PackedCoordinateSequence.Float(packedCoordinates, dimension); } } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(float[], * int) */ public CoordinateSequence create(float[] packedCoordinates, int dimension) { if (type == DOUBLE) { return new PackedCoordinateSequence.Double(packedCoordinates, dimension); } else { return new PackedCoordinateSequence.Float(packedCoordinates, dimension); } } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int) */ public CoordinateSequence create(int size, int dimension) { if (type == DOUBLE) { return new PackedCoordinateSequence.Double(size, dimension); } else { return new PackedCoordinateSequence.Float(size, dimension); } } }jts-1.11/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequence.java0000644000000000000000000001513111343017562025515 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.impl; import java.io.Serializable; import com.vividsolutions.jts.geom.*; /** * The {@link CoordinateSequence} implementation that {@link Geometry}s use by default. * In this implementation, Coordinates returned by #toArray and #getCoordinate are live -- * modifications to them are actually changing the * CoordinateSequence's underlying data. * * @version 1.7 */ public class CoordinateArraySequence implements CoordinateSequence, Serializable { //With contributions from Markus Schaber [schabios@logi-track.com] 2004-03-26 private static final long serialVersionUID = -915438501601840650L; private Coordinate[] coordinates; /** * Constructs a sequence based on the given array (the * array is not copied). * * @param coordinates the coordinate array that will be referenced. */ public CoordinateArraySequence(Coordinate[] coordinates) { this.coordinates = coordinates; if (coordinates == null) this.coordinates = new Coordinate[0]; } /** * Constructs a sequence of a given size, populated * with new {@link Coordinate}s. * * @param size the size of the sequence to create */ public CoordinateArraySequence(int size) { coordinates = new Coordinate[size]; for (int i = 0; i < size; i++) { coordinates[i] = new Coordinate(); } } /** * Constructs a sequence based on the given array (the * array is not copied). * * @param coordinates the coordinate array that will be referenced. */ public CoordinateArraySequence(CoordinateSequence coordSeq) { if (coordSeq != null) coordinates = new Coordinate[coordSeq.size()]; else coordinates = new Coordinate[0]; for (int i = 0; i < coordinates.length; i++) { coordinates[i] = coordSeq.getCoordinateCopy(i); } } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getDimension() */ public int getDimension() { return 3; } /** * Get the Coordinate with index i. * * @param i * the index of the coordinate * @return the requested Coordinate instance */ public Coordinate getCoordinate(int i) { return coordinates[i]; } /** * Get a copy of the Coordinate with index i. * * @param i the index of the coordinate * @return a copy of the requested Coordinate */ public Coordinate getCoordinateCopy(int i) { return new Coordinate(coordinates[i]); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int) */ public void getCoordinate(int index, Coordinate coord) { coord.x = coordinates[index].x; coord.y = coordinates[index].y; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int) */ public double getX(int index) { return coordinates[index].x; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int) */ public double getY(int index) { return coordinates[index].y; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int) */ public double getOrdinate(int index, int ordinateIndex) { switch (ordinateIndex) { case CoordinateSequence.X: return coordinates[index].x; case CoordinateSequence.Y: return coordinates[index].y; case CoordinateSequence.Z: return coordinates[index].z; } return Double.NaN; } /** * Creates a deep copy of the Object * * @return The deep copy */ public Object clone() { Coordinate[] cloneCoordinates = new Coordinate[size()]; for (int i = 0; i < coordinates.length; i++) { cloneCoordinates[i] = (Coordinate) coordinates[i].clone(); } return new CoordinateArraySequence(cloneCoordinates); } /** * Returns the size of the coordinate sequence * * @return the number of coordinates */ public int size() { return coordinates.length; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#setOrdinate(int, int, double) */ public void setOrdinate(int index, int ordinateIndex, double value) { switch (ordinateIndex) { case CoordinateSequence.X: coordinates[index].x = value; break; case CoordinateSequence.Y: coordinates[index].y = value; break; case CoordinateSequence.Z: coordinates[index].z = value; break; default: throw new IllegalArgumentException("invalid ordinateIndex"); } } /** * This method exposes the internal Array of Coordinate Objects * * @return the Coordinate[] array. */ public Coordinate[] toCoordinateArray() { return coordinates; } public Envelope expandEnvelope(Envelope env) { for (int i = 0; i < coordinates.length; i++ ) { env.expandToInclude(coordinates[i]); } return env; } /** * Returns the string Representation of the coordinate array * * @return The string */ public String toString() { if (coordinates.length > 0) { StringBuffer strBuf = new StringBuffer(17 * coordinates.length); strBuf.append('('); strBuf.append(coordinates[0]); for (int i = 1; i < coordinates.length; i++) { strBuf.append(", "); strBuf.append(coordinates[i]); } strBuf.append(')'); return strBuf.toString(); } else { return "()"; } } }jts-1.11/src/com/vividsolutions/jts/geom/impl/PackedCoordinateSequence.java0000644000000000000000000003274011343017562025633 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.impl; import com.vividsolutions.jts.geom.*; import java.lang.ref.SoftReference; /** * A {@link CoordinateSequence} implementation based on a packed arrays. * In this implementation, {@link Coordinate}s returned by #toArray and #get are copies * of the internal values. * To change the actual values, use the provided setters. *

* For efficiency, created Coordinate arrays * are cached using a soft reference. * The cache is cleared each time the coordinate sequence contents are * modified through a setter method. * * @version 1.7 */ public abstract class PackedCoordinateSequence implements CoordinateSequence { /** * The dimensions of the coordinates hold in the packed array */ protected int dimension; /** * A soft reference to the Coordinate[] representation of this sequence. * Makes repeated coordinate array accesses more efficient. */ protected SoftReference coordRef; /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getDimension() */ public int getDimension() { return this.dimension; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ public Coordinate getCoordinate(int i) { Coordinate[] coords = getCachedCoords(); if(coords != null) return coords[i]; else return getCoordinateInternal(i); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ public Coordinate getCoordinateCopy(int i) { return getCoordinateInternal(i); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ public void getCoordinate(int i, Coordinate coord) { coord.x = getOrdinate(i, 0); coord.y = getOrdinate(i, 1); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#toCoordinateArray() */ public Coordinate[] toCoordinateArray() { Coordinate[] coords = getCachedCoords(); // testing - never cache if (coords != null) return coords; coords = new Coordinate[size()]; for (int i = 0; i < coords.length; i++) { coords[i] = getCoordinateInternal(i); } coordRef = new SoftReference(coords); return coords; } /** * @return */ private Coordinate[] getCachedCoords() { if (coordRef != null) { Coordinate[] coords = (Coordinate[]) coordRef.get(); if (coords != null) { return coords; } else { // System.out.print("-"); coordRef = null; return null; } } else { // System.out.print("-"); return null; } } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getX(int) */ public double getX(int index) { return getOrdinate(index, 0); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getY(int) */ public double getY(int index) { return getOrdinate(index, 1); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int) */ public abstract double getOrdinate(int index, int ordinateIndex); /** * Sets the first ordinate of a coordinate in this sequence. * * @param index the coordinate index * @param value the new ordinate value */ public void setX(int index, double value) { coordRef = null; setOrdinate(index, 0, value); } /** * Sets the second ordinate of a coordinate in this sequence. * * @param index the coordinate index * @param value the new ordinate value */ public void setY(int index, double value) { coordRef = null; setOrdinate(index, 1, value); } /** * Returns a Coordinate representation of the specified coordinate, by always * building a new Coordinate object * * @param index * @return */ protected abstract Coordinate getCoordinateInternal(int index); /** * @see java.lang.Object#clone() */ public abstract Object clone(); /** * Sets the ordinate of a coordinate in this sequence. *
* Warning: for performance reasons the ordinate index is not checked * - if it is over dimensions you may not get an exception but a meaningless value. * * @param index * the coordinate index * @param ordinate * the ordinate index in the coordinate, 0 based, smaller than the * number of dimensions * @param value * the new ordinate value */ public abstract void setOrdinate(int index, int ordinate, double value); /** * Packed coordinate sequence implementation based on doubles */ public static class Double extends PackedCoordinateSequence { /** * The packed coordinate array */ double[] coords; /** * Builds a new packed coordinate sequence * * @param coords * @param dimensions */ public Double(double[] coords, int dimensions) { if (dimensions < 2) { throw new IllegalArgumentException("Must have at least 2 dimensions"); } if (coords.length % dimensions != 0) { throw new IllegalArgumentException("Packed array does not contain " + "an integral number of coordinates"); } this.dimension = dimensions; this.coords = coords; } /** * Builds a new packed coordinate sequence out of a float coordinate array * * @param coordinates */ public Double(float[] coordinates, int dimensions) { this.coords = new double[coordinates.length]; this.dimension = dimensions; for (int i = 0; i < coordinates.length; i++) { this.coords[i] = coordinates[i]; } } /** * Builds a new packed coordinate sequence out of a coordinate array * * @param coordinates */ public Double(Coordinate[] coordinates, int dimension) { if (coordinates == null) coordinates = new Coordinate[0]; this.dimension = dimension; coords = new double[coordinates.length * this.dimension]; for (int i = 0; i < coordinates.length; i++) { coords[i * this.dimension] = coordinates[i].x; if (this.dimension >= 2) coords[i * this.dimension + 1] = coordinates[i].y; if (this.dimension >= 3) coords[i * this.dimension + 2] = coordinates[i].z; } } /** * Builds a new packed coordinate sequence out of a coordinate array * * @param coordinates */ public Double(Coordinate[] coordinates) { this(coordinates, 3); } /** * Builds a new empty packed coordinate sequence of a given size and dimension * * @param coordinates */ public Double(int size, int dimension) { this.dimension = dimension; coords = new double[size * this.dimension]; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ public Coordinate getCoordinateInternal(int i) { double x = coords[i * dimension]; double y = coords[i * dimension + 1]; double z = dimension == 2 ? Coordinate.NULL_ORDINATE : coords[i * dimension + 2]; return new Coordinate(x, y, z); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#size() */ public int size() { return coords.length / dimension; } /** * @see java.lang.Object#clone() */ public Object clone() { double[] clone = new double[coords.length]; System.arraycopy(coords, 0, clone, 0, coords.length); return new Double(clone, dimension); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int) * Beware, for performace reasons the ordinate index is not checked, if * it's over dimensions you may not get an exception but a meaningless * value. */ public double getOrdinate(int index, int ordinate) { return coords[index * dimension + ordinate]; } /** * @see com.vividsolutions.jts.geom.PackedCoordinateSequence#setOrdinate(int, * int, double) */ public void setOrdinate(int index, int ordinate, double value) { coordRef = null; coords[index * dimension + ordinate] = value; } public Envelope expandEnvelope(Envelope env) { for (int i = 0; i < coords.length; i += dimension ) { env.expandToInclude(coords[i], coords[i + 1]); } return env; } } /** * Packed coordinate sequence implementation based on floats */ public static class Float extends PackedCoordinateSequence { /** * The packed coordinate array */ float[] coords; /** * Constructs a packed coordinate sequence from an array of floats * * @param coords * @param dimensions */ public Float(float[] coords, int dimensions) { if (dimensions < 2) { throw new IllegalArgumentException("Must have at least 2 dimensions"); } if (coords.length % dimensions != 0) { throw new IllegalArgumentException("Packed array does not contain " + "an integral number of coordinates"); } this.dimension = dimensions; this.coords = coords; } /** * Constructs a packed coordinate sequence from an array of doubles * * @param coordinates * @param dimension */ public Float(double[] coordinates, int dimensions) { this.coords = new float[coordinates.length]; this.dimension = dimensions; for (int i = 0; i < coordinates.length; i++) { this.coords[i] = (float) coordinates[i]; } } /** * Constructs a packed coordinate sequence out of a coordinate array * * @param coordinates */ public Float(Coordinate[] coordinates, int dimension) { if (coordinates == null) coordinates = new Coordinate[0]; this.dimension = dimension; coords = new float[coordinates.length * this.dimension]; for (int i = 0; i < coordinates.length; i++) { coords[i * this.dimension] = (float) coordinates[i].x; if (this.dimension >= 2) coords[i * this.dimension + 1] = (float) coordinates[i].y; if (this.dimension >= 3) coords[i * this.dimension + 2] = (float) coordinates[i].z; } } /** * Constructs an empty packed coordinate sequence of a given size and dimension * * @param coordinates */ public Float(int size, int dimension) { this.dimension = dimension; coords = new float[size * this.dimension]; } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getCoordinate(int) */ public Coordinate getCoordinateInternal(int i) { double x = coords[i * dimension]; double y = coords[i * dimension + 1]; double z = dimension == 2 ? Coordinate.NULL_ORDINATE : coords[i * dimension + 2]; return new Coordinate(x, y, z); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#size() */ public int size() { return coords.length / dimension; } /** * @see java.lang.Object#clone() */ public Object clone() { float[] clone = new float[coords.length]; System.arraycopy(coords, 0, clone, 0, coords.length); return new Float(clone, dimension); } /** * @see com.vividsolutions.jts.geom.CoordinateSequence#getOrdinate(int, int) * Beware, for performace reasons the ordinate index is not checked, if * it's over dimensions you may not get an exception but a meaningless * value. */ public double getOrdinate(int index, int ordinate) { return coords[index * dimension + ordinate]; } /** * @see com.vividsolutions.jts.geom.PackedCoordinateSequence#setOrdinate(int, * int, double) */ public void setOrdinate(int index, int ordinate, double value) { coordRef = null; coords[index * dimension + ordinate] = (float) value; } public Envelope expandEnvelope(Envelope env) { for (int i = 0; i < coords.length; i += dimension ) { env.expandToInclude(coords[i], coords[i + 1]); } return env; } } }jts-1.11/src/com/vividsolutions/jts/geom/impl/CoordinateArraySequenceFactory.java0000644000000000000000000000606611343017562027054 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.impl; import java.io.Serializable; import com.vividsolutions.jts.geom.*; /** * Creates {@link CoordinateSequence}s represented as an array of {@link Coordinate}s. * * @version 1.7 */ public final class CoordinateArraySequenceFactory implements CoordinateSequenceFactory, Serializable { private static final long serialVersionUID = -4099577099607551657L; private static CoordinateArraySequenceFactory instanceObject = new CoordinateArraySequenceFactory(); private CoordinateArraySequenceFactory() { } private Object readResolve() { // http://www.javaworld.com/javaworld/javatips/jw-javatip122.html return CoordinateArraySequenceFactory.instance(); } /** * Returns the singleton instance of {@link CoordinateArraySequenceFactory} */ public static CoordinateArraySequenceFactory instance() { return instanceObject; } /** * Returns a {@link CoordinateArraySequence} based on the given array (the array is * not copied). * * @param coordinates * the coordinates, which may not be null nor contain null * elements */ public CoordinateSequence create(Coordinate[] coordinates) { return new CoordinateArraySequence(coordinates); } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(com.vividsolutions.jts.geom.CoordinateSequence) */ public CoordinateSequence create(CoordinateSequence coordSeq) { return new CoordinateArraySequence(coordSeq); } /** * @see com.vividsolutions.jts.geom.CoordinateSequenceFactory#create(int, int) * * @throws IllegalArgumentException if the dimension is > 3 */ public CoordinateSequence create(int size, int dimension) { if (dimension > 3) throw new IllegalArgumentException("dimension must be <= 3"); return new CoordinateArraySequence(size); } }jts-1.11/src/com/vividsolutions/jts/geom/impl/package.html0000644000000000000000000000030611343017562022352 0ustar rootroot Implementations of interfaces for geometric structures. jts-1.11/src/com/vividsolutions/jts/geom/prep/0000755000000000000000000000000011343017562020077 5ustar rootrootjts-1.11/src/com/vividsolutions/jts/geom/prep/PreparedGeometryFactory.java0000644000000000000000000000514611343017562025556 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.prep; import com.vividsolutions.jts.geom.*; /** * A factory for creating {@link PreparedGeometry}s. * It chooses an appropriate implementation of PreparedGeometry * based on the geoemtric type of the input geometry. *

* In the future, the factory may accept hints that indicate * special optimizations which can be performed. * * * @author Martin Davis * */ public class PreparedGeometryFactory { /** * Creates a new {@link PreparedGeometry} appropriate for the argument {@link Geometry}. * * @param geom the geometry to prepare * @return the prepared geometry */ public static PreparedGeometry prepare(Geometry geom) { return (new PreparedGeometryFactory()).create(geom); } public PreparedGeometryFactory() { } /** * Creates a new {@link PreparedGeometry} appropriate for the argument {@link Geometry}. * * @param geom the geometry to prepare * @return the prepared geometry */ public PreparedGeometry create(Geometry geom) { if (geom instanceof Polygonal) return new PreparedPolygon((Polygonal) geom); if (geom instanceof Lineal) return new PreparedLineString((Lineal) geom); if (geom instanceof Puntal) return new PreparedPoint((Puntal) geom); /** * Default representation. */ return new BasicPreparedGeometry(geom); } } jts-1.11/src/com/vividsolutions/jts/geom/prep/PreparedPoint.java0000644000000000000000000000372111343017562023521 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.prep; import com.vividsolutions.jts.geom.*; /** * A prepared version for {@link Puntal} geometries. * * @author Martin Davis * */ public class PreparedPoint extends BasicPreparedGeometry { public PreparedPoint(Puntal point) { super((Geometry) point); } /** * Tests whether this point intersects a {@link Geometry}. *

* The optimization here is that computing topology for the test geometry * is avoided. This can be significant for large geometries. */ public boolean intersects(Geometry g) { if (! envelopesIntersect(g)) return false; /** * This avoids computing topology for the test geometry */ return isAnyTargetComponentInTest(g); } } jts-1.11/src/com/vividsolutions/jts/geom/prep/AbstractPreparedPolygonContains.java0000644000000000000000000002203411343017562027240 0ustar rootroot/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.vividsolutions.jts.geom.prep; import java.util.*; import com.vividsolutions.jts.algorithm.*; import com.vividsolutions.jts.geom.*; import com.vividsolutions.jts.noding.*; import com.vividsolutions.jts.geom.util.*; /** * A base class containing the logic for computes the contains * and covers spatial relationship predicates * for a {@link PreparedPolygon} relative to all other {@link Geometry} classes. * Uses short-circuit tests and indexing to improve performance. *

* Contains and covers are very similar, and differ only in how certain * cases along the boundary are handled. These cases require * full topological evaluation to handle, so all the code in * this class is common to both predicates. *

* It is not possible to short-circuit in all cases, in particular * in the case where line segments of the test geometry touches the polygon linework. * In this case full topology must be computed. * (However, if the test geometry consists of only points, this * can be evaluated in an optimized fashion. * * @author Martin Davis * */ public abstract class AbstractPreparedPolygonContains extends PreparedPolygonPredicate { /** * This flag controls a difference between contains and covers. * * For contains the value is true. * For covers the value is false. */ protected boolean requireSomePointInInterior = true; // information about geometric situation private boolean hasSegmentIntersection = false; private boolean hasProperIntersection = false; private boolean hasNonProperIntersection = false; /** * Creates an instance of this operation. * * @param prepPoly the PreparedPolygon to evaluate */ public AbstractPreparedPolygonContains(PreparedPolygon prepPoly) { super(prepPoly); } /** * Evaluate the contains or covers relationship * for the given geometry. * * @param geom the test geometry * @return true if the test geometry is contained */ protected boolean eval(Geometry geom) { /** * Do point-in-poly tests first, since they are cheaper and may result * in a quick negative result. * * If a point of any test components does not lie in target, result is false */ boolean isAllInTargetArea = isAllTestComponentsInTarget(geom); if (! isAllInTargetArea) return false; /** * If the test geometry consists of only Points, * then it is now sufficient to test if any of those * points lie in the interior of the target geometry. * If so, the test is contained. * If not, all points are on the boundary of the area, * which implies not contained. */ if (requireSomePointInInterior && geom.getDimension() == 0) { boolean isAnyInTargetInterior = isAnyTestComponentInTargetInterior(geom); return isAnyInTargetInterior; } /** * Check if there is any intersection between the line segments * in target and test. * In some important cases, finding a proper interesection implies that the * test geometry is NOT contained. * These cases are: *