0001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/spatialschema/GeometryFactory.java $
0002: /*---------------- FILE HEADER ------------------------------------------
0003:
0004: This file is part of deegree.
0005: Copyright (C) 2001-2008 by:
0006: EXSE, Department of Geography, University of Bonn
0007: http://www.giub.uni-bonn.de/deegree/
0008: lat/lon GmbH
0009: http://www.lat-lon.de
0010:
0011: This library is free software; you can redistribute it and/or
0012: modify it under the terms of the GNU Lesser General Public
0013: License as published by the Free Software Foundation; either
0014: version 2.1 of the License, or (at your option) any later version.
0015:
0016: This library is distributed in the hope that it will be useful,
0017: but WITHOUT ANY WARRANTY; without even the implied warranty of
0018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019: Lesser General Public License for more details.
0020:
0021: You should have received a copy of the GNU Lesser General Public
0022: License along with this library; if not, write to the Free Software
0023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0024:
0025: Contact:
0026:
0027: Andreas Poth
0028: lat/lon GmbH
0029: Aennchenstr. 19
0030: 53115 Bonn
0031: Germany
0032: E-Mail: poth@lat-lon.de
0033:
0034: Prof. Dr. Klaus Greve
0035: Department of Geography
0036: University of Bonn
0037: Meckenheimer Allee 166
0038: 53115 Bonn
0039: Germany
0040: E-Mail: greve@giub.uni-bonn.de
0041:
0042:
0043: ---------------------------------------------------------------------------*/
0044: package org.deegree.model.spatialschema;
0045:
0046: import java.util.ArrayList;
0047:
0048: import javax.vecmath.Point3d;
0049:
0050: import org.deegree.framework.util.StringTools;
0051: import org.deegree.model.crs.CoordinateSystem;
0052:
0053: /**
0054: * Factory to create geometry instances.
0055: *
0056: * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
0057: * @version $Revision: 10278 $, $Date: 2008-02-25 06:53:37 -0800 (Mon, 25 Feb 2008) $
0058: *
0059: */
0060: public final class GeometryFactory {
0061:
0062: private GeometryFactory() {
0063: // Hidden default constructor.
0064: }
0065:
0066: /**
0067: * creates a Envelope object out from two corner coordinates
0068: *
0069: * @param minx
0070: * lower x-axis coordinate
0071: * @param miny
0072: * lower y-axis coordinate
0073: * @param maxx
0074: * upper x-axis coordinate
0075: * @param maxy
0076: * upper y-axis coordinate
0077: * @param crs
0078: * The coordinate system
0079: * @return an Envelope with given parameters
0080: */
0081: public static Envelope createEnvelope(double minx, double miny,
0082: double maxx, double maxy, CoordinateSystem crs) {
0083: Position min = createPosition(minx, miny);
0084: Position max = createPosition(maxx, maxy);
0085: return new EnvelopeImpl(min, max, crs);
0086: }
0087:
0088: /**
0089: * creates a Envelope object out from two corner coordinates
0090: *
0091: * @param min
0092: * lower point
0093: * @param max
0094: * upper point
0095: * @param crs
0096: * The coordinate system
0097: * @return an Envelope with given parameters
0098: */
0099: public static Envelope createEnvelope(Position min, Position max,
0100: CoordinateSystem crs) {
0101: return new EnvelopeImpl(min, max, crs);
0102: }
0103:
0104: /**
0105: * creates an Envelope from a comma seperated String; e.g.: 10,34,15,48
0106: *
0107: * @param bbox
0108: * the boundingbox of the created Envelope
0109: * @param crs
0110: * The coordinate system
0111: * @return an Envelope with given parameters
0112: */
0113: public static Envelope createEnvelope(String bbox,
0114: CoordinateSystem crs) {
0115: double[] d = StringTools.toArrayDouble(bbox, ",");
0116: return createEnvelope(d[0], d[1], d[2], d[3], crs);
0117: }
0118:
0119: /**
0120: * creates a Position from two coordinates.
0121: *
0122: * @param x
0123: * coordinate on the x-axis
0124: * @param y
0125: * coordinate on the y-axis
0126: * @return a Position defining position x, y
0127: */
0128: public static Position createPosition(double x, double y) {
0129: return new PositionImpl(x, y);
0130: }
0131:
0132: /**
0133: * creates a Position from three coordinates.
0134: *
0135: * @param x
0136: * coordinate on the x-axis
0137: * @param y
0138: * coordinate on the y-axis
0139: * @param z
0140: * coordinate on the z-axis
0141: * @return a Position defining position x, y, z
0142: */
0143: public static Position createPosition(double x, double y, double z) {
0144: return new PositionImpl(new double[] { x, y, z });
0145: }
0146:
0147: /**
0148: * creates a Position from a point3d.
0149: *
0150: * @param coordinates
0151: * the coordinates to create the position from.
0152: * @return a Position defining position x, y, z
0153: */
0154: public static Position createPosition(Point3d coordinates) {
0155: return new PositionImpl(coordinates);
0156: }
0157:
0158: /**
0159: * creates a Position from an array of double.
0160: *
0161: * @param p
0162: * list of points
0163: * @return the Position defined by the array.
0164: */
0165: public static Position createPosition(double[] p) {
0166: return new PositionImpl(p);
0167: }
0168:
0169: /**
0170: * creates a Point from two coordinates.
0171: *
0172: * @param x
0173: * x coordinate
0174: * @param y
0175: * y coordinate
0176: * @param crs
0177: * spatial reference system of the point geometry
0178: * @return a Position defining position x, y in the given CRS
0179: */
0180: public static Point createPoint(double x, double y,
0181: CoordinateSystem crs) {
0182: return new PointImpl(x, y, crs);
0183: }
0184:
0185: /**
0186: * creates a Point from two coordinates.
0187: *
0188: * @param x
0189: * x coordinate
0190: * @param y
0191: * y coordinate
0192: * @param z
0193: * coordinate on the z-axis
0194: * @param crs
0195: * spatial reference system of the point geometry
0196: * @return a Position defining position x, y, z in the given CRS
0197: */
0198: public static Point createPoint(double x, double y, double z,
0199: CoordinateSystem crs) {
0200: return new PointImpl(x, y, z, crs);
0201: }
0202:
0203: /**
0204: * creates a Point from a position.
0205: *
0206: * @param position
0207: * position
0208: * @param crs
0209: * spatial reference system of the point geometry
0210: * @return the Position defined by the array in the given CRS
0211: */
0212: public static Point createPoint(Position position,
0213: CoordinateSystem crs) {
0214: return new PointImpl(position, crs);
0215: }
0216:
0217: /**
0218: * creates a Point from a wkb.
0219: *
0220: * @param wkb
0221: * geometry in Well-Known Binary (WKB) format
0222: * @param srs
0223: * spatial reference system of the geometry
0224: * @return the Position defined by the WKB and the given CRS
0225: * @throws GeometryException
0226: * if the wkb is not known or invalid
0227: */
0228: public static Point createPoint(byte[] wkb, CoordinateSystem srs)
0229: throws GeometryException {
0230: int wkbType = -1;
0231: double x = 0;
0232: double y = 0;
0233:
0234: byte byteorder = wkb[0];
0235:
0236: if (byteorder == 0) {
0237: wkbType = ByteUtils.readBEInt(wkb, 1);
0238: } else {
0239: wkbType = ByteUtils.readLEInt(wkb, 1);
0240: }
0241:
0242: if (wkbType != 1) {
0243: throw new GeometryException("invalid byte stream");
0244: }
0245:
0246: if (byteorder == 0) {
0247: x = ByteUtils.readBEDouble(wkb, 5);
0248: y = ByteUtils.readBEDouble(wkb, 13);
0249: } else {
0250: x = ByteUtils.readLEDouble(wkb, 5);
0251: y = ByteUtils.readLEDouble(wkb, 13);
0252: }
0253:
0254: return new PointImpl(x, y, srs);
0255: }
0256:
0257: /**
0258: * creates a CurveSegment from an array of points.
0259: *
0260: * @param points
0261: * array of Point
0262: * @param crs
0263: * CS_CoordinateSystem spatial reference system of the curve
0264: * @return A curve defined by the given Points in the CRS.
0265: * @throws GeometryException
0266: * if the point array is empty
0267: */
0268: public static CurveSegment createCurveSegment(Position[] points,
0269: CoordinateSystem crs) throws GeometryException {
0270: return new LineStringImpl(points, crs);
0271: }
0272:
0273: /**
0274: * creates a Curve from an array of Positions.
0275: *
0276: * @param positions
0277: * positions
0278: * @param crs
0279: * spatial reference system of the geometry
0280: * @return A curve defined by the given Points in the CRS.
0281: * @throws GeometryException
0282: * if the point array is empty
0283: */
0284: public static Curve createCurve(Position[] positions,
0285: CoordinateSystem crs) throws GeometryException {
0286: CurveSegment[] cs = new CurveSegment[1];
0287: cs[0] = createCurveSegment(positions, crs);
0288: return new CurveImpl(cs);
0289: }
0290:
0291: /**
0292: * creates a Curve from one curve segment.
0293: *
0294: * @param segment
0295: * CurveSegments
0296: * @return a new CurveSegment
0297: * @throws GeometryException
0298: * if the segment is null
0299: */
0300: public static Curve createCurve(CurveSegment segment)
0301: throws GeometryException {
0302: return new CurveImpl(new CurveSegment[] { segment });
0303: }
0304:
0305: /**
0306: * creates a Curve from an array of curve segments.
0307: *
0308: * @param segments
0309: * array of CurveSegments
0310: * @return a new CurveSegment
0311: * @throws GeometryException
0312: * if the segment is null or has no values
0313: *
0314: */
0315: public static Curve createCurve(CurveSegment[] segments)
0316: throws GeometryException {
0317: return new CurveImpl(segments);
0318: }
0319:
0320: /**
0321: * creates a Curve from an array of curve segments.
0322: *
0323: * @param segments
0324: * array of CurveSegments
0325: * @param crs
0326: * @return a new CurveSegment
0327: * @throws GeometryException
0328: * if the segment is null or has no values
0329: *
0330: */
0331: public static Curve createCurve(CurveSegment[] segments,
0332: CoordinateSystem crs) throws GeometryException {
0333: return new CurveImpl(segments, crs);
0334: }
0335:
0336: /**
0337: * creates a GM_Curve from an array of ordinates
0338: *
0339: * TODO: If resources are available, think about good programming style.
0340: *
0341: * @param ord
0342: * the ordinates
0343: * @param dim
0344: * the dimension of the ordinates
0345: * @param crs
0346: * the spatial reference system of the geometry
0347: *
0348: * @return the Curve defined by the given parameters
0349: * @throws GeometryException
0350: * if the ord array is empty
0351: */
0352: public static Curve createCurve(double[] ord, int dim,
0353: CoordinateSystem crs) throws GeometryException {
0354: Position[] pos = new Position[ord.length / dim];
0355: int i = 0;
0356: while (i < ord.length) {
0357: double[] o = new double[dim];
0358: for (int j = 0; j < dim; j++) {
0359: o[j] = ord[i++];
0360: }
0361: pos[i / dim - 1] = GeometryFactory.createPosition(o);
0362: }
0363: return GeometryFactory.createCurve(pos, crs);
0364: }
0365:
0366: /**
0367: * creates a SurfacePatch from array(s) of Position
0368: *
0369: * @param exteriorRing
0370: * exterior ring of the patch
0371: * @param interiorRings
0372: * interior rings of the patch
0373: * @param si
0374: * SurfaceInterpolation
0375: * @param crs
0376: * CS_CoordinateSystem spatial reference system of the surface patch
0377: * @return a Surfacepatch defined by the given Parameters
0378: * @throws GeometryException
0379: */
0380: public static SurfacePatch createSurfacePatch(
0381: Position[] exteriorRing, Position[][] interiorRings,
0382: SurfaceInterpolation si, CoordinateSystem crs)
0383: throws GeometryException {
0384: return new PolygonImpl(si, exteriorRing, interiorRings, crs);
0385: }
0386:
0387: /**
0388: *
0389: * @param exteriorRing
0390: * @param interiorRings
0391: * @param crs
0392: * @return
0393: * @throws GeometryException
0394: */
0395: public static SurfacePatch createSurfacePatch(
0396: CurveSegment[] exteriorRing,
0397: CurveSegment[][] interiorRings, CoordinateSystem crs)
0398: throws GeometryException {
0399: Ring eRing = new RingImpl(exteriorRing, crs, '+');
0400: Ring[] iRings = null;
0401: if (interiorRings != null) {
0402: iRings = new Ring[interiorRings.length];
0403: for (int i = 0; i < iRings.length; i++) {
0404: iRings[i] = new RingImpl(interiorRings[i], crs, '+');
0405: }
0406: }
0407: return new PolygonImpl(eRing, iRings, crs);
0408: }
0409:
0410: /**
0411: *
0412: * @param exteriorRing
0413: * @param interiorRings
0414: * @param crs
0415: * @return
0416: * @throws GeometryException
0417: */
0418: public static SurfacePatch createSurfacePatch(Curve exteriorRing,
0419: Curve[] interiorRings, CoordinateSystem crs)
0420: throws GeometryException {
0421: CurveSegment[] e = exteriorRing.getCurveSegments();
0422: CurveSegment[][] i = null;
0423: if (interiorRings != null) {
0424: i = new CurveSegment[interiorRings.length][];
0425: for (int j = 0; j < i.length; j++) {
0426: i[j] = interiorRings[j].getCurveSegments();
0427: }
0428: }
0429: return createSurfacePatch(e, i, crs);
0430: }
0431:
0432: /**
0433: * creates a Curve from a wkb.
0434: *
0435: * @param wkb
0436: * byte stream that contains the wkb information
0437: * @param crs
0438: * CS_CoordinateSystem spatial reference system of the curve
0439: * @return the Curve defined by the WKB and the given CRS
0440: * @throws GeometryException
0441: * if the wkb is not known or invalid
0442: *
0443: */
0444: public static Curve createCurve(byte[] wkb, CoordinateSystem crs)
0445: throws GeometryException {
0446: int wkbType = -1;
0447: int numPoints = -1;
0448: Position[] points = null;
0449: double x = 0;
0450: double y = 0;
0451:
0452: byte byteorder = wkb[0];
0453:
0454: if (byteorder == 0) {
0455: wkbType = ByteUtils.readBEInt(wkb, 1);
0456: } else {
0457: wkbType = ByteUtils.readLEInt(wkb, 1);
0458: }
0459:
0460: // check if it's realy a linestrin/curve
0461: if (wkbType != 2) {
0462: throw new GeometryException("invalid byte stream for Curve");
0463: }
0464:
0465: // read number of points
0466: if (byteorder == 0) {
0467: numPoints = ByteUtils.readBEInt(wkb, 5);
0468: } else {
0469: numPoints = ByteUtils.readLEInt(wkb, 5);
0470: }
0471:
0472: int offset = 9;
0473:
0474: points = new Position[numPoints];
0475:
0476: // read the i-th point depending on the byteorde
0477: if (byteorder == 0) {
0478: for (int i = 0; i < numPoints; i++) {
0479: x = ByteUtils.readBEDouble(wkb, offset);
0480: offset += 8;
0481: y = ByteUtils.readBEDouble(wkb, offset);
0482: offset += 8;
0483: points[i] = new PositionImpl(x, y);
0484: }
0485: } else {
0486: for (int i = 0; i < numPoints; i++) {
0487: x = ByteUtils.readLEDouble(wkb, offset);
0488: offset += 8;
0489: y = ByteUtils.readLEDouble(wkb, offset);
0490: offset += 8;
0491: points[i] = new PositionImpl(x, y);
0492: }
0493: }
0494:
0495: CurveSegment[] segment = new CurveSegment[1];
0496:
0497: segment[0] = createCurveSegment(points, crs);
0498:
0499: return createCurve(segment);
0500: }
0501:
0502: /**
0503: * creates a Surface composed of one SurfacePatch from array(s) of Position
0504: *
0505: * @param exteriorRing
0506: * exterior ring of the patch
0507: * @param interiorRings
0508: * interior rings of the patch
0509: * @param si
0510: * SurfaceInterpolation
0511: * @param crs
0512: * CS_CoordinateSystem spatial reference system of the surface patch
0513: * @return a Surface composed of one SurfacePatch from array(s) of Position
0514: * @throws GeometryException
0515: * if the implicite orientation is not '+' or '-', or the rings aren't closed
0516: */
0517: public static Surface createSurface(Position[] exteriorRing,
0518: Position[][] interiorRings, SurfaceInterpolation si,
0519: CoordinateSystem crs) throws GeometryException {
0520: SurfacePatch sp = new PolygonImpl(si, exteriorRing,
0521: interiorRings, crs);
0522: return createSurface(sp);
0523: }
0524:
0525: /**
0526: * creates a Surface from an array of SurfacePatch.
0527: *
0528: * @param patch
0529: * patches that build the surface
0530: * @return a Surface from an array of SurfacePatch.
0531: * @throws GeometryException
0532: * if implicite the orientation is not '+' or '-'
0533: */
0534: public static Surface createSurface(SurfacePatch patch)
0535: throws GeometryException {
0536: return new SurfaceImpl(patch);
0537: }
0538:
0539: /**
0540: * creates a Surface from an array of SurfacePatch.
0541: *
0542: * @param patches
0543: * patches that build the surface
0544: *
0545: * @return a Surface from an array of SurfacePatch.
0546: * @throws GeometryException
0547: * if implicite the orientation is not '+' or '-'
0548: */
0549: public static Surface createSurface(SurfacePatch[] patches)
0550: throws GeometryException {
0551: return new SurfaceImpl(patches);
0552: }
0553:
0554: /**
0555: * creates a Surface from an array of SurfacePatch.
0556: *
0557: * @param patches
0558: * patches that build the surface
0559: * @param crs
0560: *
0561: * @return a Surface from an array of SurfacePatch.
0562: * @throws GeometryException
0563: * if implicite the orientation is not '+' or '-'
0564: */
0565: public static Surface createSurface(SurfacePatch[] patches,
0566: CoordinateSystem crs) throws GeometryException {
0567: return new SurfaceImpl(patches, crs);
0568: }
0569:
0570: /**
0571: * creates a Surface from a wkb.
0572: *
0573: * @param wkb
0574: * byte stream that contains the wkb information
0575: * @param crs
0576: * CS_CoordinateSystem spatial reference system of the curve
0577: * @param si
0578: * SurfaceInterpolation
0579: * @return a Surface from a wkb.
0580: * @throws GeometryException
0581: * if the implicite orientation is not '+' or '-' or the wkb is not known or invalid
0582: */
0583: public static Surface createSurface(byte[] wkb,
0584: CoordinateSystem crs, SurfaceInterpolation si)
0585: throws GeometryException {
0586: int wkbtype = -1;
0587: int numRings = 0;
0588: int numPoints = 0;
0589: int offset = 0;
0590: double x = 0;
0591: double y = 0;
0592:
0593: Position[] externalBoundary = null;
0594: Position[][] internalBoundaries = null;
0595:
0596: byte byteorder = wkb[offset++];
0597:
0598: if (byteorder == 0) {
0599: wkbtype = ByteUtils.readBEInt(wkb, offset);
0600: } else {
0601: wkbtype = ByteUtils.readLEInt(wkb, offset);
0602: }
0603:
0604: offset += 4;
0605:
0606: if (wkbtype == 6) {
0607: return null;
0608: }
0609:
0610: // is the geometry respresented by wkb a polygon?
0611: if (wkbtype != 3) {
0612: throw new GeometryException(
0613: "invalid byte stream for Surface " + wkbtype);
0614: }
0615:
0616: // read number of rings of the polygon
0617: if (byteorder == 0) {
0618: numRings = ByteUtils.readBEInt(wkb, offset);
0619: } else {
0620: numRings = ByteUtils.readLEInt(wkb, offset);
0621: }
0622:
0623: offset += 4;
0624:
0625: // read number of points of the external ring
0626: if (byteorder == 0) {
0627: numPoints = ByteUtils.readBEInt(wkb, offset);
0628: } else {
0629: numPoints = ByteUtils.readLEInt(wkb, offset);
0630: }
0631:
0632: offset += 4;
0633:
0634: // allocate memory for the external boundary
0635: externalBoundary = new Position[numPoints];
0636:
0637: if (byteorder == 0) {
0638: // read points of the external boundary from the byte[]
0639: for (int i = 0; i < numPoints; i++) {
0640: x = ByteUtils.readBEDouble(wkb, offset);
0641: offset += 8;
0642: y = ByteUtils.readBEDouble(wkb, offset);
0643: offset += 8;
0644: externalBoundary[i] = new PositionImpl(x, y);
0645: }
0646: } else {
0647: // read points of the external boundary from the byte[]
0648: for (int i = 0; i < numPoints; i++) {
0649: x = ByteUtils.readLEDouble(wkb, offset);
0650: offset += 8;
0651: y = ByteUtils.readLEDouble(wkb, offset);
0652: offset += 8;
0653: externalBoundary[i] = new PositionImpl(x, y);
0654: }
0655: }
0656:
0657: // only if numRings is larger then one there internal rings
0658: if (numRings > 1) {
0659: internalBoundaries = new Position[numRings - 1][];
0660: }
0661:
0662: if (byteorder == 0) {
0663: for (int j = 1; j < numRings; j++) {
0664: // read number of points of the j-th internal ring
0665: numPoints = ByteUtils.readBEInt(wkb, offset);
0666: offset += 4;
0667:
0668: // allocate memory for the j-th internal boundary
0669: internalBoundaries[j - 1] = new Position[numPoints];
0670:
0671: // read points of the external boundary from the byte[]
0672: for (int i = 0; i < numPoints; i++) {
0673: x = ByteUtils.readBEDouble(wkb, offset);
0674: offset += 8;
0675: y = ByteUtils.readBEDouble(wkb, offset);
0676: offset += 8;
0677: internalBoundaries[j - 1][i] = new PositionImpl(x,
0678: y);
0679: }
0680: }
0681: } else {
0682: for (int j = 1; j < numRings; j++) {
0683: // read number of points of the j-th internal ring
0684: numPoints = ByteUtils.readLEInt(wkb, offset);
0685: offset += 4;
0686:
0687: // allocate memory for the j-th internal boundary
0688: internalBoundaries[j - 1] = new Position[numPoints];
0689:
0690: // read points of the external boundary from the byte[]
0691: for (int i = 0; i < numPoints; i++) {
0692: x = ByteUtils.readLEDouble(wkb, offset);
0693: offset += 8;
0694: y = ByteUtils.readLEDouble(wkb, offset);
0695: offset += 8;
0696: internalBoundaries[j - 1][i] = new PositionImpl(x,
0697: y);
0698: }
0699: }
0700: }
0701:
0702: SurfacePatch patch = createSurfacePatch(externalBoundary,
0703: internalBoundaries, si, crs);
0704:
0705: return createSurface(patch);
0706: }
0707:
0708: /**
0709: * Creates a <tt>Surface</tt> from a <tt>Envelope</tt>.
0710: * <p>
0711: *
0712: * @param bbox
0713: * envelope to be converted
0714: * @param crs
0715: * spatial reference system of the surface
0716: * @return corresponding surface
0717: *
0718: * @throws GeometryException
0719: * if the implicite orientation is not '+' or '-'
0720: */
0721: public static Surface createSurface(Envelope bbox,
0722: CoordinateSystem crs) throws GeometryException {
0723:
0724: Position min = bbox.getMin();
0725: Position max = bbox.getMax();
0726: Position[] exteriorRing = null;
0727: if (min.getCoordinateDimension() == 2) {
0728: exteriorRing = new Position[] { min,
0729: new PositionImpl(min.getX(), max.getY()), max,
0730: new PositionImpl(max.getX(), min.getY()), min };
0731: } else {
0732: exteriorRing = new Position[] {
0733: min,
0734: new PositionImpl(min.getX(), max.getY(), min.getZ()
0735: + ((max.getZ() - min.getZ()) * 0.5)),
0736: max,
0737: new PositionImpl(max.getX(), min.getY(), min.getZ()
0738: + ((max.getZ() - min.getZ()) * 0.5)), min };
0739: }
0740:
0741: return createSurface(exteriorRing, null,
0742: new SurfaceInterpolationImpl(), crs);
0743: }
0744:
0745: /**
0746: * Creates a <tt>GM_Surface</tt> from the ordinates of the exterior ring and the the interior rings
0747: * <p>
0748: *
0749: * @param exterior
0750: * ring
0751: * @param interior
0752: * ring
0753: * @param dim
0754: * of the surface
0755: * @param crs
0756: * spatial reference system of the surface
0757: * @return corresponding surface
0758: * @throws GeometryException
0759: * if the implicite orientation is not '+' or '-'
0760: *
0761: */
0762: public static Surface createSurface(double[] exterior,
0763: double[][] interior, int dim, CoordinateSystem crs)
0764: throws GeometryException {
0765:
0766: // get exterior ring
0767: Position[] ext = new Position[exterior.length / dim];
0768: int i = 0;
0769: int k = 0;
0770: while (i < exterior.length - 1) {
0771: double[] o = new double[dim];
0772: for (int j = 0; j < dim; j++) {
0773: o[j] = exterior[i++];
0774: }
0775: ext[k++] = GeometryFactory.createPosition(o);
0776: }
0777:
0778: // get interior rings if available
0779: Position[][] in = null;
0780: if (interior != null && interior.length > 0) {
0781: in = new Position[interior.length][];
0782: for (int j = 0; j < in.length; j++) {
0783: in[j] = new Position[interior[j].length / dim];
0784: i = 0;
0785: while (i < interior[j].length) {
0786: double[] o = new double[dim];
0787: for (int z = 0; z < dim; z++) {
0788: o[z] = interior[j][i++];
0789: }
0790: in[j][i / dim - 1] = GeometryFactory
0791: .createPosition(o);
0792: }
0793: }
0794: }
0795:
0796: // default - linear - interpolation
0797: SurfaceInterpolation si = new SurfaceInterpolationImpl();
0798: return GeometryFactory.createSurface(ext, in, si, crs);
0799: }
0800:
0801: /**
0802: * creates a MultiPoint from an array of Point.
0803: *
0804: * @param points
0805: * array of Points
0806: * @return a MultiPoint from an array of Point.
0807: *
0808: */
0809: public static MultiPoint createMultiPoint(Point[] points) {
0810: return new MultiPointImpl(points);
0811: }
0812:
0813: /**
0814: * creates a MultiPoint from an array of Point.
0815: *
0816: * @param points
0817: * array of Points
0818: * @param crs
0819: * @return a MultiPoint from an array of Point.
0820: */
0821: public static MultiPoint createMultiPoint(Point[] points,
0822: CoordinateSystem crs) {
0823: return new MultiPointImpl(points, crs);
0824: }
0825:
0826: /**
0827: * creates a MultiPoint from a wkb.
0828: *
0829: * @param wkb
0830: * byte stream that contains the wkb information
0831: * @param crs
0832: * CS_CoordinateSystem spatial reference system of the curve
0833: * @return the MultiPoint defined by the WKB and the given CRS
0834: * @throws GeometryException
0835: * if the wkb is not known or invalid
0836: *
0837: */
0838: public static MultiPoint createMultiPoint(byte[] wkb,
0839: CoordinateSystem crs) throws GeometryException {
0840: Point[] points = null;
0841: int wkbType = -1;
0842: int numPoints = -1;
0843: double x = 0;
0844: double y = 0;
0845: byte byteorder = wkb[0];
0846:
0847: // read wkbType
0848: if (byteorder == 0) {
0849: wkbType = ByteUtils.readBEInt(wkb, 1);
0850: } else {
0851: wkbType = ByteUtils.readLEInt(wkb, 1);
0852: }
0853:
0854: // if the geometry isn't a multipoint throw exception
0855: if (wkbType != 4) {
0856: throw new GeometryException(
0857: "Invalid byte stream for MultiPoint");
0858: }
0859:
0860: // read number of points
0861: if (byteorder == 0) {
0862: numPoints = ByteUtils.readBEInt(wkb, 5);
0863: } else {
0864: numPoints = ByteUtils.readLEInt(wkb, 5);
0865: }
0866:
0867: points = new Point[numPoints];
0868:
0869: int offset = 9;
0870:
0871: Object[] o = new Object[3];
0872: o[2] = crs;
0873:
0874: // read all points
0875: for (int i = 0; i < numPoints; i++) {
0876: // byteorder of the i-th point
0877: byteorder = wkb[offset];
0878:
0879: // wkbType of the i-th geometry
0880: if (byteorder == 0) {
0881: wkbType = ByteUtils.readBEInt(wkb, offset + 1);
0882: } else {
0883: wkbType = ByteUtils.readLEInt(wkb, offset + 1);
0884: }
0885:
0886: // if the geometry isn't a point throw exception
0887: if (wkbType != 1) {
0888: throw new GeometryException(
0889: "Invalid byte stream for Point as "
0890: + "part of a multi point");
0891: }
0892:
0893: // read the i-th point depending on the byteorde
0894: if (byteorder == 0) {
0895: x = ByteUtils.readBEDouble(wkb, offset + 5);
0896: y = ByteUtils.readBEDouble(wkb, offset + 13);
0897: } else {
0898: x = ByteUtils.readLEDouble(wkb, offset + 5);
0899: y = ByteUtils.readLEDouble(wkb, offset + 13);
0900: }
0901:
0902: offset += 21;
0903:
0904: points[i] = new PointImpl(x, y, crs);
0905: }
0906:
0907: return createMultiPoint(points);
0908: }
0909:
0910: /**
0911: * creates a MultiCurve from an array of Curves.
0912: *
0913: * @param curves
0914: * @return a MultiCurve from an array of Curves.
0915: */
0916: public static MultiCurve createMultiCurve(Curve[] curves) {
0917: return new MultiCurveImpl(curves);
0918: }
0919:
0920: /**
0921: * creates a MultiCurve from an array of Curves.
0922: *
0923: * @param curves
0924: * @param crs
0925: * @return a MultiCurve from an array of Curves.
0926: */
0927: public static MultiCurve createMultiCurve(Curve[] curves,
0928: CoordinateSystem crs) {
0929: return new MultiCurveImpl(curves, crs);
0930: }
0931:
0932: /**
0933: * creates a MultiCurve from a wkb.
0934: *
0935: * @param wkb
0936: * byte stream that contains the wkb information
0937: * @param crs
0938: * CS_CoordinateSystem spatial reference system of the curve
0939: * @return the MultiCurve defined by the WKB and the given CRS
0940: * @throws GeometryException
0941: * if the wkb is not known or invalid
0942: */
0943: public static MultiCurve createMultiCurve(byte[] wkb,
0944: CoordinateSystem crs) throws GeometryException {
0945: int wkbType = -1;
0946: int numPoints = -1;
0947: int numParts = -1;
0948: double x = 0;
0949: double y = 0;
0950: Position[][] points = null;
0951: int offset = 0;
0952: byte byteorder = wkb[offset++];
0953:
0954: if (byteorder == 0) {
0955: wkbType = ByteUtils.readBEInt(wkb, offset);
0956: } else {
0957: wkbType = ByteUtils.readLEInt(wkb, offset);
0958: }
0959:
0960: offset += 4;
0961:
0962: // check if it's realy a linestring
0963: if (wkbType != 5) {
0964: throw new GeometryException(
0965: "Invalid byte stream for MultiCurve");
0966: }
0967:
0968: // read number of linestrings
0969: if (byteorder == 0) {
0970: numParts = ByteUtils.readBEInt(wkb, offset);
0971: } else {
0972: numParts = ByteUtils.readLEInt(wkb, offset);
0973: }
0974:
0975: offset += 4;
0976:
0977: points = new Position[numParts][];
0978:
0979: // for every linestring
0980: for (int j = 0; j < numParts; j++) {
0981: byteorder = wkb[offset++];
0982:
0983: if (byteorder == 0) {
0984: wkbType = ByteUtils.readBEInt(wkb, offset);
0985: } else {
0986: wkbType = ByteUtils.readLEInt(wkb, offset);
0987: }
0988:
0989: offset += 4;
0990:
0991: // check if it's realy a linestring
0992: if (wkbType != 2) {
0993: throw new GeometryException(
0994: "Invalid byte stream for Curve as "
0995: + " part of a MultiCurve.");
0996: }
0997:
0998: // read number of points
0999: if (byteorder == 0) {
1000: numPoints = ByteUtils.readBEInt(wkb, offset);
1001: } else {
1002: numPoints = ByteUtils.readLEInt(wkb, offset);
1003: }
1004:
1005: offset += 4;
1006:
1007: points[j] = new Position[numPoints];
1008:
1009: // read the i-th point depending on the byteorde
1010: if (byteorder == 0) {
1011: for (int i = 0; i < numPoints; i++) {
1012: x = ByteUtils.readBEDouble(wkb, offset);
1013: offset += 8;
1014: y = ByteUtils.readBEDouble(wkb, offset);
1015: offset += 8;
1016: points[j][i] = new PositionImpl(x, y);
1017: }
1018: } else {
1019: for (int i = 0; i < numPoints; i++) {
1020: x = ByteUtils.readLEDouble(wkb, offset);
1021: offset += 8;
1022: y = ByteUtils.readLEDouble(wkb, offset);
1023: offset += 8;
1024: points[j][i] = new PositionImpl(x, y);
1025: }
1026: }
1027: }
1028:
1029: CurveSegment[] segment = new CurveSegment[1];
1030: Curve[] curves = new Curve[numParts];
1031:
1032: for (int i = 0; i < numParts; i++) {
1033: segment[0] = createCurveSegment(points[i], crs);
1034: curves[i] = createCurve(segment);
1035: }
1036:
1037: return createMultiCurve(curves);
1038: }
1039:
1040: /**
1041: * creates a MultiSurface from an array of surfaces
1042: *
1043: * @param surfaces
1044: * @return a MultiSurface from an array of surfaces
1045: */
1046: public static MultiSurface createMultiSurface(Surface[] surfaces) {
1047: return new MultiSurfaceImpl(surfaces);
1048: }
1049:
1050: /**
1051: * creates a MultiSurface from an array of surfaces
1052: *
1053: * @param surfaces
1054: * @param crs
1055: * @return a MultiSurface from an array of surfaces
1056: */
1057: public static MultiSurface createMultiSurface(Surface[] surfaces,
1058: CoordinateSystem crs) {
1059: return new MultiSurfaceImpl(surfaces, crs);
1060: }
1061:
1062: /**
1063: * creates a MultiSurface from a wkb
1064: *
1065: * @param wkb
1066: * geometry in Well-Known Binary (WKB) format
1067: * @param crs
1068: * spatial reference system of the geometry
1069: * @param si
1070: * surface interpolation
1071: * @return the MultiSurface defined by the WKB and the given CRS
1072: * @throws GeometryException
1073: * if the wkb is not known or invalid
1074: */
1075: public static MultiSurface createMultiSurface(byte[] wkb,
1076: CoordinateSystem crs, SurfaceInterpolation si)
1077: throws GeometryException {
1078: int wkbtype = -1;
1079: int numPoly = 0;
1080: int numRings = 0;
1081: int numPoints = 0;
1082: int offset = 0;
1083: double x = 0;
1084: double y = 0;
1085: Position[] externalBoundary = null;
1086: Position[][] internalBoundaries = null;
1087: byte byteorder = wkb[offset++];
1088:
1089: if (byteorder == 0) {
1090: wkbtype = ByteUtils.readBEInt(wkb, offset);
1091: } else {
1092: wkbtype = ByteUtils.readLEInt(wkb, offset);
1093: }
1094:
1095: offset += 4;
1096:
1097: // is the wkbmetry a multipolygon?
1098: if (wkbtype != 6) {
1099: throw new GeometryException(
1100: "Invalid byte stream for MultiSurface");
1101: }
1102:
1103: // read number of polygons on the byte[]
1104: if (byteorder == 0) {
1105: numPoly = ByteUtils.readBEInt(wkb, offset);
1106: } else {
1107: numPoly = ByteUtils.readLEInt(wkb, offset);
1108: }
1109:
1110: offset += 4;
1111:
1112: ArrayList<Surface> list = new ArrayList<Surface>(numPoly);
1113:
1114: for (int ip = 0; ip < numPoly; ip++) {
1115: byteorder = wkb[offset];
1116: offset++;
1117:
1118: if (byteorder == 0) {
1119: wkbtype = ByteUtils.readBEInt(wkb, offset);
1120: } else {
1121: wkbtype = ByteUtils.readLEInt(wkb, offset);
1122: }
1123:
1124: offset += 4;
1125:
1126: // is the geometry respresented by wkb a polygon?
1127: if (wkbtype != 3) {
1128: throw new GeometryException(
1129: "invalid byte stream for Surface " + wkbtype);
1130: }
1131:
1132: // read number of rings of the polygon
1133: if (byteorder == 0) {
1134: numRings = ByteUtils.readBEInt(wkb, offset);
1135: } else {
1136: numRings = ByteUtils.readLEInt(wkb, offset);
1137: }
1138:
1139: offset += 4;
1140:
1141: // read number of points of the external ring
1142: if (byteorder == 0) {
1143: numPoints = ByteUtils.readBEInt(wkb, offset);
1144: } else {
1145: numPoints = ByteUtils.readLEInt(wkb, offset);
1146: }
1147:
1148: offset += 4;
1149:
1150: // allocate memory for the external boundary
1151: externalBoundary = new Position[numPoints];
1152:
1153: if (byteorder == 0) {
1154: // read points of the external boundary from the byte[]
1155: for (int i = 0; i < numPoints; i++) {
1156: x = ByteUtils.readBEDouble(wkb, offset);
1157: offset += 8;
1158: y = ByteUtils.readBEDouble(wkb, offset);
1159: offset += 8;
1160: externalBoundary[i] = new PositionImpl(x, y);
1161: }
1162: } else {
1163: // read points of the external boundary from the byte[]
1164: for (int i = 0; i < numPoints; i++) {
1165: x = ByteUtils.readLEDouble(wkb, offset);
1166: offset += 8;
1167: y = ByteUtils.readLEDouble(wkb, offset);
1168: offset += 8;
1169: externalBoundary[i] = new PositionImpl(x, y);
1170: }
1171: }
1172:
1173: // only if numRings is larger then one there internal rings
1174: if (numRings > 1) {
1175: internalBoundaries = new Position[numRings - 1][];
1176: }
1177:
1178: if (byteorder == 0) {
1179: for (int j = 1; j < numRings; j++) {
1180: // read number of points of the j-th internal ring
1181: numPoints = ByteUtils.readBEInt(wkb, offset);
1182: offset += 4;
1183:
1184: // allocate memory for the j-th internal boundary
1185: internalBoundaries[j - 1] = new Position[numPoints];
1186:
1187: // read points of the external boundary from the byte[]
1188: for (int i = 0; i < numPoints; i++) {
1189: x = ByteUtils.readBEDouble(wkb, offset);
1190: offset += 8;
1191: y = ByteUtils.readBEDouble(wkb, offset);
1192: offset += 8;
1193: internalBoundaries[j - 1][i] = new PositionImpl(
1194: x, y);
1195: }
1196: }
1197: } else {
1198: for (int j = 1; j < numRings; j++) {
1199: // read number of points of the j-th internal ring
1200: numPoints = ByteUtils.readLEInt(wkb, offset);
1201: offset += 4;
1202:
1203: // allocate memory for the j-th internal boundary
1204: internalBoundaries[j - 1] = new Position[numPoints];
1205:
1206: // read points of the external boundary from the byte[]
1207: for (int i = 0; i < numPoints; i++) {
1208: x = ByteUtils.readLEDouble(wkb, offset);
1209: offset += 8;
1210: y = ByteUtils.readLEDouble(wkb, offset);
1211: offset += 8;
1212: internalBoundaries[j - 1][i] = new PositionImpl(
1213: x, y);
1214: }
1215: }
1216: }
1217:
1218: SurfacePatch patch = createSurfacePatch(externalBoundary,
1219: internalBoundaries, si, crs);
1220:
1221: list.add(createSurface(patch));
1222: }
1223:
1224: MultiSurface multisurface = new MultiSurfaceImpl(crs);
1225:
1226: for (int i = 0; i < list.size(); i++) {
1227: multisurface.addSurface(list.get(i));
1228: }
1229:
1230: return multisurface;
1231: }
1232:
1233: }
|