gvsig-vectorediting / org.gvsig.vectorediting.offset / trunk / org.gvsig.vectorediting.offset / org.gvsig.vectorediting.offset.lib / org.gvsig.vectorediting.offset.lib.prov / org.gvsig.vectorediting.offset.lib.prov.offset / src / main / java / org / gvsig / vectorediting / offset / lib / prov / offset / OffsetEditingProvider.java @ 2173
History | View | Annotate | Download (26 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 |
package org.gvsig.vectorediting.offset.lib.prov.offset; |
25 |
|
26 |
import java.util.ArrayList; |
27 |
import java.util.HashMap; |
28 |
import java.util.LinkedHashMap; |
29 |
import java.util.List; |
30 |
import java.util.Map; |
31 |
import org.apache.commons.lang3.StringUtils; |
32 |
import org.gvsig.fmap.dal.exception.DataException; |
33 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
34 |
import org.gvsig.fmap.dal.feature.Feature; |
35 |
import org.gvsig.fmap.dal.feature.FeatureSelection; |
36 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
37 |
import org.gvsig.fmap.geom.Geometry; |
38 |
import org.gvsig.fmap.geom.GeometryException; |
39 |
import org.gvsig.fmap.geom.GeometryLocator; |
40 |
import org.gvsig.fmap.geom.GeometryManager; |
41 |
import org.gvsig.fmap.geom.aggregate.Aggregate; |
42 |
import org.gvsig.fmap.geom.aggregate.MultiCurve; |
43 |
import org.gvsig.fmap.geom.aggregate.MultiPoint; |
44 |
import org.gvsig.fmap.geom.aggregate.MultiSurface; |
45 |
import org.gvsig.fmap.geom.operation.GeometryOperationException; |
46 |
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException; |
47 |
import org.gvsig.fmap.geom.primitive.Arc; |
48 |
import org.gvsig.fmap.geom.primitive.Circle; |
49 |
import org.gvsig.fmap.geom.primitive.Circumference; |
50 |
import org.gvsig.fmap.geom.primitive.Curve; |
51 |
import org.gvsig.fmap.geom.primitive.Ellipse; |
52 |
import org.gvsig.fmap.geom.primitive.FilledSpline; |
53 |
import org.gvsig.fmap.geom.primitive.Line; |
54 |
import org.gvsig.fmap.geom.primitive.PeriEllipse; |
55 |
import org.gvsig.fmap.geom.primitive.Point; |
56 |
import org.gvsig.fmap.geom.primitive.Polygon; |
57 |
import org.gvsig.fmap.geom.primitive.Spline; |
58 |
import org.gvsig.fmap.geom.primitive.Surface; |
59 |
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol; |
60 |
import org.gvsig.tools.ToolsLocator; |
61 |
import org.gvsig.tools.dispose.DisposableIterator; |
62 |
import org.gvsig.tools.dynobject.DynObject; |
63 |
import org.gvsig.tools.i18n.I18nManager; |
64 |
import org.gvsig.tools.service.spi.ProviderServices; |
65 |
import org.gvsig.vectorediting.lib.api.DrawingStatus; |
66 |
import org.gvsig.vectorediting.lib.api.EditingServiceParameter; |
67 |
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE; |
68 |
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException; |
69 |
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException; |
70 |
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException; |
71 |
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException; |
72 |
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider; |
73 |
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus; |
74 |
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter; |
75 |
import org.gvsig.vectorediting.lib.spi.EditingProvider; |
76 |
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory; |
77 |
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator; |
78 |
import org.gvsig.vectorediting.lib.spi.EditingProviderManager; |
79 |
import org.gvsig.vectorediting.lib.spi.EditingProviderServices; |
80 |
|
81 |
public class OffsetEditingProvider extends AbstractEditingProvider implements |
82 |
EditingProvider { |
83 |
|
84 |
private static final Double PRECISION = 1.0e-5; |
85 |
|
86 |
private static final String LEFT = "_left"; |
87 |
|
88 |
private static final String RIGHT = "_right"; |
89 |
|
90 |
private final EditingServiceParameter selectionParameter; |
91 |
|
92 |
private final EditingServiceParameter offsetParameter; |
93 |
|
94 |
private final EditingServiceParameter sideParameter; |
95 |
|
96 |
private final EditingServiceParameter deleteOriginalGeometriesParameter; |
97 |
|
98 |
private boolean deleteOriginalGeometries = false; |
99 |
|
100 |
private Map<EditingServiceParameter, Object> values; |
101 |
|
102 |
private final Map<String, String> options; |
103 |
|
104 |
private final FeatureStore featureStore; |
105 |
|
106 |
public OffsetEditingProvider(ProviderServices providerServices, DynObject parameters) {
|
107 |
super(providerServices);
|
108 |
this.featureStore = (FeatureStore) parameters.getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
|
109 |
I18nManager i18nManager = ToolsLocator.getI18nManager(); |
110 |
|
111 |
this.selectionParameter
|
112 |
= new DefaultEditingServiceParameter("selection", |
113 |
i18nManager.getTranslation("selection"), TYPE.SELECTION);
|
114 |
|
115 |
this.offsetParameter
|
116 |
= new DefaultEditingServiceParameter("offset_distance", |
117 |
i18nManager.getTranslation("offset_distance"),
|
118 |
TYPE.POSITION, TYPE.VALUE, TYPE.DISTANCE); |
119 |
|
120 |
Map<String, String> sideOptions = new HashMap<>(); |
121 |
sideOptions.put(LEFT, i18nManager.getTranslation(LEFT)); |
122 |
sideOptions.put(RIGHT, i18nManager.getTranslation(RIGHT)); |
123 |
|
124 |
this.sideParameter
|
125 |
= new DefaultEditingServiceParameter("side", |
126 |
i18nManager.getTranslation("_side"),
|
127 |
sideOptions, |
128 |
TYPE.OPTION, TYPE.POSITION); |
129 |
|
130 |
this.options = new LinkedHashMap<>(); |
131 |
options.put(i18nManager.getTranslation("short_yes"),
|
132 |
"delete_original_geometries");
|
133 |
options.put(i18nManager.getTranslation("short_no"),
|
134 |
"keep_original_geometries");
|
135 |
|
136 |
// EditingProviderServices editingProviderServices
|
137 |
// = (EditingProviderServices) getProviderServices();
|
138 |
|
139 |
String consoleMsg
|
140 |
= ((EditingProviderServices)providerServices).makeConsoleMessage( |
141 |
"delete_original_geometries_question", options);
|
142 |
|
143 |
this.deleteOriginalGeometriesParameter
|
144 |
= new DefaultEditingServiceParameter("Delete original geometries", |
145 |
consoleMsg, options, TYPE.OPTION); |
146 |
|
147 |
} |
148 |
|
149 |
@Override
|
150 |
public EditingServiceParameter next() {
|
151 |
|
152 |
if (values.get(selectionParameter) == null) { |
153 |
return selectionParameter;
|
154 |
} else if (values.get(offsetParameter) == null) { |
155 |
return offsetParameter;
|
156 |
} else if (values.get(sideParameter) == null) { |
157 |
Object offsetValue = values.get(offsetParameter);
|
158 |
if (!(offsetValue instanceof Point)) { |
159 |
Double distance = (Double) offsetValue; |
160 |
if (distance >= 0) { |
161 |
return sideParameter;
|
162 |
} |
163 |
} |
164 |
} |
165 |
|
166 |
if (values.get(deleteOriginalGeometriesParameter) == null) { |
167 |
return this.deleteOriginalGeometriesParameter; |
168 |
} |
169 |
|
170 |
return null; |
171 |
} |
172 |
|
173 |
@Override
|
174 |
public DrawingStatus getDrawingStatus(Point mousePosition) throws DrawServiceException { |
175 |
DefaultDrawingStatus drawingStatus = new DefaultDrawingStatus();
|
176 |
EditingProviderManager editingProviderManager |
177 |
= EditingProviderLocator.getProviderManager(); |
178 |
// ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
|
179 |
ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
|
180 |
ISymbol auxiliaryLineSymbolEditingDirection = editingProviderManager.getSymbol("auxiliary-line-symbol-editing-direction");
|
181 |
ISymbol lineSymbolEditing = editingProviderManager.getSymbol("line-symbol-editing");
|
182 |
ISymbol polygonSymbolEditing = editingProviderManager.getSymbol("polygon-symbol-editing");
|
183 |
|
184 |
FeatureSelection selected |
185 |
= (FeatureSelection) values.get(selectionParameter); |
186 |
try {
|
187 |
if ((selected != null) && !selected.isEmpty()) { |
188 |
Point point; // = null; |
189 |
double distance = 0.0; |
190 |
double side = 1.0; |
191 |
Object offsetValue = values.get(offsetParameter);
|
192 |
|
193 |
if (offsetValue != null) { |
194 |
if (offsetValue instanceof Point) { |
195 |
distance = Math.abs(getMinDistance(selected, (Point) offsetValue)); |
196 |
} else {
|
197 |
distance = (Double) offsetValue;
|
198 |
} |
199 |
|
200 |
Object sideValue = values.get(sideParameter);
|
201 |
if (sideValue == null) { |
202 |
point = mousePosition; |
203 |
side = Math.signum(getMinDistance(selected, point));
|
204 |
} else {
|
205 |
Double signum = getSideSignum((String) sideValue); |
206 |
if (signum != null) { |
207 |
side = signum; |
208 |
} |
209 |
} |
210 |
} else {
|
211 |
point = mousePosition; |
212 |
distance = getMinDistance(selected, point); |
213 |
} |
214 |
|
215 |
DisposableIterator it; |
216 |
it = selected.fastIterator(); |
217 |
|
218 |
while (it.hasNext()) {
|
219 |
Feature feat = (Feature) it.next(); |
220 |
Geometry transformedGeometry = feat.getDefaultGeometry().offset(distance * side); |
221 |
|
222 |
ISymbol symbol = null;
|
223 |
if (transformedGeometry instanceof Curve || transformedGeometry instanceof MultiCurve) { |
224 |
symbol = lineSymbolEditing; |
225 |
drawingStatus.addStatus(feat.getDefaultGeometry(), auxiliaryLineSymbolEditingDirection, "Direction");
|
226 |
} else if (transformedGeometry instanceof Surface || transformedGeometry instanceof MultiSurface) { |
227 |
symbol = polygonSymbolEditing; |
228 |
} else if (transformedGeometry instanceof Point || transformedGeometry instanceof MultiPoint) { |
229 |
symbol = auxiliaryPointSymbolEditing; |
230 |
} |
231 |
if (transformedGeometry instanceof Aggregate) { |
232 |
int primitivesNumber = ((Aggregate) transformedGeometry).getPrimitivesNumber();
|
233 |
for (int i = 0; i < primitivesNumber; i++) { |
234 |
drawingStatus.addStatus(((Aggregate) transformedGeometry).getPrimitiveAt(i), symbol, "");
|
235 |
} |
236 |
} else {
|
237 |
drawingStatus.addStatus(transformedGeometry, symbol, "");
|
238 |
} |
239 |
} |
240 |
it.dispose(); |
241 |
} |
242 |
return drawingStatus;
|
243 |
} catch (Exception e) { |
244 |
throw new DrawServiceException(e); |
245 |
} |
246 |
} |
247 |
|
248 |
/**
|
249 |
* @param selected
|
250 |
* @param point
|
251 |
* @return
|
252 |
* @throws DataException
|
253 |
* @throws GeometryOperationException
|
254 |
* @throws GeometryOperationNotSupportedException
|
255 |
* @throws GeometryException
|
256 |
*/
|
257 |
private double getMinDistance(FeatureSelection selected, Point point) throws DataException, GeometryOperationNotSupportedException, GeometryOperationException, GeometryException { |
258 |
double minorDistance = Double.POSITIVE_INFINITY; |
259 |
DisposableIterator it; |
260 |
it = selected.fastIterator(); |
261 |
while (it.hasNext()) {
|
262 |
Feature feat = (Feature) it.next(); |
263 |
Geometry geometry = feat.getDefaultGeometry(); |
264 |
double distance = getDistance(geometry, point);
|
265 |
if (distance < minorDistance) {
|
266 |
minorDistance = distance; |
267 |
} |
268 |
} |
269 |
it.dispose(); |
270 |
return minorDistance;
|
271 |
|
272 |
} |
273 |
|
274 |
/**
|
275 |
* @param geometry
|
276 |
* @param point
|
277 |
* @return
|
278 |
* @throws GeometryOperationException
|
279 |
* @throws GeometryOperationNotSupportedException
|
280 |
* @throws GeometryException
|
281 |
*/
|
282 |
private double getDistance(Geometry geometry, Point point) throws GeometryOperationNotSupportedException, GeometryOperationException, GeometryException { |
283 |
GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
284 |
if (geometry instanceof Arc) { |
285 |
Arc arc = (Arc) geometry; |
286 |
Point center = arc.getCenterPoint();
|
287 |
double radius = center.distance(arc.getInitPoint());
|
288 |
double distance = center.distance(point) - radius;
|
289 |
return distance;
|
290 |
} |
291 |
|
292 |
if (geometry instanceof Circle) { |
293 |
Circle circle = (Circle) geometry; |
294 |
return circle.getCenter().distance(point) - circle.getRadious();
|
295 |
} |
296 |
if (geometry instanceof Circumference) { |
297 |
Circumference circumference = (Circumference) geometry; |
298 |
return circumference.getCenter().distance(point) - circumference.getRadious();
|
299 |
} |
300 |
if (geometry instanceof PeriEllipse) { |
301 |
double minDistance = Double.POSITIVE_INFINITY; |
302 |
PeriEllipse ellipse = (PeriEllipse) geometry; |
303 |
Geometry[] closestPoints = point.closestPoints(ellipse);
|
304 |
if (closestPoints != null) { |
305 |
for (int i = 0; i < closestPoints.length; i++) { |
306 |
Geometry closestPoint = closestPoints[i]; |
307 |
if (!point.equals(closestPoint)) {
|
308 |
double distance = closestPoint.distance(point);
|
309 |
if (distance < minDistance) {
|
310 |
minDistance = distance; |
311 |
} |
312 |
} |
313 |
} |
314 |
} |
315 |
Ellipse auxEllipse = (Ellipse) geomManager.create(Geometry.TYPES.ELLIPSE, geometry.getGeometryType().getSubType()); |
316 |
auxEllipse.setPoints(ellipse.getAxis1Start(), ellipse.getAxis1End(), ellipse.getAxis2Dist()); |
317 |
if (auxEllipse.contains(point)) {
|
318 |
return -minDistance;
|
319 |
} |
320 |
return minDistance;
|
321 |
} |
322 |
if (geometry instanceof Ellipse) { |
323 |
Ellipse ellipse = (Ellipse) geometry; |
324 |
PeriEllipse auxPeriEllipse = (PeriEllipse) geomManager.create(Geometry.TYPES.PERIELLIPSE, geometry.getGeometryType().getSubType()); |
325 |
auxPeriEllipse.setPoints(ellipse.getAxis1Start(), ellipse.getAxis1End(), ellipse.getAxis2Dist()); |
326 |
double distance = getDistance(auxPeriEllipse, point);
|
327 |
|
328 |
return distance;
|
329 |
} |
330 |
|
331 |
if (geometry instanceof Spline || geometry instanceof FilledSpline) { |
332 |
return getDistance(geometry.toLines().getPrimitiveAt(0), point); |
333 |
} |
334 |
|
335 |
if (geometry instanceof Line) { |
336 |
Line line = (Line) geometry; |
337 |
double minDistance = Double.POSITIVE_INFINITY; |
338 |
Geometry[] closestPoints = point.closestPoints(line);
|
339 |
Point closestPoint = null; |
340 |
if (closestPoints != null) { |
341 |
for (Geometry closestPoint1 : closestPoints) {
|
342 |
Point p = (Point) closestPoint1; |
343 |
if (!point.equals(p)) {
|
344 |
double distance = p.distance(point);
|
345 |
if (distance < minDistance) {
|
346 |
minDistance = distance; |
347 |
closestPoint = p; |
348 |
} |
349 |
} |
350 |
} |
351 |
} |
352 |
if (closestPoint != null) { |
353 |
for (int i = 0; i < line.getNumVertices() - 1; i++) { |
354 |
Line segment = (Line) geomManager.create(Geometry.TYPES.LINE, geometry.getGeometryType().getSubType()); |
355 |
segment.addVertex(line.getVertex(i)); |
356 |
segment.addVertex(line.getVertex(i + 1));
|
357 |
if (segment.isWithinDistance(closestPoint, PRECISION)) {
|
358 |
if (line.getVertex(0).equals(line.getVertex(line.getNumVertices() - 1))) { //isClosed |
359 |
if (line.toPolygons().contains(point)) {
|
360 |
return -minDistance;
|
361 |
} |
362 |
return minDistance;
|
363 |
} else {
|
364 |
return getDirectedDistance(closestPoint, point, segment);
|
365 |
} |
366 |
} |
367 |
} |
368 |
} |
369 |
} |
370 |
|
371 |
if (geometry instanceof Polygon) { |
372 |
Polygon polygon = (Polygon) geometry; |
373 |
if (!polygon.contains(point)) {
|
374 |
double minDistance = Double.POSITIVE_INFINITY; |
375 |
Geometry[] closestPoints = point.closestPoints(polygon);
|
376 |
Point closestPoint = null; |
377 |
if (closestPoints != null) { |
378 |
for (Geometry closestPoint1 : closestPoints) {
|
379 |
Point p = (Point) closestPoint1; |
380 |
if (!point.equals(p)) {
|
381 |
double distance = p.distance(point);
|
382 |
if (distance < minDistance) {
|
383 |
minDistance = distance; |
384 |
closestPoint = p; |
385 |
} |
386 |
} |
387 |
} |
388 |
} |
389 |
if (closestPoint != null) { |
390 |
return closestPoint.distance(point);
|
391 |
} |
392 |
} else {
|
393 |
Line auxLine = (Line) polygon.toLines().getPrimitiveAt(0); |
394 |
if (auxLine != null) { |
395 |
return getDistance(auxLine, point);
|
396 |
} |
397 |
} |
398 |
} |
399 |
|
400 |
if (geometry instanceof Aggregate) { |
401 |
double minDistance = Double.POSITIVE_INFINITY; |
402 |
Aggregate aggregate2 = (Aggregate) geometry; |
403 |
for (int i = 0; i < aggregate2.getPrimitivesNumber(); i++) { |
404 |
double distance = getDistance(aggregate2.getPrimitiveAt(i), point);
|
405 |
if (distance < minDistance) {
|
406 |
minDistance = distance; |
407 |
} |
408 |
} |
409 |
return minDistance;
|
410 |
} |
411 |
return 0.0; |
412 |
} |
413 |
|
414 |
@Override
|
415 |
public void stop() { |
416 |
values.clear(); |
417 |
} |
418 |
|
419 |
private void validateAndInsertValue(EditingServiceParameter param, |
420 |
Object value) throws InvalidEntryException { |
421 |
I18nManager i18nManager = ToolsLocator.getI18nManager(); |
422 |
|
423 |
if (param == selectionParameter) {
|
424 |
if (value instanceof FeatureSelection) { |
425 |
values.put(param, value); |
426 |
} |
427 |
} else if (param == offsetParameter) { |
428 |
if (value instanceof Point) { |
429 |
try {
|
430 |
Double distance = getMinDistance((FeatureSelection) values.get(selectionParameter), (Point) value); |
431 |
values.put(param, Math.abs(distance));
|
432 |
values.put(sideParameter, coerceSide(distance)); |
433 |
} catch (Exception e) { |
434 |
throw new InvalidEntryException(e); |
435 |
} |
436 |
return;
|
437 |
} |
438 |
if (value instanceof Double) { |
439 |
Double distance = (Double) value; |
440 |
if (distance >= 0) { |
441 |
values.put(param, value); |
442 |
} else {
|
443 |
values.put(param, Math.abs(distance));
|
444 |
values.put(sideParameter, coerceSide(distance)); |
445 |
} |
446 |
} |
447 |
} else if (param == sideParameter) { |
448 |
if (value instanceof Point) { |
449 |
try {
|
450 |
values.put(param, coerceSide(getMinDistance((FeatureSelection) values.get(selectionParameter), (Point) value)));
|
451 |
} catch (Exception e) { |
452 |
throw new InvalidEntryException(e); |
453 |
} |
454 |
return;
|
455 |
} |
456 |
if (value instanceof String) { |
457 |
values.put(param, coerceSide(value)); |
458 |
} |
459 |
} else if (param == deleteOriginalGeometriesParameter) { |
460 |
if (value instanceof String) { |
461 |
if (((String) value).trim().equalsIgnoreCase( |
462 |
i18nManager.getTranslation("short_yes"))) {
|
463 |
deleteOriginalGeometries = true;
|
464 |
} else if (((String) value).trim().equalsIgnoreCase( |
465 |
i18nManager.getTranslation("short_no"))) {
|
466 |
deleteOriginalGeometries = false;
|
467 |
} else {
|
468 |
throw new InvalidEntryException(null); |
469 |
} |
470 |
values.put(param, value); |
471 |
} |
472 |
} |
473 |
|
474 |
} |
475 |
|
476 |
private String coerceSide(Object value) throws InvalidEntryException { |
477 |
|
478 |
if (value instanceof Double) { |
479 |
return (Double) value >= 0 ? LEFT : RIGHT; |
480 |
} |
481 |
if (value instanceof String) { |
482 |
Double signum = getSideSignum((String) value); |
483 |
if (signum != null) { |
484 |
return signum >= 0 ? LEFT : RIGHT; |
485 |
} |
486 |
} |
487 |
throw new InvalidEntryException(null); |
488 |
} |
489 |
|
490 |
private Double getSideSignum(String side) { |
491 |
I18nManager i18nManager = ToolsLocator.getI18nManager(); |
492 |
String sideTrim = side.trim();
|
493 |
if (StringUtils.equalsIgnoreCase(sideTrim, LEFT)
|
494 |
|| StringUtils.startsWithIgnoreCase(i18nManager.getTranslation(LEFT), sideTrim)) { |
495 |
return 1.0; |
496 |
} else if (StringUtils.equalsIgnoreCase(sideTrim, RIGHT) |
497 |
|| StringUtils.startsWithIgnoreCase(i18nManager.getTranslation(RIGHT), sideTrim)) { |
498 |
return -1.0; |
499 |
} |
500 |
return null; |
501 |
} |
502 |
|
503 |
@Override
|
504 |
public List<EditingServiceParameter> getParameters() { |
505 |
List<EditingServiceParameter> list
|
506 |
= new ArrayList<>(); |
507 |
list.add(selectionParameter); |
508 |
list.add(offsetParameter); |
509 |
list.add(sideParameter); |
510 |
return list;
|
511 |
} |
512 |
|
513 |
@Override
|
514 |
public void setValue(Object value) throws InvalidEntryException { |
515 |
EditingServiceParameter param = next(); |
516 |
validateAndInsertValue(param, value); |
517 |
} |
518 |
|
519 |
@Override
|
520 |
public void finishAndStore() throws FinishServiceException { |
521 |
|
522 |
FeatureSelection selected |
523 |
= (FeatureSelection) values.get(selectionParameter); |
524 |
try {
|
525 |
if (!selected.isEmpty()) {
|
526 |
double side = 1.0; |
527 |
Object sideValue = values.get(sideParameter);
|
528 |
if (sideValue != null) { |
529 |
if (sideValue instanceof String) { |
530 |
Double signum = getSideSignum((String) sideValue); |
531 |
side = signum != null ? signum : null; |
532 |
} |
533 |
} |
534 |
double distance = ((Double) values.get(offsetParameter)) * side; |
535 |
DisposableIterator it; |
536 |
it = selected.fastIterator(); |
537 |
|
538 |
while (it.hasNext()) {
|
539 |
Feature feature = (Feature) it.next(); |
540 |
Geometry geom; |
541 |
try {
|
542 |
geom = feature.getDefaultGeometry().offset(distance); |
543 |
} catch (GeometryOperationNotSupportedException | GeometryOperationException e) {
|
544 |
throw new FinishServiceException(e); |
545 |
} |
546 |
|
547 |
if (this.deleteOriginalGeometries) { |
548 |
// Se sustituye la geometr?a original por la
|
549 |
// calculada
|
550 |
EditableFeature editableFeature |
551 |
= feature.getEditable(); |
552 |
editableFeature.setDefaultGeometry(geom); |
553 |
((EditingProviderServices) getProviderServices()) |
554 |
.updateFeatureInFeatureStore(editableFeature, |
555 |
featureStore); |
556 |
} else {
|
557 |
// Se crea una feature nueva copiando los valores de
|
558 |
// la feature original excepto aquellos que sean PK
|
559 |
EditingProviderServices editingProviderServices |
560 |
= (EditingProviderServices) getProviderServices(); |
561 |
EditableFeature editableFeature |
562 |
= editingProviderServices |
563 |
.getFeatureCopyWithoutPK(featureStore, |
564 |
feature); |
565 |
editableFeature.setDefaultGeometry(geom); |
566 |
editingProviderServices |
567 |
.insertFeatureIntoFeatureStore(editableFeature, |
568 |
featureStore); |
569 |
} |
570 |
|
571 |
} |
572 |
it.dispose(); |
573 |
featureStore.getFeatureSelection().deselectAll(); |
574 |
} |
575 |
} catch (DataException e) {
|
576 |
throw new FinishServiceException(e); |
577 |
} |
578 |
} |
579 |
|
580 |
private Double getDirectedDistance(Point pointInLine, Point distancePoint, Line line) |
581 |
throws GeometryOperationNotSupportedException, GeometryOperationException {
|
582 |
Double distance = distancePoint.distance(pointInLine);
|
583 |
EditingProviderServices editingProviderServices |
584 |
= (EditingProviderServices) getProviderServices(); |
585 |
Double angle = editingProviderServices.getAngle(pointInLine, distancePoint);
|
586 |
double angleLine = editingProviderServices.getAngle(line.getVertex(0), line.getVertex(1)); |
587 |
|
588 |
Double angleDifference = angle - angleLine;
|
589 |
if (angleDifference < 0) { |
590 |
angleDifference += 2 * Math.PI; |
591 |
} |
592 |
if (angleDifference > Math.PI) { |
593 |
distance = -distance; |
594 |
} |
595 |
return distance;
|
596 |
} |
597 |
|
598 |
@Override
|
599 |
public Geometry finish() throws FinishServiceException { |
600 |
return null; |
601 |
} |
602 |
|
603 |
@Override
|
604 |
public void start() throws StartServiceException { |
605 |
this.values = new HashMap<>(); |
606 |
FeatureSelection selected = null;
|
607 |
if (featureStore != null) { |
608 |
try {
|
609 |
selected |
610 |
= (FeatureSelection) featureStore.getFeatureSelection() |
611 |
.clone(); |
612 |
} catch (DataException e) {
|
613 |
throw new StartServiceException(e); |
614 |
} catch (CloneNotSupportedException e) { |
615 |
// Do nothing
|
616 |
} |
617 |
if ((selected != null) && (selected.getSelectedCount() > 0)) { |
618 |
values.put(selectionParameter, selected); |
619 |
} |
620 |
} |
621 |
} |
622 |
|
623 |
@Override
|
624 |
public String getName() { |
625 |
return OffsetEditingProviderFactory.PROVIDER_NAME;
|
626 |
} |
627 |
} |