/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2006-2008, Open Source Geospatial Foundation (OSGeo) * * 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; * version 2.1 of the License. * * 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. */ package org.geotools.geometry.iso.primitive; import java.util.Set; import org.opengis.geometry.complex.Complex; import org.opengis.geometry.primitive.OrientablePrimitive; import org.opengis.geometry.primitive.Primitive; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * * Orientable primitives (ISO 19107 v5 figure 10) are those that can be mirrored * into new geometric objects in terms of their internal local coordinate * systems (manifold charts). For curves, the orientation reflects the direction * in which the curve is traversed, that is, the sense of its parameterization. * When used as boundary curves, the surface being bounded is to the "left" of * the oriented curve. For surfaces, the orientation reflects from which * direction the local coordinate system can be viewed as right handed, the * "top" or the surface being the direction of a completing z-axis that would * form a right-handed system. When used as a boundary surface, the bounded * solid is "below" the surface. The orientation of points and solids has no * immediate geometric interpretation in 3-dimensional space. * OrientablePrimitive objects are essentially references to geometric * primitives that carry an "orientation" reversal flag (either "+" or "-") that * determines whether this primitive agrees or disagrees with the orientation of * the referenced object. * * NOTE There are several reasons for subclassing the “positive” primitives * under the orientable primitives. First is a matter of the semantics of * subclassing. Subclassing is assumed to be a “is type of” hierarchy. In the * view used, the “positive” primitive is simply the orientable one with the * positive orientation. If the opposite view were taken, and orientable * primitives were subclassed under the “positive” primitive, then by * subclassing logic, the “negative” primitive would have to hold the same sort * of geometric description that the “positive” primitive does. The only viable * solution would be to separate “negative” primitives under the geometric root * as being some sort of reference to their opposite. This adds a great deal of * complexity to the subclassing tree. To minimize the number of objects and to * bypass this logical complexity, positively oriented primitives are * self-referential (are instances of the corresponding primitive subtype) while * negatively oriented primitives are not. * * * * @source $URL$ * @version <A HREF="http://www.opengis.org/docs/01-101.pdf">Abstract * Specification V5</A> * @author Jackson Roehrig & Sanjay Jena * */ public abstract class OrientablePrimitiveImpl extends PrimitiveImpl implements OrientablePrimitive { /** * Oriented Association (from Specification of OrientablePrimitive) Each * Primitive of dimension 1 or 2 is associated to two OrientablePrimitives, * one for each possible orientation. * * Primitive::proxy [2] : Reference<OrientablePrimitive>; * * OrientablePrimitive::primitive [1] : Reference<Primitive>; For curves * and surfaces, there are exactly two orientable primitives for each * geometric object. * * Primitive: (proxy ? notEmpty) = (dimension = 1 or dimension = 2); * * OrientablePrimitive: a, b :OrientablePrimitive * ((a.primitive=b.primitive)and(a.orientation=b.orientation)) implies a=b; * * As the positive orientable primitive is self-referencing to the * primitive, the field proxy has only one value, which is the opposite * orientable primitive. See the method OrientablePrimitive[] getProxy() */ protected OrientablePrimitive proxy = null; /** * Constructor for empty Orientable Primitive * * @param crs * */ protected OrientablePrimitiveImpl(CoordinateReferenceSystem crs) { super(crs, null, null, null); this.proxy = this.createProxy(); } /** * Constructor * * @param crs * @param containedPrimitive * @param containingPrimitive * @param complex */ protected OrientablePrimitiveImpl(CoordinateReferenceSystem crs, Set<Primitive> containedPrimitive, Set<Primitive> containingPrimitive, Set<Complex> complex) { super(crs, containedPrimitive, containingPrimitive, complex); this.proxy = this.createProxy(); } /** * @return a new orientable primitive with negative orientation */ protected abstract OrientablePrimitive createProxy(); /** * Returns an array with two orientable primitives, whereas the first one is * "this" object and the second one the field proxy * * @return an array OrientablePrimitive[2] with the positive and the * negative orientable primitive */ public OrientablePrimitive[] getProxy() { return new OrientablePrimitive[] { this, this.proxy }; } /** * Orientable primitives are often denoted by a sign (for the orientation) * and a base geometry (curve or surface). The sign datatype is defined in * ISO 19103. If "c" is a curve, then "<+, c>" is its positive orientable * curve and "<-, c>" is its negative orientable curve. In most cases, * leaving out the syntax for record "< , >" does not lead to confusion, so "<+, * c>" may be written as "+c" or simply "c", and "<-, c>" as "-c". Curve * space arithmetic can be performed if the curves align properly, so that: * * For c, d : OrientableCurves such that c.endPoint = d.startPoint then * ( c + d ) ==: CompositeCurve = < c, d > * * @return 1 if positive and -1 if negative */ /* (non-Javadoc) * @see org.opengis.geometry.primitive.OrientablePrimitive#getOrientation() */ public int getOrientation() { return 1; } /* (non-Javadoc) * @see org.opengis.geometry.primitive.OrientablePrimitive#getPrimitive() */ public Primitive getPrimitive() { return this; } }