001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.ui;
010:
011: import java.awt.Color;
012: import java.awt.Dimension;
013: import java.awt.Graphics2D;
014: import java.awt.Rectangle;
015: import java.awt.Shape;
016: import java.awt.geom.AffineTransform;
017: import java.awt.geom.Point2D;
018: import java.awt.image.RenderedImage;
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.List;
022:
023: import net.refractions.udig.ui.graphics.AWTGraphics;
024: import net.refractions.udig.ui.graphics.NonAdvancedSWTGraphics;
025: import net.refractions.udig.ui.graphics.SLDs;
026: import net.refractions.udig.ui.graphics.SWTGraphics;
027: import net.refractions.udig.ui.graphics.ViewportGraphics;
028:
029: import org.eclipse.core.runtime.Platform;
030: import org.eclipse.swt.graphics.GC;
031: import org.eclipse.swt.graphics.Image;
032: import org.eclipse.swt.widgets.Display;
033: import org.geotools.data.DataUtilities;
034: import org.geotools.feature.Feature;
035: import org.geotools.feature.FeatureType;
036: import org.geotools.feature.IllegalAttributeException;
037: import org.geotools.feature.SchemaException;
038: import org.geotools.filter.FilterFactoryFinder;
039: import org.geotools.geometry.jts.JTS;
040: import org.geotools.renderer.lite.LiteShape;
041: import org.geotools.renderer.style.GraphicStyle2D;
042: import org.geotools.renderer.style.MarkStyle2D;
043: import org.geotools.renderer.style.SLDStyleFactory;
044: import org.geotools.renderer.style.Style2D;
045: import org.geotools.styling.FeatureTypeStyle;
046: import org.geotools.styling.LineSymbolizer;
047: import org.geotools.styling.PointSymbolizer;
048: import org.geotools.styling.PolygonSymbolizer;
049: import org.geotools.styling.RasterSymbolizer;
050: import org.geotools.styling.Rule;
051: import org.geotools.styling.Style;
052: import org.geotools.styling.StyleBuilder;
053: import org.geotools.styling.Symbolizer;
054: import org.geotools.styling.TextSymbolizer;
055: import org.geotools.util.NumberRange;
056: import org.opengis.referencing.operation.MathTransform;
057:
058: import com.vividsolutions.jts.geom.Coordinate;
059: import com.vividsolutions.jts.geom.Envelope;
060: import com.vividsolutions.jts.geom.Geometry;
061: import com.vividsolutions.jts.geom.GeometryFactory;
062: import com.vividsolutions.jts.geom.LineString;
063: import com.vividsolutions.jts.geom.LinearRing;
064: import com.vividsolutions.jts.geom.MultiLineString;
065: import com.vividsolutions.jts.geom.MultiPoint;
066: import com.vividsolutions.jts.geom.MultiPolygon;
067: import com.vividsolutions.jts.geom.Point;
068: import com.vividsolutions.jts.geom.Polygon;
069:
070: /**
071: * Drawing utitlity package - make your own previes and glyphs!
072: *
073: * @author jones
074: * @since 0.6.0
075: */
076: public final class Drawing {
077: private GeometryFactory gf = new GeometryFactory();
078:
079: private Drawing() {
080: // prevent subclassing
081: }
082:
083: /**
084: * Retrieve the default Drawing implementation.
085: *
086: * @return Drawing ready for use
087: */
088: public static Drawing create() {
089: return new Drawing();
090: }
091:
092: /**
093: * Creates a ViewportGraphics object based backed by SWT.
094: *
095: * <p><b>REMEMBER to dispose of graphics.</b>
096: *
097: * @param gc A SWT GC object that the ViewportGraphics object will draw on.
098: * @param display The display object that will be used to create new
099: * @param displaySize
100: * @return Wrapper around a normal SWT Image
101: */
102: public static ViewportGraphics createGraphics(GC gc,
103: Display display, Dimension displaySize) {
104: if (Platform.getOS().equals(Platform.OS_LINUX))
105:
106: return new NonAdvancedSWTGraphics(gc, display, displaySize);
107:
108: return new SWTGraphics(gc, display);
109: }
110:
111: /**
112: * Creates a ViewportGraphics object based backed by SWT.
113: *
114: * @param graphics
115: * @return Wrapper allowing system to draw onto j2d images
116: */
117: public static ViewportGraphics createGraphics(Graphics2D graphics) {
118: return new AWTGraphics(graphics);
119: }
120:
121: /**
122: * Used to draw a freature directly onto the provided image.
123: * <p>
124: * Feature coordintes are in the same coordinates as the image.
125: * </p>
126: * <p>
127: * You may call this method multiple times to draw several features onto the same
128: * Image (say for glyph creation).
129: * </p>
130: *
131: * @param image Image to render on to
132: * @param display Needed to create Colors for image
133: * @param feature Feature to be rendered
134: * @param style Style to render feature with
135: */
136: public void drawDirect(Image image, Display display,
137: Feature feature, Style style) {
138:
139: ViewportGraphics graphics = createSWTGraphics(image, display);
140: drawFeature(graphics, feature, style, new AffineTransform());
141: graphics.dispose();
142: }
143:
144: public void drawDirect(Image image, Display display,
145: Feature feature, Rule rule) {
146: AffineTransform worldToScreenTransform = new AffineTransform();
147:
148: ViewportGraphics graphics = createSWTGraphics(image, display);
149: drawFeature(graphics, feature, worldToScreenTransform, false,
150: getSymbolizers(rule), null);
151: graphics.dispose();
152: }
153:
154: /**
155: *
156: * @param image
157: * @param display
158: * @return
159: */
160: private ViewportGraphics createSWTGraphics(Image image,
161: Display display) {
162: if (Platform.getOS().equals(Platform.OS_LINUX))
163: return new NonAdvancedSWTGraphics(image, display);
164: return new SWTGraphics(image, display);
165: }
166:
167: public void drawFeature(ViewportGraphics graphics, Feature feature,
168: AffineTransform worldToScreenTransform,
169: boolean drawVertices, MathTransform mt) {
170: if (feature == null)
171: return;
172: drawFeature(graphics, feature, worldToScreenTransform,
173: drawVertices, getSymbolizers(feature), mt);
174: }
175:
176: public void drawFeature(ViewportGraphics graphics, Feature feature,
177: AffineTransform worldToScreenTransform) {
178: if (feature == null)
179: return;
180: drawFeature(graphics, feature, worldToScreenTransform, false,
181: getSymbolizers(feature), null);
182: }
183:
184: public void drawFeature(ViewportGraphics graphics, Feature feature,
185: AffineTransform worldToScreenTransform, Style style) {
186: if (feature == null)
187: return;
188: drawFeature(graphics, feature, worldToScreenTransform, false,
189: getSymbolizers(style), null);
190: }
191:
192: public void drawFeature(ViewportGraphics graphics, Feature feature,
193: Style style, AffineTransform worldToScreenTransform) {
194: if (feature == null)
195: return;
196:
197: drawFeature(graphics, feature, worldToScreenTransform, false,
198: getSymbolizers(style), null);
199: }
200:
201: Symbolizer[] getSymbolizers(Style style) {
202: List<Symbolizer> symbs = new ArrayList<Symbolizer>();
203: FeatureTypeStyle[] styles = style.getFeatureTypeStyles();
204: for (int i = 0; i < styles.length; i++) {
205: FeatureTypeStyle fstyle = styles[i];
206: Rule[] rules = fstyle.getRules();
207: for (int j = 0; j < rules.length; j++) {
208: Rule rule = rules[j];
209: symbs.addAll(Arrays.asList(rule.getSymbolizers()));
210: }
211: }
212: return symbs.toArray(new Symbolizer[symbs.size()]);
213: }
214:
215: Symbolizer[] getSymbolizers(Rule rule) {
216: List<Symbolizer> symbs = new ArrayList<Symbolizer>();
217: symbs.addAll(Arrays.asList(rule.getSymbolizers()));
218: return symbs.toArray(new Symbolizer[symbs.size()]);
219: }
220:
221: public void drawFeature(ViewportGraphics graphics, Feature feature,
222: AffineTransform worldToScreenTransform,
223: boolean drawVertices, Symbolizer[] symbs, MathTransform mt) {
224:
225: LiteShape shape = new LiteShape(null, worldToScreenTransform,
226: false);
227: if (symbs == null)
228: return;
229: for (int m = 0; m < symbs.length; m++) {
230: drawFeature(graphics, feature, worldToScreenTransform,
231: drawVertices, symbs[m], mt, shape);
232: }
233: }
234:
235: public void drawFeature(ViewportGraphics graphics, Feature feature,
236: AffineTransform worldToScreenTransform,
237: boolean drawVertices, Symbolizer symbolizer,
238: MathTransform mathTransform, LiteShape shape) {
239: if (symbolizer instanceof RasterSymbolizer) {
240: // TODO
241: } else {
242: Geometry g = findGeometry(feature, symbolizer);
243: if (g == null)
244: return;
245: if (mathTransform != null) {
246: try {
247: g = JTS.transform(g, mathTransform);
248: } catch (Exception e) {
249: // do nothing
250: }
251: }
252: shape.setGeometry(g);
253:
254: paint(graphics, feature, shape, symbolizer);
255: if (drawVertices) {
256: double averageDistance = 0;
257: Coordinate[] coords = g.getCoordinates();
258: java.awt.Point oldP = worldToPixel(coords[0],
259: worldToScreenTransform);
260: for (int i = 1; i < coords.length; i++) {
261: Coordinate coord = coords[i];
262: java.awt.Point p = worldToPixel(coord,
263: worldToScreenTransform);
264: averageDistance += p.distance(oldP) / i;
265: oldP = p;
266: }
267: int pixels = 1;
268: if (averageDistance > 20)
269: pixels = 3;
270: if (averageDistance > 60)
271: pixels = 5;
272: if (pixels > 1) {
273: graphics.setColor(Color.RED);
274: for (int i = 0; i < coords.length; i++) {
275: Coordinate coord = coords[i];
276: java.awt.Point p = worldToPixel(coord,
277: worldToScreenTransform);
278: graphics.fillRect(p.x - (pixels - 1) / 2, p.y
279: - (pixels - 1) / 2, pixels, pixels);
280: }
281: }
282: }
283: }
284: }
285:
286: public java.awt.Point worldToPixel(Coordinate coord,
287: AffineTransform worldToScreenTransform) {
288: Point2D w = new Point2D.Double(coord.x, coord.y);
289: AffineTransform at = worldToScreenTransform;
290: Point2D p = at.transform(w, new Point2D.Double());
291: return new java.awt.Point((int) p.getX(), (int) p.getY());
292: }
293:
294: /** Unsure if this is the paint for the border, or the fill? */
295: private void paint(ViewportGraphics g, Feature feature,
296: LiteShape shape, Symbolizer symb) {
297: if (symb instanceof PolygonSymbolizer) {
298: PolygonSymbolizer polySymb = (PolygonSymbolizer) symb;
299: Color stroke = SLDs.polyColor(polySymb);
300: double opacity = SLDs.polyFillOpacity(polySymb);
301: Color fill = SLDs.polyFill(polySymb);
302:
303: int width = SLDs.width(SLDs.stroke(polySymb));
304: if (width == SLDs.NOTFOUND)
305: width = 1;
306:
307: if (Double.isNaN(opacity))
308: opacity = 1.0;
309: if (fill != null) {
310: fill = new Color(fill.getRed(), fill.getGreen(), fill
311: .getBlue(), (int) (255 * opacity));
312: g.setColor(fill);
313: g.fill(shape);
314: }
315: if (stroke != null) {
316: g.setColor(stroke);
317: g.setStroke(ViewportGraphics.LINE_SOLID, width);
318: g.draw(shape);
319: }
320: }
321: if (symb instanceof LineSymbolizer) {
322: LineSymbolizer lineSymbolizer = (LineSymbolizer) symb;
323: Color c = SLDs.color(lineSymbolizer);
324: int w = SLDs.width(lineSymbolizer);
325: if (c != null && w > 0) {
326: g.setColor(c);
327: g.setStroke(ViewportGraphics.LINE_SOLID, w);
328: g.draw(shape);
329: }
330: }
331: if (symb instanceof PointSymbolizer) {
332: PointSymbolizer pointSymbolizer = (PointSymbolizer) symb;
333:
334: Color c = SLDs.pointColor(pointSymbolizer);
335: Color fill = SLDs.pointFill(pointSymbolizer);
336: int width = SLDs.width(SLDs.stroke(pointSymbolizer));
337: float[] point = new float[6];
338: shape.getPathIterator(null).currentSegment(point);
339: SLDStyleFactory styleFactory = new SLDStyleFactory();
340: Style2D tmp = styleFactory.createStyle(feature,
341: pointSymbolizer, new NumberRange(Double.MIN_VALUE,
342: Double.MAX_VALUE));
343:
344: if (tmp instanceof MarkStyle2D) {
345: MarkStyle2D style = (MarkStyle2D) tmp;
346: Shape shape2 = style.getTransformedShape(point[0],
347: point[1]);
348:
349: if (c == null && fill == null) {
350: g.setColor(Color.GRAY);
351: g.fill(shape2);
352: }
353:
354: if (fill != null) {
355: g.setColor(fill);
356: g.fill(shape2);
357: } else {
358: g.setColor(Color.GRAY);
359: g.fill(shape2);
360: }
361: if (c != null) {
362: g.setStroke(ViewportGraphics.LINE_SOLID, width);
363: g.setColor(c);
364: g.draw(shape2);
365: } else {
366: g.setStroke(ViewportGraphics.LINE_SOLID, width);
367: g.setColor(Color.DARK_GRAY);
368: g.draw(shape2);
369: }
370: } else if (tmp instanceof GraphicStyle2D) {
371: GraphicStyle2D style = (GraphicStyle2D) tmp;
372:
373: float rotation = style.getRotation();
374:
375: g.setTransform(AffineTransform
376: .getRotateInstance(rotation));
377:
378: RenderedImage image = (RenderedImage) style.getImage();
379: g.drawImage(image, (int) (point[0] - ((double) image
380: .getWidth())
381: / (double) 2),
382: (int) (point[1] - ((double) image.getHeight())
383: / (double) 2));
384: }
385: }
386: }
387:
388: public static Symbolizer[] getSymbolizers(Feature feature) {
389: return getSymbolizers(feature.getDefaultGeometry().getClass(),
390: Color.RED);
391: }
392:
393: public static Symbolizer[] getSymbolizers(
394: Class<? extends Geometry> type, Color baseColor) {
395: return getSymbolizers(type, baseColor, true);
396: }
397:
398: public static Symbolizer[] getSymbolizers(
399: Class<? extends Geometry> type, Color baseColor,
400: boolean useTransparency) {
401:
402: StyleBuilder builder = new StyleBuilder();
403: Symbolizer[] syms = new Symbolizer[1];
404: if (LineString.class.isAssignableFrom(type)
405: || MultiLineString.class.isAssignableFrom(type))
406: syms[0] = builder.createLineSymbolizer(baseColor, 2);
407: if (Point.class.isAssignableFrom(type)
408: || MultiPoint.class.isAssignableFrom(type)) {
409: PointSymbolizer point = builder
410: .createPointSymbolizer(builder.createGraphic());
411: point.getGraphic().getMarks()[0]
412: .setSize(FilterFactoryFinder.createFilterFactory()
413: .createLiteralExpression(10));
414: point.getGraphic().getMarks()[0].setFill(builder
415: .createFill(baseColor));
416: syms[0] = point;
417: }
418: if (Polygon.class.isAssignableFrom(type)
419: || MultiPolygon.class.isAssignableFrom(type)) {
420: syms[0] = builder.createPolygonSymbolizer(builder
421: .createStroke(baseColor, 2), builder.createFill(
422: baseColor, useTransparency ? .6 : 1.0));
423: }
424: return syms;
425: }
426:
427: /**
428: * Finds the geometric attribute requested by the symbolizer
429: *
430: * @param f The victim
431: * @param s The symbolizer
432: * @param style the resolved style for the specified victim
433: * @return The geometry requested in the symbolizer, or the default geometry if none is
434: * specified
435: */
436: private com.vividsolutions.jts.geom.Geometry findGeometry(
437: Feature f, Symbolizer s) {
438: String geomName = getGeometryPropertyName(s);
439: // get the geometry
440: com.vividsolutions.jts.geom.Geometry geom;
441: if (geomName == null) {
442: geom = f.getDefaultGeometry();
443: } else {
444: geom = (com.vividsolutions.jts.geom.Geometry) f
445: .getAttribute(geomName);
446: }
447: // if the symbolizer is a point or text symbolizer generate a suitable
448: // location to place the
449: // point in order to avoid recomputing that location at each rendering
450: // step
451: if ((s instanceof PointSymbolizer || s instanceof TextSymbolizer)
452: && !(geom instanceof Point)) {
453: if (geom instanceof LineString
454: && !(geom instanceof LinearRing)) {
455: // use the mid point to represent the point/text symbolizer
456: // anchor
457: Coordinate[] coordinates = geom.getCoordinates();
458: Coordinate start = coordinates[0];
459: Coordinate end = coordinates[1];
460: Coordinate mid = new Coordinate((start.x + end.x) / 2,
461: (start.y + end.y) / 2);
462: geom = geom.getFactory().createPoint(mid);
463: } else {
464: // otherwise use the centroid of the polygon
465: geom = geom.getCentroid();
466: }
467: }
468: return geom;
469: }
470:
471: private String getGeometryPropertyName(Symbolizer s) {
472: String geomName = null;
473: // TODO: fix the styles, the getGeometryPropertyName should probably be
474: // moved into an interface...
475: if (s instanceof PolygonSymbolizer) {
476: geomName = ((PolygonSymbolizer) s)
477: .getGeometryPropertyName();
478: } else if (s instanceof PointSymbolizer) {
479: geomName = ((PointSymbolizer) s).getGeometryPropertyName();
480: } else if (s instanceof LineSymbolizer) {
481: geomName = ((LineSymbolizer) s).getGeometryPropertyName();
482: } else if (s instanceof TextSymbolizer) {
483: geomName = ((TextSymbolizer) s).getGeometryPropertyName();
484: }
485: return geomName;
486: }
487:
488: /**
489: * TODO summary sentence for worldToScreenTransform ...
490: *
491: * @param bounds
492: * @param rectangle
493: * @return
494: */
495: public static AffineTransform worldToScreenTransform(
496: Envelope mapExtent, Rectangle screenSize) {
497: double scaleX = screenSize.getWidth() / mapExtent.getWidth();
498: double scaleY = screenSize.getHeight() / mapExtent.getHeight();
499:
500: double tx = -mapExtent.getMinX() * scaleX;
501: double ty = (mapExtent.getMinY() * scaleY)
502: + screenSize.getHeight();
503:
504: AffineTransform at = new AffineTransform(scaleX, 0.0d, 0.0d,
505: -scaleY, tx, ty);
506:
507: return at;
508: }
509:
510: /**
511: * Create a FeatureType schema using a type short hand.
512: * <p>
513: * Code Example:<pre><code>
514: * new Drawing().schema("namespace.typename", "id:0,*geom:LineString,name:String,*centroid:Point");
515: * </code></pre>
516: * <ul>
517: * <li>FeatureType with identifier "namespace.typename"
518: * <li>Default Geometry "geom" of type LineStirng indicated with a "*"
519: * <li>Three attributes: id of type Integer, name of type String and centroid of type Point
520: * </ul>
521: * </p>
522: * @param name namespace.name
523: * @param spec
524: * @return Generated FeatureType
525: */
526: public FeatureType schema(String name, String spec) {
527: try {
528: return DataUtilities.createType(name, spec);
529: } catch (SchemaException e) {
530: throw new IllegalArgumentException(e);
531: }
532: }
533:
534: static FeatureType pointSchema;
535: static FeatureType lineSchema;
536: static FeatureType polygonSchema;
537: static FeatureType multipointSchema;
538: static FeatureType multilineSchema;
539: static FeatureType multipolygonSchema;
540: static {
541: try {
542: pointSchema = DataUtilities.createType(
543: "generated:point", "*point:Point"); //$NON-NLS-1$ //$NON-NLS-2$
544: lineSchema = DataUtilities.createType(
545: "generated:linestring", "*linestring:LineString"); //$NON-NLS-1$ //$NON-NLS-2$
546: polygonSchema = DataUtilities.createType(
547: "generated:polygon", "*polygon:Polygon"); //$NON-NLS-1$ //$NON-NLS-2$
548: multipointSchema = DataUtilities.createType(
549: "generated:multipoint", "*multipoint:MultiPoint"); //$NON-NLS-1$ //$NON-NLS-2$
550: multilineSchema = DataUtilities
551: .createType(
552: "generated:multilinestring", "*multilinestring:MultiLineString"); //$NON-NLS-1$ //$NON-NLS-2$
553: multipolygonSchema = DataUtilities
554: .createType(
555: "generated:multipolygon", "*multipolygon:MultiPolygon"); //$NON-NLS-1$ //$NON-NLS-2$
556: } catch (SchemaException unExpected) {
557: System.err.println(unExpected);
558: }
559: }
560:
561: /**
562: * Just a convinient method to create feature from geometry.
563: *
564: * @param geom the geometry to create feature from
565: * @return feature instance
566: */
567: public Feature feature(Geometry geom) {
568: if (geom instanceof Polygon) {
569: return feature((Polygon) geom);
570: } else if (geom instanceof MultiPolygon) {
571: return feature((MultiPolygon) geom);
572: } else if (geom instanceof Point) {
573: return feature((Point) geom);
574: } else if (geom instanceof LineString) {
575: return feature((LineString) geom);
576: } else if (geom instanceof MultiPoint) {
577: return feature((MultiPoint) geom);
578: } else if (geom instanceof MultiLineString) {
579: return feature((MultiLineString) geom);
580: } else {
581: throw new IllegalArgumentException(
582: "Geometry is not supported to create feature"); //$NON-NLS-1$
583: }
584: }
585:
586: /**
587: * Simple feature with one attribute called "point".
588: * @param point
589: * @return Feature with a default geometry and no attribtues
590: */
591: public Feature feature(Point point) {
592: if (point == null)
593: throw new NullPointerException("Point required"); //$NON-NLS-1$
594: try {
595: return pointSchema.create(new Object[] { point });
596: } catch (IllegalAttributeException e) {
597: // this should not happen because we *know* the parameter matches schame
598: throw new RuntimeException(
599: "Could not generate feature for point " + point); //$NON-NLS-1$
600: }
601: }
602:
603: /**
604: * Simple Feature with a default geometry and no attribtues.
605: * @param line
606: * @return Feature with a default geometry and no attribtues
607: */
608: public Feature feature(LineString line) {
609: if (line == null)
610: throw new NullPointerException("line required"); //$NON-NLS-1$
611: try {
612: return lineSchema.create(new Object[] { line });
613: } catch (IllegalAttributeException e) {
614: // this should not happen because we *know* the parameter matches schame
615: throw new RuntimeException(
616: "Could not generate feature for point " + line); //$NON-NLS-1$
617: }
618: }
619:
620: /**
621: * Simple Feature with a default geometry and no attribtues.
622: * @param polygon
623: * @return Feature with a default geometry and no attribtues
624: */
625: public Feature feature(Polygon polygon) {
626: if (polygon == null)
627: throw new NullPointerException("polygon required"); //$NON-NLS-1$
628: try {
629: return polygonSchema.create(new Object[] { polygon });
630: } catch (IllegalAttributeException e) {
631: // this should not happen because we *know* the parameter matches schame
632: throw new RuntimeException(
633: "Could not generate feature for point " + polygon); //$NON-NLS-1$
634: }
635: }
636:
637: /**
638: * Simple Feature with a default geometry and no attribtues.
639: * @param multipoint
640: * @return Feature with a default geometry and no attribtues
641: */
642: public Feature feature(MultiPoint multipoint) {
643: if (multipoint == null)
644: throw new NullPointerException("multipoint required"); //$NON-NLS-1$
645: try {
646: return multipointSchema.create(new Object[] { multipoint });
647: } catch (IllegalAttributeException e) {
648: // this should not happen because we *know* the parameter matches schame
649: throw new RuntimeException(
650: "Could not generate feature for point " + multipoint); //$NON-NLS-1$
651: }
652: }
653:
654: /**
655: * Simple Feature with a default geometry and no attribtues.
656: * @param multilinestring
657: * @return Feature with a default geometry and no attribtues
658: */
659: public Feature feature(MultiLineString multilinestring) {
660: if (multilinestring == null)
661: throw new NullPointerException("multilinestring required"); //$NON-NLS-1$
662: try {
663: return multilineSchema
664: .create(new Object[] { multilinestring });
665: } catch (IllegalAttributeException e) {
666: // this should not happen because we *know* the parameter matches schame
667: throw new RuntimeException(
668: "Could not generate feature for point " + multilinestring); //$NON-NLS-1$
669: }
670: }
671:
672: /**
673: * Simple Feature with a default geometry and no attribtues.
674: * @param multipolygon
675: * @return Feature with a default geometry and no attribtues
676: */
677: public Feature feature(MultiPolygon multipolygon) {
678: if (multipolygon == null)
679: throw new NullPointerException("multipolygon required"); //$NON-NLS-1$
680: try {
681: return multipolygonSchema
682: .create(new Object[] { multipolygon });
683: } catch (IllegalAttributeException e) {
684: // this should not happen because we *know* the parameter matches schame
685: throw new RuntimeException(
686: "Could not generate feature for point " + multipolygon); //$NON-NLS-1$
687: }
688: }
689:
690: /**
691: * Generate Point from two dimensional ordinates
692: *
693: * @param x
694: * @param y
695: * @return Point
696: */
697: public Point point(int x, int y) {
698: return gf.createPoint(new Coordinate(x, y));
699: }
700:
701: /**
702: * Generate LineStrings from two dimensional ordinates
703: *
704: * @param xy
705: * @return LineStirng
706: */
707: public LineString line(int[] xy) {
708: Coordinate[] coords = new Coordinate[xy.length / 2];
709:
710: for (int i = 0; i < xy.length; i += 2) {
711: coords[i / 2] = new Coordinate(xy[i], xy[i + 1]);
712: }
713:
714: return gf.createLineString(coords);
715: }
716:
717: /**
718: * Generate a MultiLineString from two dimensional ordinates
719: *
720: * @param xy
721: * @return MultiLineStirng
722: */
723: public MultiLineString lines(int[][] xy) {
724: LineString[] lines = new LineString[xy.length];
725:
726: for (int i = 0; i < xy.length; i++) {
727: lines[i] = line(xy[i]);
728: }
729:
730: return gf.createMultiLineString(lines);
731: }
732:
733: /**
734: * Convience constructor for GeometryFactory.createPolygon.
735: * <p>
736: * The provided xy ordinates are turned into a linear rings.
737: * </p>
738: * @param xy Two dimensional ordiantes.
739: * @return Polygon
740: */
741: public Polygon polygon(int[] xy) {
742: LinearRing shell = ring(xy);
743: return gf.createPolygon(shell, null);
744: }
745:
746: /**
747: * Convience constructor for GeometryFactory.createPolygon.
748: * <p>
749: * The provided xy and holes are turned into linear rings.
750: * </p>
751: * @param xy Two dimensional ordiantes.
752: * @param holes Holes in polygon or null.
753: *
754: * @return Polygon
755: */
756: public Polygon polygon(int[] xy, int[] holes[]) {
757: if (holes == null || holes.length == 0) {
758: return polygon(xy);
759: }
760: LinearRing shell = ring(xy);
761:
762: LinearRing[] rings = new LinearRing[holes.length];
763:
764: for (int i = 0; i < xy.length; i++) {
765: rings[i] = ring(holes[i]);
766: }
767: return gf.createPolygon(shell, rings);
768: }
769:
770: /**
771: * Convience constructor for GeometryFactory.createLinearRing.
772: *
773: * @param xy Two dimensional ordiantes.
774: * @return LinearRing for use with polygon
775: */
776: public LinearRing ring(int[] xy) {
777: int length = xy.length / 2;
778: if (xy[0] != xy[xy.length - 2] || xy[1] != xy[xy.length - 1]) {
779: length++;
780: }
781: Coordinate[] coords = new Coordinate[length];
782:
783: for (int i = 0; i < xy.length; i += 2) {
784: coords[i / 2] = new Coordinate(xy[i], xy[i + 1]);
785: }
786: if (xy[0] != xy[xy.length - 2] || xy[1] != xy[xy.length - 1]) {
787: coords[length - 1] = coords[0];
788: }
789: return gf.createLinearRing(coords);
790: }
791: }
|