Statistics
| Revision:

gvsig-vectorediting / org.gvsig.vectorediting / trunk / org.gvsig.vectorediting / org.gvsig.vectorediting.lib / org.gvsig.vectorediting.lib.prov / org.gvsig.vectorediting.lib.prov.regularpolygon / src / main / java / org / gvsig / vectorediting / lib / prov / regularpolygon / RegularPolygonEditingProvider.java @ 193

History | View | Annotate | Download (15.5 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright ? 2007-2014 gvSIG Association
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.vectorediting.lib.prov.regularpolygon;
26

    
27
import java.util.ArrayList;
28
import java.util.Collection;
29
import java.util.HashMap;
30
import java.util.LinkedHashMap;
31
import java.util.List;
32
import java.util.Map;
33

    
34
import org.gvsig.fmap.dal.feature.FeatureStore;
35
import org.gvsig.fmap.geom.Geometry;
36
import org.gvsig.fmap.geom.GeometryLocator;
37
import org.gvsig.fmap.geom.GeometryManager;
38
import org.gvsig.fmap.geom.aggregate.MultiCurve;
39
import org.gvsig.fmap.geom.primitive.Curve;
40
import org.gvsig.fmap.geom.primitive.OrientablePrimitive;
41
import org.gvsig.fmap.geom.primitive.Point;
42
import org.gvsig.fmap.geom.primitive.Surface;
43
import org.gvsig.fmap.geom.type.GeometryType;
44
import org.gvsig.tools.ToolsLocator;
45
import org.gvsig.tools.dynobject.DynObject;
46
import org.gvsig.tools.exception.BaseException;
47
import org.gvsig.tools.i18n.I18nManager;
48
import org.gvsig.tools.service.spi.ProviderServices;
49
import org.gvsig.vectorediting.lib.api.DrawingStatus;
50
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
51
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
52
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
53
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
54
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
55
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
56
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
57
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
58
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
59
import org.gvsig.vectorediting.lib.spi.EditingProvider;
60
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
61
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
62

    
63
/**
64
 * 
65
 * @author llmarques
66
 *
67
 */
68
public class RegularPolygonEditingProvider extends AbstractEditingProvider
69
    implements EditingProvider {
70

    
71
    protected EditingServiceParameter polygonSides;
72

    
73
    protected EditingServiceParameter center;
74

    
75
    protected EditingServiceParameter mode;
76

    
77
    protected EditingServiceParameter pointOfCircle;
78

    
79
    protected Map<EditingServiceParameter, Object> values;
80

    
81
    protected Map<String, String> options;
82

    
83
    protected FeatureStore featureStore;
84

    
85
    public RegularPolygonEditingProvider(ProviderServices providerServices,
86
        DynObject parameters) {
87
        super(providerServices);
88
        this.featureStore =
89
            (FeatureStore) parameters
90
                .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
91
        
92
        polygonSides =
93
            new DefaultEditingServiceParameter("sides",
94
                "sides_of_regular_polygon", EditingServiceParameter.TYPE.VALUE);
95

    
96
        options = new LinkedHashMap<String, String>();
97
        options.put("I", "inscribed");
98
        options.put("C", "circumscribed");
99

    
100
        mode =
101
            new DefaultEditingServiceParameter("mode",
102
                "inscribed_or_circumscribed", options,
103
                EditingServiceParameter.TYPE.OPTION);
104

    
105
        center =
106
            new DefaultEditingServiceParameter("center",
107
                "center_of_regular_polygon",
108
                EditingServiceParameter.TYPE.POSITION);
109

    
110
        pointOfCircle =
111
            new DefaultEditingServiceParameter("point_of_circle",
112
                "point_of_circle", EditingServiceParameter.TYPE.POSITION);
113
    }
114

    
115
    public EditingServiceParameter next() {
116
        if (values.get(polygonSides) == null) {
117
            return polygonSides;
118
        } else if (values.get(mode) == null) {
119
            return mode;
120
        } else if (values.get(center) == null) {
121
            return center;
122
        } else if (values.get(pointOfCircle) == null) {
123
            return pointOfCircle;
124
        }
125
        return null;
126
    }
127

    
128
    public DrawingStatus getDrawingStatus(Point mousePosition)
129
        throws DrawServiceException {
130
        DrawingStatus drawingStatus = new DefaultDrawingStatus();
131
        if (values != null) {
132

    
133
            Double sidesValue = (Double) values.get(polygonSides);
134
            String modeValue = (String) values.get(mode);
135
            Point centerValue = (Point) values.get(center);
136

    
137
            if (modeValue != null && centerValue != null) {
138

    
139
                try {
140

    
141
                    EditingProviderServices editingProviderServices =
142
                        (EditingProviderServices) getProviderServices();
143
                    int subtype =
144
                        editingProviderServices.getSubType(featureStore);
145

    
146
                    Curve polygon =
147
                        calculateRegularPolygon(modeValue, centerValue,
148
                            mousePosition, sidesValue.intValue());
149
                    Curve line =
150
                        editingProviderServices.createLine(centerValue.getX(),
151
                            centerValue.getY(), mousePosition.getX(),
152
                            mousePosition.getY(), subtype);
153

    
154
                    double radius = mousePosition.distance(centerValue);
155
                    Curve circumference =
156
                        editingProviderServices.createArc(centerValue, radius,
157
                            0, 2 * Math.PI, subtype);
158

    
159
                    drawingStatus.addGeometry(circumference);
160
                    drawingStatus.addGeometry(polygon);
161
                    drawingStatus.addGeometry(centerValue);
162
                    drawingStatus.addGeometry(line);
163

    
164
                } catch (BaseException e) {
165
                    throw new DrawServiceException(e);
166
                }
167
            }
168
        }
169
        return drawingStatus;
170
    }
171

    
172
    /**
173
     * Calculates polygon as of mode (inscribed or circumscribed), center of
174
     * polygon, point of circle and number of sides.
175
     * 
176
     * @param modeValue
177
     *            of polygon (inscribed or circumscribed).
178
     * @param centerValue
179
     *            of polygon
180
     * @param pointOfCircleValue
181
     *            of circle that inscribe or circumscribe polygon
182
     * @param sidesValue
183
     *            number of sides.
184
     */
185
    protected Curve calculateRegularPolygon(String modeValue,
186
        Point centerValue, Point pointOfCircle, int sidesValue)
187
        throws BaseException {
188
        
189
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
190

    
191
        EditingProviderServices editingProviderServices =
192
            (EditingProviderServices) getProviderServices();
193
        int subtype = editingProviderServices.getSubType(featureStore);
194

    
195
        Curve polygon =
196
            (Curve) geometryManager.create(Geometry.TYPES.CURVE, subtype);
197

    
198
        double initAngle =
199
            editingProviderServices.getAngle(centerValue, pointOfCircle);
200
        double radiusValue = pointOfCircle.distance(centerValue);
201
        double theta = 2 * Math.PI / sidesValue;
202

    
203
        if (modeValue.equalsIgnoreCase("I")) {
204

    
205
            for (int i = 0; i < sidesValue; ++i) {
206

    
207
                double x =
208
                    centerValue.getX() + radiusValue
209
                        * Math.cos(theta * i + initAngle);
210
                double y =
211
                    centerValue.getY() + radiusValue
212
                        * Math.sin(theta * i + initAngle);
213

    
214
                Point createPoint =
215
                    editingProviderServices.createPoint(x, y, subtype);
216

    
217
                polygon.addVertex(createPoint);
218
            }
219

    
220
        } else if (modeValue.equalsIgnoreCase("C")) {
221

    
222
            for (int i = 0; i < sidesValue; ++i) {
223

    
224
                double x =
225
                    centerValue.getX() + radiusValue
226
                        * Math.cos(theta * i + initAngle);
227
                double y =
228
                    centerValue.getY() + radiusValue
229
                        * Math.sin(theta * i + initAngle);
230

    
231
                Point apothemPoint =
232
                    editingProviderServices.createPoint(x, y, subtype);
233

    
234
                Double[] apothemParams =
235
                    editingProviderServices.getLineParams(centerValue,
236
                        apothemPoint);
237
                Point[] perpendicular =
238
                    editingProviderServices.getPerpendicular(apothemParams[0],
239
                        apothemParams[1], apothemPoint, subtype);
240

    
241
                double x1 =
242
                    centerValue.getX() + radiusValue
243
                        * Math.cos(theta * (i + 1) + initAngle);
244
                double y1 =
245
                    centerValue.getY() + radiusValue
246
                        * Math.sin(theta * (i + 1) + initAngle);
247

    
248
                Point nextApothemPoint =
249
                    editingProviderServices.createPoint(x1, y1, subtype);
250

    
251
                Double[] nextApothemParams =
252
                    editingProviderServices.getLineParams(centerValue,
253
                        nextApothemPoint);
254
                Point[] nextPerpendicular =
255
                    editingProviderServices.getPerpendicular(
256
                        nextApothemParams[0], nextApothemParams[1],
257
                        nextApothemPoint, subtype);
258

    
259
                Point vertex =
260
                    editingProviderServices.getIntersection(perpendicular,
261
                        nextPerpendicular, subtype);
262

    
263
                polygon.addVertex(vertex);
264
            }
265
        }
266
        polygon = (Curve) closeGeometry(polygon);
267
        return polygon;
268
    }
269

    
270
    /**
271
     * Close geometry if it is necessary.
272
     * 
273
     * @param geometry
274
     *            to be closed.
275
     */
276
    protected Geometry closeGeometry(Geometry geometry) {
277

    
278
        if (!isClose(geometry) && geometry != null) {
279

    
280
            if (geometry instanceof Surface) {
281
                Surface surface = (Surface) geometry;
282
                Point firstp = surface.getVertex(0);
283
                firstp = (Point) firstp.cloneGeometry();
284
                surface.addVertex(firstp);
285
                return surface;
286
            } else if (geometry instanceof Curve) {
287
                Curve line = (Curve) geometry;
288
                Point firstp = line.getVertex(0);
289
                firstp = (Point) firstp.cloneGeometry();
290
                line.addVertex(firstp);
291
                return line;
292
            }
293
        }
294
        return geometry;
295
    }
296

    
297
    /**
298
     * Gets if the geometry received by parameter is closed or not.
299
     * 
300
     * @param geometry
301
     * @return True if geometry is closed, otherwise false.
302
     */
303
    private boolean isClose(Geometry geometry) {
304

    
305
        if (geometry != null) {
306

    
307
            if (geometry instanceof OrientablePrimitive) {
308
                OrientablePrimitive orientablePrimitive =
309
                    (OrientablePrimitive) geometry;
310
                Point firstPoint = orientablePrimitive.getVertex(0);
311
                Point lastPoint =
312
                    orientablePrimitive.getVertex(orientablePrimitive
313
                        .getNumVertices() - 1);
314
                if (firstPoint.equals(lastPoint)) {
315
                    return true;
316
                }
317
            }
318
        }
319
        return false;
320
    }
321

    
322
    public void stop() throws StopServiceException {
323
        if (values != null) {
324
            values.clear();
325
        }
326
    }
327

    
328
    public List<EditingServiceParameter> getParameters() {
329
        List<EditingServiceParameter> parameters =
330
            new ArrayList<EditingServiceParameter>();
331
        parameters.add(polygonSides);
332
        parameters.add(mode);
333
        parameters.add(center);
334
        parameters.add(pointOfCircle);
335

    
336
        return parameters;
337
    }
338

    
339
    public void setValue(Object value) throws InvalidEntryException {
340
        EditingServiceParameter parameter = next();
341
        validateAndInsertValue(parameter, value);
342
    }
343

    
344
    private void validateAndInsertValue(EditingServiceParameter param,
345
        Object value) throws InvalidEntryException {
346

    
347
        if (param == polygonSides) {
348
            if (value instanceof Double) {
349

    
350
                double sides = (Double) value;
351

    
352
                if (sides > 0) {
353
                    values.put(param, sides);
354
                    return;
355
                } else {
356
                    throw new InvalidEntryException(null);
357
                }
358
            }
359
        } else if (param == mode) {
360

    
361
            if (value instanceof String) {
362

    
363
                String option = (String) value;
364
                Collection<String> valueOptions = options.keySet();
365

    
366
                if (valueOptions.contains(option)) {
367
                    values.put(param, value);
368
                    return;
369
                } else {
370
                    throw new InvalidEntryException(null);
371
                }
372
            }
373

    
374
        } else if (param == center) {
375

    
376
            if (value instanceof Point) {
377
                values.put(param, value);
378
                return;
379
            }
380

    
381
        } else if (param == pointOfCircle) {
382
            if (value instanceof Point) {
383
                values.put(param, value);
384
                return;
385
            }
386

    
387
        }
388
        throw new InvalidEntryException(null);
389
    }
390

    
391
    public Geometry finish() throws FinishServiceException {
392

    
393
        if (values != null) {
394

    
395
            Double sidesValue = (Double) values.get(polygonSides);
396
            String modeValue = (String) values.get(mode);
397
            Point centerValue = (Point) values.get(center);
398
            Point pointOfCircleValue = (Point) values.get(pointOfCircle);
399

    
400
            try {
401
                Curve polygon =
402
                    calculateRegularPolygon(modeValue, centerValue,
403
                        pointOfCircleValue, sidesValue.intValue());
404

    
405
                EditingProviderServices editingProviderServices =
406
                    (EditingProviderServices) getProviderServices();
407
                GeometryType geomType =
408
                    editingProviderServices.getGeomType(featureStore);
409

    
410
                if (geomType.isTypeOf(Geometry.TYPES.MULTICURVE)) {
411

    
412
                    MultiCurve multiCurve =
413
                        GeometryLocator.getGeometryManager().createMultiCurve(
414
                            geomType.getSubType());
415
                    multiCurve.addCurve(polygon);
416
                    return multiCurve;
417
                }
418

    
419
                return polygon;
420
            } catch (Exception e) {
421
                throw new FinishServiceException(e);
422
            }
423
        }
424
        return null;
425
    }
426

    
427
    public void finishAndStore() throws FinishServiceException {
428
        try {
429
            Geometry geometry = finish();
430
            if (geometry != null) {
431
                EditingProviderServices editingProviderServices =
432
                    (EditingProviderServices) getProviderServices();
433
                editingProviderServices.insertGeometryIntoFeatureStore(
434
                    geometry, featureStore);
435
            }
436
        } catch (Exception e) {
437
            throw new FinishServiceException(e);
438
        }
439

    
440
    }
441

    
442
    public void start() throws StartServiceException {
443
        values = new HashMap<EditingServiceParameter, Object>();
444
    }
445

    
446
    public String getName() {
447
        return RegularPolygonEditingProviderFactory.PROVIDER_NAME;
448
    }
449

    
450
}