001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032: package com.vividsolutions.jump.plugin.edit;
033:
034: import com.vividsolutions.jts.geom.Coordinate;
035: import com.vividsolutions.jts.geom.Geometry;
036: import com.vividsolutions.jts.geom.LineString;
037: import com.vividsolutions.jump.I18N;
038: import com.vividsolutions.jump.feature.Feature;
039: import com.vividsolutions.jump.feature.FeatureCollection;
040:
041: /**
042: * Uses geometry data in two {@link FeatureCollection}s to
043: * extract parameters for an affine transformation.
044: * The contents of the layers determines how the
045: * parameters are extracted.
046: * The layers can contain:
047: * <ul>
048: * <li>A 2-point vector - parameters will have isometric scaling and no shear
049: * <li>A 3-point LineString - a general affine transformation will be computed
050: * <li>(FUTURE) 1, 2 or 3 points, each with a tag value - the affine transformation will be
051: * computed from the mappings between the points.
052: * </ul>
053: *
054: * @author Martin Davis
055: * @version 1.0
056: */
057: public class AffineTransControlPointExtracter {
058: public static final int TYPE_UNKNOWN = 0;
059: public static final int TYPE_VECTOR = 1;
060: public static final int TYPE_LINE_3 = 2;
061:
062: private FeatureCollection fcSrc;
063: private FeatureCollection fcDest;
064:
065: private int inputType = TYPE_UNKNOWN;
066: private String parseErrMsg = I18N
067: .get("jump.plugin.edit.AffineTransControlPointExtracter.Unrecognized-control-point-geometry");
068:
069: private int numGeoms;
070: private Geometry[] geomSrc = new Geometry[3];
071: private Geometry[] geomDest = new Geometry[3];
072:
073: private int numControlPts;
074: private Coordinate[] controlPtSrc;
075: private Coordinate[] controlPtDest;
076:
077: public AffineTransControlPointExtracter(FeatureCollection fcSrc,
078: FeatureCollection fcDest) {
079: this .fcSrc = fcSrc;
080: this .fcDest = fcDest;
081: init();
082: }
083:
084: public int getInputType() {
085: return inputType;
086: }
087:
088: public String getParseErrorMessage() {
089: return parseErrMsg;
090: }
091:
092: public Coordinate[] getSrcControlPoints() {
093: return controlPtSrc;
094: }
095:
096: public Coordinate[] getDestControlPoints() {
097: return controlPtDest;
098: }
099:
100: private void init() {
101: parseInput();
102: }
103:
104: private void parseInput() {
105: inputType = TYPE_UNKNOWN;
106: int fcSrcSize = fcSrc.size();
107: int fcDestSize = fcDest.size();
108:
109: // error - # geoms must match
110: if (fcSrcSize != fcDestSize) {
111: parseErrMsg = I18N
112: .get("jump.plugin.edit.AffineTransControlPointExtracter.Control-point-collections-must-be-same-size");
113: return;
114: }
115: // for now only handling pair of geoms to define control points
116: if (fcSrcSize != 1) {
117: parseErrMsg = I18N
118: .get("jump.plugin.edit.AffineTransControlPointExtracter.Control-points-must-be-a-single-geometry");
119: return;
120: }
121:
122: geomSrc[0] = ((Feature) fcSrc.iterator().next()).getGeometry();
123: geomDest[0] = ((Feature) fcDest.iterator().next())
124: .getGeometry();
125:
126: if (geomSrc[0].getClass() != geomDest[0].getClass()) {
127: parseErrMsg = I18N
128: .get("jump.plugin.edit.AffineTransControlPointExtracter.Control-points-must-be-LineStrings");
129: return;
130: }
131:
132: // for now only handling LineStrings
133: if (!(geomSrc[0] instanceof LineString)) {
134: parseErrMsg = I18N
135: .get("jump.plugin.edit.AffineTransControlPointExtracter.Control-points-must-be-LineStrings");
136: return;
137: }
138:
139: parseLines();
140: return;
141: }
142:
143: private void parseLines() {
144: controlPtSrc = geomSrc[0].getCoordinates();
145: controlPtDest = geomDest[0].getCoordinates();
146:
147: if (controlPtSrc.length != controlPtDest.length) {
148: parseErrMsg = I18N
149: .get("jump.plugin.edit.AffineTransControlPointExtracter.Control-Point-LineStrings-are-different-lengths");
150: return;
151: }
152: if (controlPtSrc.length < 2) {
153: parseErrMsg = I18N
154: .get("jump.plugin.edit.AffineTransControlPointExtracter.Single-control-points-are-not-supported");
155: }
156: if (controlPtSrc.length > 3) {
157: parseErrMsg = I18N
158: .get("jump.plugin.edit.AffineTransControlPointExtracter.Too-many-points-in-LineString");
159: }
160: inputType = TYPE_VECTOR;
161: }
162:
163: }
|