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.chamfer / src / main / java / org / gvsig / vectorediting / lib / prov / chamfer / ChamferByLengthAndAngleEditingProvider.java @ 4284

History | View | Annotate | Download (66.8 KB)

1 3194 fdiaz
/**
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 3289 fdiaz
package org.gvsig.vectorediting.lib.prov.chamfer;
25 3194 fdiaz
26
import java.awt.Color;
27
import java.awt.geom.Point2D;
28
import java.util.ArrayList;
29
import java.util.Arrays;
30
import java.util.HashMap;
31
import java.util.List;
32
import java.util.Map;
33
import java.util.Objects;
34
import org.apache.commons.lang3.tuple.ImmutablePair;
35
import org.apache.commons.lang3.tuple.Pair;
36
import org.gvsig.euclidean.EuclideanLine2D;
37
import org.gvsig.euclidean.EuclideanManager;
38
import org.gvsig.fmap.dal.feature.EditableFeature;
39
import org.gvsig.fmap.dal.feature.Feature;
40
import org.gvsig.fmap.dal.feature.FeatureStore;
41
import org.gvsig.fmap.geom.Geometry;
42
import org.gvsig.fmap.geom.GeometryException;
43
import org.gvsig.fmap.geom.GeometryLocator;
44
import org.gvsig.fmap.geom.GeometryManager;
45
import org.gvsig.fmap.geom.GeometryUtils;
46
import org.gvsig.fmap.geom.aggregate.MultiLine;
47
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
48
import org.gvsig.fmap.geom.exception.CreateGeometryException;
49
import org.gvsig.fmap.geom.operation.GeometryOperationException;
50
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
51
import org.gvsig.fmap.geom.primitive.Arc;
52
import org.gvsig.fmap.geom.primitive.Curve;
53
import org.gvsig.fmap.geom.primitive.Line;
54
import org.gvsig.fmap.geom.primitive.Point;
55
import org.gvsig.fmap.geom.primitive.Polygon;
56
import org.gvsig.fmap.geom.primitive.Primitive;
57
import org.gvsig.fmap.geom.primitive.Surface;
58
import org.gvsig.fmap.mapcontext.MapContext;
59
import org.gvsig.fmap.mapcontext.rendering.symbols.ISymbol;
60
import org.gvsig.symbology.SymbologyLocator;
61
import org.gvsig.symbology.SymbologyManager;
62
import org.gvsig.symbology.fmap.mapcontext.rendering.symbol.text.ISimpleTextSymbol;
63
import org.gvsig.tools.ToolsLocator;
64
import org.gvsig.tools.dataTypes.DataTypes;
65
import org.gvsig.tools.dynobject.DynObject;
66
import org.gvsig.tools.i18n.I18nManager;
67
import org.gvsig.tools.service.spi.ProviderServices;
68
import org.gvsig.tools.util.ToolsUtilLocator;
69
import org.gvsig.vectorediting.lib.api.DrawingStatus;
70
import org.gvsig.vectorediting.lib.api.EditingServiceParameter;
71
import org.gvsig.vectorediting.lib.api.EditingServiceParameter.TYPE;
72
import org.gvsig.vectorediting.lib.api.exceptions.DrawServiceException;
73
import org.gvsig.vectorediting.lib.api.exceptions.FinishServiceException;
74
import org.gvsig.vectorediting.lib.api.exceptions.InvalidEntryException;
75
import org.gvsig.vectorediting.lib.api.exceptions.StartServiceException;
76
import org.gvsig.vectorediting.lib.api.exceptions.StopServiceException;
77
import static org.gvsig.vectorediting.lib.prov.chamfer.SegmentData.SEGMENT_POSITION_FIRST;
78
import static org.gvsig.vectorediting.lib.prov.chamfer.SegmentData.SEGMENT_POSITION_LAST;
79
import static org.gvsig.vectorediting.lib.prov.chamfer.SegmentData.SEGMENT_POSITION_MIDDLE;
80
import org.gvsig.vectorediting.lib.spi.AbstractEditingProvider;
81
import org.gvsig.vectorediting.lib.spi.DefaultDrawingStatus;
82
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameter;
83
import org.gvsig.vectorediting.lib.spi.DefaultEditingServiceParameterOptions;
84
import org.gvsig.vectorediting.lib.spi.EditingProvider;
85
import org.gvsig.vectorediting.lib.spi.EditingProviderFactory;
86
import org.gvsig.vectorediting.lib.spi.EditingProviderLocator;
87
import org.gvsig.vectorediting.lib.spi.EditingProviderManager;
88
import org.gvsig.vectorediting.lib.spi.EditingProviderServices;
89
import org.slf4j.Logger;
90
import org.slf4j.LoggerFactory;
91
92
/**
93
 * @author fdiaz
94
 *
95
 */
96 4284 fdiaz
public class ChamferByLengthAndAngleEditingProvider extends AbstractEditingProvider {
97 3194 fdiaz
98 3289 fdiaz
    private static final Logger LOGGER = LoggerFactory.getLogger(ChamferByLengthAndAngleEditingProvider.class);
99
100
    private static final int ERR_OK = 0;
101
    private static final int ERR_CHAMFER_TOO_LARGE = 1;
102
    private static final int ERR_SEGMENT_DATA_NOT_FILLED = 2;
103
    private static final int ERR_FIRST_SEGMENT_DATA_NULL = 3;
104
    private static final int ERR_SAME_SEGMENT = 4;
105
    private static final int ERR_CANT_CALCULATE_CHAMFER_POINT = 5;
106
    private static final int ERR_NON_ADJACENT_SEGMENTS = 6;
107
    private static final int ERR_DIFFERENT_GEOMETRY_TYPES = 7;
108
    private static final int ERR_CANT_CONNECT_SEGMENTS = 8;
109
    private static final int ERR_ONE_OF_THE_TWO_SEGMENTS_ISNT_EXTREME = 9;
110
    private static final int ERR_INVALID_VALUE = 10;
111
    private static final int ERR_INVALID_GEOMETRY_TYPE = 11;
112
    private static final int ERR_CANT_FIND_NEAREST_GEOMETRY = 12;
113
    private static final int ERR_CANT_CALCULATE_CHAMFER = 13;
114
115
    private static String[] stateMessages= {
116
        "_Valid",
117
        "_Chamfer_too_large",
118
        "_Cant_fill_segment_data",
119
        "_First_segment_data_is_null",
120
        "_Same_segment",
121
        "_Cant_calculate_chamfer_point",
122
        "_Non-adjacent_segments",
123
        "_Different_geometry_types",
124
        "_Cant_connect_segments",
125
        "_One_of_the_two_segments_isnt_extreme",
126
        "_Invalid_value",
127
        "_Invalid_geometry_type",
128
        "_Cant_find_nearest_geometry",
129
        "_Cant_calculate_chamfer"
130
131
    };
132 3194 fdiaz
133 3289 fdiaz
134 3194 fdiaz
    private static final int INSIDE_THE_SEGMENT = 0;
135
    private static final int BEYOND_THE_SEGMENT = 1;
136
    private static final int INVALID_ZONE = -1;
137
138 3289 fdiaz
    private static final String CHAMFER_LENGTH = "_Length";
139
//    private static final String CHAMFER_ANGLE = "_Angle";
140
//
141
//    private static final String SHORT_CHAMFER_LENGTH = "_Short_length";
142
//    private static final String SHORT_CHAMFER_ANGLE = "_Short_angle";
143 3194 fdiaz
144 3289 fdiaz
//    private static final String CHAMFER_METHOD = "_Method";
145 3194 fdiaz
146
    private static final String DELETE_SECOND_SELECTED_GEOMETRY_QUESTION = "_Delete_second_selected_geometry_question";
147
148
    private static final String DELETE_SECOND_SELECTED_GEOMETRY = "_Delete_second_selected_geometry";
149
150
    private static final String YES = "_yes";
151
    private static final String NO = "_no";
152
153
    private static final String SHORT_YES = "_short_yes";
154
    private static final String SHORT_NO = "_short_no";
155
    //Variable est?tica para guardarnos el deleteSecondFeatureDefaultValue
156
    private static Boolean deleteSecondFeatureDefaultValue;
157
158 3289 fdiaz
    private final EditingServiceParameter lengthParameter;
159 3194 fdiaz
160
    private final EditingServiceParameter firstSegmentParameter;
161
162
    private final EditingServiceParameter secondSegmentParameter;
163
164
    private final EditingServiceParameter angleParameter;
165
166
    private final EditingServiceParameter deleteSecondSelectedGeometryParameter;
167
168
    private final Map<EditingServiceParameter, Object> values;
169
170
    private final FeatureStore featureStore;
171
172
    private final MapContext mapContext;
173
174
    private SegmentData firstSegmentData;
175
    private SegmentData secondSegmentData;
176
177 3289 fdiaz
    private Point pointToChamfer;
178 3194 fdiaz
179
    //Variable est?tica para guardarnos la distancia por defecto
180
    private static Double savedDistance;
181
182
    private ISymbol previewSymbol;
183
184
    /**
185
     * Default constructor.
186
     *
187
     * @param providerServices available services for this provider
188
     * @param parameters of this provider
189
     */
190 3289 fdiaz
    public ChamferByLengthAndAngleEditingProvider(ProviderServices providerServices,
191 3194 fdiaz
            DynObject parameters) {
192
        super(providerServices);
193
        I18nManager i18nManager = ToolsLocator.getI18nManager();
194
195
        this.featureStore
196
                = (FeatureStore) parameters
197
                        .getDynValue(EditingProviderFactory.FEATURE_STORE_FIELD);
198
199
        this.mapContext
200
                = (MapContext) parameters
201
                        .getDynValue(EditingProviderFactory.MAPCONTEXT_FIELD);
202
203
        this.firstSegmentParameter
204
                = new DefaultEditingServiceParameter("_First_segment", "_First_segment", TYPE.POSITION);
205
206
        this.secondSegmentParameter
207
                = new DefaultEditingServiceParameter("_Second_segment", "_Second_segment", TYPE.POSITION);
208
209 3289 fdiaz
//        DefaultEditingServiceParameterOptions methodOptions = new DefaultEditingServiceParameterOptions()
210
//                .add(i18nManager.getTranslation(CHAMFER_LENGTH), CHAMFER_LENGTH, i18nManager.getTranslation(SHORT_CHAMFER_LENGTH))
211
//                .add(i18nManager.getTranslation(CHAMFER_ANGLE), CHAMFER_ANGLE, i18nManager.getTranslation(SHORT_CHAMFER_ANGLE));
212 3194 fdiaz
213 3289 fdiaz
//        String methodConsoleMsg
214
//                = ((EditingProviderServices) providerServices).makeConsoleMessage(
215
//                        i18nManager.getTranslation(CHAMFER_METHOD), methodOptions);
216 3194 fdiaz
217 3289 fdiaz
        this.lengthParameter = new DefaultEditingServiceParameter(
218
                "_Length",
219
                "_Length",
220 3194 fdiaz
                TYPE.VALUE,
221 3289 fdiaz
//                TYPE.POSITION,
222 3194 fdiaz
                TYPE.DISTANCE
223
        );
224
225
        this.angleParameter
226
                = new DefaultEditingServiceParameter("_Angle", "_Angle",
227
                        TYPE.POSITION,
228
                        TYPE.VALUE);
229
230
        DefaultEditingServiceParameterOptions deleteSecondSelectedGeometryParameterOptions = new DefaultEditingServiceParameterOptions()
231
                .add(YES, true, i18nManager.getTranslation(SHORT_YES))
232
                .add(NO, false, i18nManager.getTranslation(SHORT_NO));
233
234
        String consoleMsg
235
                = ((EditingProviderServices) providerServices).makeConsoleMessage(
236
                        DELETE_SECOND_SELECTED_GEOMETRY_QUESTION, deleteSecondSelectedGeometryParameterOptions);
237
238
        this.deleteSecondSelectedGeometryParameter
239
                = new DefaultEditingServiceParameter(
240
                        DELETE_SECOND_SELECTED_GEOMETRY,
241
                        consoleMsg,
242
                        deleteSecondSelectedGeometryParameterOptions,
243
                        null, //deleteSecondFeatureDefaultValue,
244
                        false,
245
                        TYPE.OPTION).setDataType(DataTypes.BOOLEAN);
246
247
        this.values = new HashMap<>();
248
        this.firstSegmentData = null;
249
        this.secondSegmentData = null;
250
    }
251
252
    @Override
253
    public String getName() {
254 3289 fdiaz
        return ChamferByLengthAndAngleEditingProviderFactory.PROVIDER_NAME;
255 3194 fdiaz
    }
256
257
    @Override
258
    public EditingServiceParameter next() {
259 3289 fdiaz
        if (values.get(lengthParameter) == null) {
260
            return this.lengthParameter;
261
        } else if (values.get(firstSegmentParameter) == null) {
262 3194 fdiaz
            return this.firstSegmentParameter;
263
        } else if (values.get(secondSegmentParameter) == null) {
264
            return this.secondSegmentParameter;
265
        } else if (values.get(angleParameter) == null) {
266
            return this.angleParameter;
267
        } else if (values.get(deleteSecondSelectedGeometryParameter) == null &&
268
                !Objects.equals(firstSegmentData.getFeature().getReference(), secondSegmentData.getFeature().getReference())) {
269
            return this.deleteSecondSelectedGeometryParameter;
270
        }
271
        return null;
272
    }
273
274
    @Override
275
    public DrawingStatus getDrawingStatus(Point mousePosition)
276
            throws DrawServiceException {
277
        DefaultDrawingStatus geometries = new DefaultDrawingStatus();
278
279
        GeometryManager geometryManager = GeometryLocator.getGeometryManager();
280
        EditingProviderManager editingProviderManager
281
                = EditingProviderLocator.getProviderManager();
282
        ISymbol lineSymbolEditing = editingProviderManager.getSymbol("line-symbol-editing");
283
        ISymbol auxiliaryLineSymbolEditing = editingProviderManager.getSymbol("auxiliary-line-symbol-editing");
284
        ISymbol auxiliaryPointSymbolEditing = editingProviderManager.getSymbol("auxiliary-point-symbol-editing");
285
        ISymbol polygonSymbolEditing = editingProviderManager.getSymbol("polygon-symbol-editing");
286
        ISymbol ruleAxisSymbol = editingProviderManager.getSymbol("rule-axis-symbol");
287
288
        auxiliaryPointSymbolEditing.setColor(Color.RED);
289
        ISimpleTextSymbol textSymbol = getTextSymbol();
290
291
        EditingProviderServices editingProviderServices
292
                = (EditingProviderServices) getProviderServices();
293
294
        ISymbol previewSymbol = null;
295
        try {
296
            int subtype = editingProviderServices.getSubType(featureStore);
297
            Double distance;
298
            if (values != null) {
299 3289 fdiaz
                if (values.get(this.lengthParameter) == null) {
300
                    return geometries;
301
                } else if (this.firstSegmentData == null) {
302 3194 fdiaz
                    Feature firstFeature = getFeatureNearestPoint(mousePosition);
303
                    if (firstFeature == null) {
304
                        return geometries;
305
                    }
306
                    Geometry firstGeometry = firstFeature.getDefaultGeometry();
307
                    if (firstGeometry == null || !validateGeometryType(firstGeometry)) {
308
                        return geometries;
309
                    }
310
311
                    SegmentData segmentData = new SegmentData(firstFeature, mousePosition);
312
                    geometries.addStatus(segmentData.getProjectedPoint(), auxiliaryPointSymbolEditing, "");
313
                    geometries.addStatus(GeometryUtils.createLine(mousePosition, segmentData.getProjectedPoint(), subtype), auxiliaryLineSymbolEditing, "");
314
                    geometries.addStatus(segmentData.getLine(), auxiliaryLineSymbolEditing, "");
315
                    return geometries;
316
317
                } else if (this.secondSegmentData == null) {
318
                    geometries.addStatus(firstSegmentData.getLine(), auxiliaryLineSymbolEditing, "");
319
                    geometries.addStatus(firstSegmentData.getProjectedPoint(), auxiliaryPointSymbolEditing, "");
320
321
                    Feature secondFeature = getFeatureNearestPoint(mousePosition);
322
                    if (secondFeature == null) {
323
                        return geometries;
324
                    }
325
                    Geometry secondGeometry = secondFeature.getDefaultGeometry();
326
                    if (secondGeometry == null || !validateGeometryType(secondGeometry)) {
327
                        return geometries;
328
                    }
329
                    SegmentData segmentData = new SegmentData(secondFeature, mousePosition);
330 3289 fdiaz
                    Pair<Point, Point> oppositePoints = calculateOpositeToChamferVertices(firstSegmentData, segmentData);
331
                    if (validateAsSecondSegmentData(segmentData, oppositePoints.getRight()) == ERR_OK) {
332 3194 fdiaz
                        geometries.addStatus(segmentData.getProjectedPoint(), auxiliaryPointSymbolEditing, "");
333
                        geometries.addStatus(GeometryUtils.createLine(mousePosition, segmentData.getProjectedPoint(), subtype), auxiliaryLineSymbolEditing, "");
334
                        geometries.addStatus(segmentData.getLine(), auxiliaryLineSymbolEditing, "");
335
336 3289 fdiaz
                        Point tmpPointToChamfer = calculatePointToChamfer(firstSegmentData, segmentData);
337
                        geometries.addStatus(tmpPointToChamfer, auxiliaryPointSymbolEditing, "");
338 3194 fdiaz
339
                    } else {
340
                        return geometries;
341
                    }
342 3289 fdiaz
                } else if (values.get(angleParameter) == null) {
343
                    Point tmpPointToFillet = calculatePointToChamfer(firstSegmentData, secondSegmentData);
344
                    Pair<Point, Point> oppositePoints = calculateOpositeToChamferVertices(firstSegmentData, secondSegmentData);
345 3194 fdiaz
                    geometries.addStatus(
346
                            GeometryUtils.createLine(oppositePoints.getLeft(), tmpPointToFillet, subtype),
347
                            auxiliaryLineSymbolEditing,
348
                            ""
349
                    );
350
                    geometries.addStatus(
351
                            GeometryUtils.createLine(oppositePoints.getRight(), tmpPointToFillet, subtype),
352
                            auxiliaryLineSymbolEditing,
353
                            ""
354
                    );
355 3289 fdiaz
356
                    distance = (Double) getValue(lengthParameter);
357
                    double angle = GeometryUtils.calculateAngle(
358
                            pointToChamfer,
359
                            mousePosition);
360 3194 fdiaz
361 3289 fdiaz
                    geometries.addStatus(tmpPointToFillet, auxiliaryPointSymbolEditing, "");
362 3194 fdiaz
363 3289 fdiaz
                    //Draw scaffolding
364
                    ScaffoldingToChamfer scaffolding = calculateScaffolding(firstSegmentData, secondSegmentData, tmpPointToFillet, distance, angle, subtype);
365
                    if(scaffolding == null){
366
                        return geometries;
367
                    }
368 3194 fdiaz
369
                    geometries.addStatus(
370 3289 fdiaz
                            GeometryUtils.createLine(
371
                                    tmpPointToFillet,
372
                                    scaffolding.getP1(),
373
                                    subtype),
374
                            auxiliaryLineSymbolEditing,
375 3194 fdiaz
                            ""
376
                    );
377 3289 fdiaz
                    if(scaffolding.isReversed()){
378
                        geometries.addStatus(
379
                                GeometryUtils.createLine(
380
                                        scaffolding.getP1(),
381
                                        GeometryUtils.createPoint(scaffolding.getChamferRight().getX(), scaffolding.getChamferRight().getY()),
382
                                        subtype),
383
                                auxiliaryLineSymbolEditing,
384
                                ""
385
                        );
386
                    } else {
387
                        geometries.addStatus(
388
                                GeometryUtils.createLine(
389
                                        scaffolding.getP1(),
390
                                        GeometryUtils.createPoint(scaffolding.getChamferRight().getX(), scaffolding.getChamferRight().getY()),
391
                                        subtype),
392
                                auxiliaryLineSymbolEditing,
393
                                ""
394
                        );
395
                    }
396
397 3194 fdiaz
                    geometries.addStatus(
398 3289 fdiaz
                            GeometryUtils.createLine(
399
                                    GeometryUtils.createPoint(scaffolding.getChamferRight().getX(), scaffolding.getChamferRight().getY()),
400
                                    GeometryUtils.createPoint(scaffolding.getChamferLeft().getX(), scaffolding.getChamferLeft().getY()),
401
                                    subtype),
402 3194 fdiaz
                            auxiliaryLineSymbolEditing,
403
                            ""
404
                    );
405
406
                    //Draw angle
407
                    Line ruleAxisBaseLine;
408
                    ruleAxisBaseLine = geometryManager.createLine(subtype);
409
                    ruleAxisBaseLine.addVertex(tmpPointToFillet);
410
                    Point p2 = geometryManager.createPoint(
411
                            tmpPointToFillet.getX() + tmpPointToFillet.distance(mousePosition),
412
                            tmpPointToFillet.getY(), subtype);
413
                    ruleAxisBaseLine.addVertex(p2);
414
                    geometries.addStatus(ruleAxisBaseLine, ruleAxisSymbol, "");
415
416
                    Line angleLine = geometryManager.createLine(subtype);
417
                    angleLine.addVertex(tmpPointToFillet);
418
                    angleLine.addVertex(mousePosition);
419
                    geometries.addStatus(angleLine, ruleAxisSymbol, "");
420
421
                    Double ext = (2 * Math.PI) - angle;
422
                    Arc arc = GeometryUtils.createArc(
423
                            tmpPointToFillet,
424
                            tmpPointToFillet.distance(mousePosition) / 2,
425
                            0,
426
                            angle,
427
                            Geometry.SUBTYPES.GEOM2D);
428
                    geometries.addStatus(arc, auxiliaryLineSymbolEditing, "");
429
                    double textDistance = 3 * tmpPointToFillet.distance(mousePosition) / 4;
430
                    Point pointText = geometryManager.createPoint(tmpPointToFillet.getX() + textDistance * Math.cos(angle / 2), tmpPointToFillet.getY() + textDistance * Math.sin(angle / 2), subtype);
431
                    geometries.addStatus(pointText, textSymbol, GeometryUtils.formatAngle("%5.3D\u00B0", Math.toDegrees(angle)));
432
433
434
                    //Draw result
435 3289 fdiaz
                    drawResult(geometries, firstSegmentData, secondSegmentData, distance, angle, subtype);
436 3194 fdiaz
                    return geometries;
437
                } else {
438 3289 fdiaz
                    drawResult(
439
                            geometries,
440 3194 fdiaz
                            firstSegmentData,
441 3289 fdiaz
                            secondSegmentData,
442
                            (Double) getValue(lengthParameter),
443 3194 fdiaz
                            Math.toRadians((Double) getValue(angleParameter)),
444
                            subtype
445
                    );
446
                    return geometries;
447
                }
448
            }
449
        } catch (Exception e) {
450
            throw new DrawServiceException(e);
451
        }
452
        return geometries;
453
    }
454
455 3289 fdiaz
    private void drawResult(DefaultDrawingStatus geometries, SegmentData firstSegmentData, SegmentData secondSegmentData, Double length, Double angle, int subtype) throws CreateGeometryException, GeometryOperationNotSupportedException, IllegalStateException, GeometryException, GeometryOperationException {
456 3194 fdiaz
        if(previewSymbol == null){
457
            return;
458
        }
459
        //Draw result
460 3289 fdiaz
        Line chamfer = calculateChamfer(firstSegmentData, secondSegmentData, length, angle, subtype);
461
        if (chamfer == null) {
462 3194 fdiaz
            return;
463
        }
464
        if (Objects.equals(firstSegmentData.getPrimitive(), secondSegmentData.getPrimitive())) {
465 3289 fdiaz
            geometries.addStatus(chamferPrimitive(firstSegmentData.getPrimitive(), chamfer), previewSymbol, null);
466 3194 fdiaz
        } else {
467 3289 fdiaz
            geometries.addStatus(chamferPrimitives(firstSegmentData.getPrimitive(), secondSegmentData.getPrimitive(), chamfer), previewSymbol, null);
468 3194 fdiaz
        }
469
    }
470
471
    private ISimpleTextSymbol getTextSymbol() {
472
        SymbologyManager symbologyManager = SymbologyLocator.getSymbologyManager();
473
        ISimpleTextSymbol textSymbol = symbologyManager.createSimpleTextSymbol();
474
        textSymbol.setFontSize(10);
475
        return textSymbol;
476
    }
477
478
    @Override
479
    public List<EditingServiceParameter> getParameters() {
480
        List<EditingServiceParameter> parameters
481
                = new ArrayList<>();
482 3289 fdiaz
        parameters.add(lengthParameter);
483 3194 fdiaz
        parameters.add(firstSegmentParameter);
484
        parameters.add(secondSegmentParameter);
485
        parameters.add(angleParameter);
486
        parameters.add(deleteSecondSelectedGeometryParameter);
487
        return parameters;
488
    }
489
490
    @Override
491
    public boolean isEnabled(EditingServiceParameter parameter) {
492
        return true;
493
    }
494
495
    @Override
496
    public void setValue(EditingServiceParameter parameter, Object value) throws InvalidEntryException {
497
        validateAndInsertValue(parameter, value);
498
    }
499
500
    @Override
501
    public void setValue(Object value) throws InvalidEntryException {
502
        EditingServiceParameter param = next();
503
        validateAndInsertValue(param, value);
504
    }
505
506
    private void validateAndInsertValue(EditingServiceParameter param,
507
            Object value) throws InvalidEntryException {
508
509
        try {
510
            EditingProviderServices editingProviderServices
511
                    = (EditingProviderServices) getProviderServices();
512
            int subtype = editingProviderServices.getSubType(featureStore);
513 3289 fdiaz
514
            I18nManager i18n = ToolsLocator.getI18nManager();
515 3194 fdiaz
516
517 3289 fdiaz
            if (param == lengthParameter) {
518
                Double distance = null;
519
                if (value instanceof Double) {
520
                    distance = (Double) value;
521
                } else if (value == null) {
522
                    distance = (Double) lengthParameter.getDefaultValue();
523
                    if(distance == null){
524
                        throw new InvalidEntryException(getName(), ERR_INVALID_VALUE, i18n.getTranslation(stateMessages[ERR_INVALID_VALUE]));
525
                    }
526
                }
527
                values.put(param, distance);
528
                savedDistance = distance;
529
            } else if (param == firstSegmentParameter) {
530 3194 fdiaz
                if (value instanceof Point) {
531
                    Point point = (Point) value;
532
533
                    Feature firstFeature = getFeatureNearestPoint(point);
534
                    if (firstFeature == null) {
535
                        throw new InvalidEntryException(new IllegalArgumentException("Can't find nearest feature."));
536
                    }
537
                    Geometry firstGeometry = firstFeature.getDefaultGeometry();
538
                    if (!validateGeometryType(firstGeometry)) {
539 3289 fdiaz
                        throw new InvalidEntryException(getName(), ERR_INVALID_GEOMETRY_TYPE, i18n.getTranslation(stateMessages[ERR_INVALID_GEOMETRY_TYPE]));
540 3194 fdiaz
                    }
541
                    this.firstSegmentData = new SegmentData(firstFeature, point);
542
                    if (!this.firstSegmentData.isFilled()) {
543
                        this.firstSegmentData = null;
544 3289 fdiaz
                        throw new InvalidEntryException(getName(), ERR_CANT_FIND_NEAREST_GEOMETRY, i18n.getTranslation(stateMessages[ERR_CANT_FIND_NEAREST_GEOMETRY]));
545 3194 fdiaz
                    }
546
                    if (firstSegmentData == null) {
547 3289 fdiaz
                        throw new InvalidEntryException(getName(), ERR_CANT_FIND_NEAREST_GEOMETRY, i18n.getTranslation(stateMessages[ERR_CANT_FIND_NEAREST_GEOMETRY]));
548 3194 fdiaz
                    }
549
                    values.put(param, value);
550
                    previewSymbol = getPreviewSymbol(this.firstSegmentData.getFeature());
551
                }
552
            } else if (param == secondSegmentParameter) {
553
                if (value instanceof Point) {
554
                    Point point = (Point) value;
555
                    Feature secondFeature = getFeatureNearestPoint(point);
556
                    if (secondFeature == null) {
557 3289 fdiaz
                        throw new InvalidEntryException(getName(), ERR_CANT_FIND_NEAREST_GEOMETRY, i18n.getTranslation(stateMessages[ERR_CANT_FIND_NEAREST_GEOMETRY]));
558 3194 fdiaz
                    }
559
                    SegmentData segmentData = new SegmentData(secondFeature, point);
560 3289 fdiaz
                    Pair<Point, Point> oppositeVertices = calculateOpositeToChamferVertices(this.firstSegmentData, segmentData);
561
                    int errno = validateAsSecondSegmentData(segmentData, oppositeVertices.getRight());
562
                    if (errno != ERR_OK) {
563 3194 fdiaz
                        this.secondSegmentData = null;
564 3289 fdiaz
                        this.pointToChamfer = null;
565
                        throw new InvalidEntryException(getName(), errno, i18n.getTranslation(stateMessages[errno]));
566 3194 fdiaz
                    } else {
567
                        try {
568
                            this.secondSegmentData = segmentData;
569 3289 fdiaz
                            this.pointToChamfer = calculatePointToChamfer(this.firstSegmentData, this.secondSegmentData);
570
                            angleParameter.setDefaultValue(calculateDefaultAngle(this.pointToChamfer, oppositeVertices));
571 3194 fdiaz
                            values.put(param, value);
572
                        } catch (GeometryOperationNotSupportedException | GeometryOperationException ex) {
573 3289 fdiaz
                            throw new InvalidEntryException(getName(), ERR_CANT_CALCULATE_CHAMFER_POINT, i18n.getTranslation(stateMessages[ERR_CANT_FIND_NEAREST_GEOMETRY]));
574 3194 fdiaz
                        }
575
                    }
576
                }
577
578
            } else if (param == angleParameter) {
579
580
                Double angle = null;
581
                if (value instanceof Double) {
582
                    angle = Math.toRadians((Double)value);
583
                } else if (value instanceof Point) {
584
                    Point point = (Point) value;
585
                    angle = GeometryUtils.calculateAngle(
586 3289 fdiaz
                            pointToChamfer,
587 3194 fdiaz
                            point);
588
                } else if (value == null) {
589
                    angle = Math.toRadians((Double) param.getDefaultValue());
590
                } else {
591 3289 fdiaz
                    throw new InvalidEntryException(getName(), ERR_INVALID_VALUE, i18n.getTranslation(stateMessages[ERR_INVALID_VALUE]));
592 3194 fdiaz
                }
593 3289 fdiaz
                Double distance = (Double) getValue(lengthParameter);
594
                Line chamfer = calculateChamfer(firstSegmentData, secondSegmentData, distance, angle, subtype);
595
                if(chamfer == null){
596
                    throw new InvalidEntryException(getName(), ERR_CANT_CALCULATE_CHAMFER, i18n.getTranslation(stateMessages[ERR_CANT_FIND_NEAREST_GEOMETRY]));
597 3194 fdiaz
                } else {
598
                    values.put(param, Math.toDegrees(angle));
599
                }
600
            } else if (param == deleteSecondSelectedGeometryParameter) {
601
                Boolean v = (Boolean) param.getOptions2().getValue(value, param.getDefaultValue());
602
                values.put(param, v);
603
                deleteSecondFeatureDefaultValue = v;
604
            }
605 3289 fdiaz
        } catch (InvalidEntryException ex) {
606
            throw ex;
607 3194 fdiaz
        } catch (Exception ex) {
608
            throw new InvalidEntryException(ex);
609
        }
610
611
    }
612
613
    private boolean validateGeometryType(Geometry geometry) throws IllegalArgumentException {
614
        List<Integer> validGeometryTypes = new ArrayList(Arrays.asList(
615
                Geometry.TYPES.LINE,
616
                Geometry.TYPES.POLYGON,
617
                Geometry.TYPES.MULTILINE,
618
                Geometry.TYPES.MULTIPOLYGON
619
        ));
620
621
        return validGeometryTypes.contains(geometry.getType());
622
    }
623
624
    @Override
625
    public Geometry finish() throws FinishServiceException {
626
        return null;
627
    }
628
629
    @Override
630
    public void finishAndStore() throws FinishServiceException {
631 3289 fdiaz
        Line chamfer; // = null;
632
        Double distance = (Double) getValue(lengthParameter);
633 3194 fdiaz
        Double angle = (Double) getValue(angleParameter);
634
        try {
635
636
            EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
637
            int subType = editingProviderServices.getSubType(featureStore);
638
639 3289 fdiaz
            chamfer = calculateChamfer(
640
                    this.firstSegmentData,
641
                    this.secondSegmentData,
642
                    (Double) getValue(lengthParameter),
643
                    Math.toRadians((Double) getValue(angleParameter)),
644
                    subType
645
            );
646
            if(chamfer == null){
647
                throw new FinishServiceException("Can't calculate chamfer.", null);
648 3194 fdiaz
            }
649
650
            Feature firstFeature = firstSegmentData.getFeature();
651
            Feature secondFeature = secondSegmentData.getFeature();
652
653
            Boolean doDeleteSecondSelectedGeometry = false;
654
            if (!Objects.equals(firstFeature.getReference(), secondFeature.getReference())) {
655
                doDeleteSecondSelectedGeometry = (Boolean) values.get(this.deleteSecondSelectedGeometryParameter);
656
            }
657
658
            EditableFeature editableFeature = firstFeature.getEditable();
659
            Geometry modifiedGeometry; //= null; //editableFeature.getDefaultGeometry().cloneGeometry();
660
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
661
            Geometry firstGeometry = firstSegmentData.getGeometry();
662
            Primitive firstPrimitive = firstSegmentData.getPrimitive();
663
            Primitive secondPrimitive = secondSegmentData.getPrimitive();
664
            if (Objects.equals(firstFeature.getReference(), secondFeature.getReference())) {
665
                if (firstGeometry instanceof MultiPrimitive) {
666
                    modifiedGeometry = geomManager.create(firstGeometry.getGeometryType());
667
                    MultiPrimitive firstMultiPrimitive = (MultiPrimitive) firstGeometry;
668
                    if (Objects.equals(firstPrimitive, secondPrimitive)) {
669
                        for (Geometry geometry : firstMultiPrimitive) {
670
                            Primitive primitive = (Primitive) geometry;
671
                            if (Objects.equals(firstPrimitive, primitive)) {
672 3289 fdiaz
                                Primitive modifiedPrimitive = chamferPrimitive(primitive, chamfer);
673 3194 fdiaz
                                ((MultiPrimitive) modifiedGeometry).addPrimitive(modifiedPrimitive);
674
                            } else if (Objects.equals(secondPrimitive, primitive)) {
675
                                //Don't add second primitive
676
                            } else {
677
                                ((MultiPrimitive) modifiedGeometry).addPrimitive(primitive);
678
                            }
679
                        }
680
                    } else {
681 3289 fdiaz
                        Primitive modifiedPrimitive = chamferPrimitives(firstPrimitive, secondPrimitive, chamfer);
682 3194 fdiaz
                        for (Geometry geometry : firstMultiPrimitive) {
683
                            Primitive primitive = (Primitive) geometry;
684
                            if (Objects.equals(firstPrimitive, primitive)) {
685
                                ((MultiPrimitive) modifiedGeometry).addPrimitive(modifiedPrimitive);
686
                            } else if (Objects.equals(secondPrimitive, primitive)) {
687
                                //Don't add second primitive
688
                            } else {
689
                                ((MultiPrimitive) modifiedGeometry).addPrimitive(primitive);
690
                            }
691
                        }
692
                    }
693
                } else {
694 3289 fdiaz
                    modifiedGeometry = chamferPrimitive((Primitive) editableFeature.getDefaultGeometry(), chamfer);
695 3194 fdiaz
                }
696
697
            } else { // Different features
698
699
                doDeleteSecondSelectedGeometry = (Boolean) values.get(this.deleteSecondSelectedGeometryParameter);
700 3289 fdiaz
                Primitive modifiedPrimitive = chamferPrimitives(firstPrimitive, secondPrimitive, chamfer);
701 3194 fdiaz
702
                modifiedGeometry = geomManager.create(firstGeometry.getGeometryType());
703
                if (firstGeometry instanceof MultiPrimitive) {
704
                    MultiPrimitive firstMultiPrimitive = (MultiPrimitive) firstGeometry;
705
                    for (Geometry geometry : firstMultiPrimitive) {
706
                        Primitive primitive = (Primitive) geometry;
707
                        if (Objects.equals(firstPrimitive, primitive)) {
708
                            ((MultiPrimitive) modifiedGeometry).addPrimitive(modifiedPrimitive);
709
                        } else {
710
                            ((MultiPrimitive) modifiedGeometry).addPrimitive(primitive);
711
                        }
712
                    }
713
                } else {
714
                    modifiedGeometry = modifiedPrimitive;
715
                }
716
                if (doDeleteSecondSelectedGeometry) {
717
                    secondFeature.getStore().delete(secondFeature);
718
                }
719
            }
720
            editableFeature.setDefaultGeometry(modifiedGeometry);
721
            ((EditingProviderServices) getProviderServices())
722
                    .updateFeatureInFeatureStore(
723
                            editableFeature, featureStore);
724
725
726
        } catch (Exception e) {
727
            throw new FinishServiceException(e);
728
        }
729
    }
730
731 3289 fdiaz
    private Primitive chamferPrimitive(Primitive primitive, Line chamfer) throws IllegalStateException, GeometryException, GeometryOperationException, GeometryOperationNotSupportedException {
732 3194 fdiaz
        Primitive modifiedPrimitive = (Primitive) (primitive.cloneGeometry());
733
        if (primitive instanceof Line || primitive instanceof Polygon) {
734
            modifiedPrimitive = (Primitive) (primitive.cloneGeometry());
735
        } else if (primitive instanceof Curve) {
736
            modifiedPrimitive = (Line) primitive.toLines().getPrimitiveAt(0);
737
        } else if (primitive instanceof Surface) {
738
            modifiedPrimitive = (Line) primitive.toPolygons().getPrimitiveAt(0);
739
        }
740
        if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() - 1)) {
741
            if (modifiedPrimitive instanceof Line) {
742
                ((Line) modifiedPrimitive).removeVertex(firstSegmentData.getIdxVertex() + 1);
743
                int i = 1;
744 3289 fdiaz
                for (Point point : chamfer) {
745 3194 fdiaz
                    ((Line) modifiedPrimitive).insertVertex(firstSegmentData.getIdxVertex() + i++, point);
746
                }
747
            } else if (modifiedPrimitive instanceof Polygon) {
748
                ((Polygon) modifiedPrimitive).removeVertex(firstSegmentData.getIdxVertex() + 1);
749
                int i = 1;
750 3289 fdiaz
                for (Point point : chamfer) {
751 3194 fdiaz
                    ((Polygon) modifiedPrimitive).insertVertex(firstSegmentData.getIdxVertex() + i++, point);
752
                }
753
            }
754
        } else if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() + 1)) {
755
            if (modifiedPrimitive instanceof Line) {
756
                ((Line) modifiedPrimitive).removeVertex(secondSegmentData.getIdxVertex() + 1);
757 3289 fdiaz
                Line flipedChamfer = (Line)chamfer.cloneGeometry();
758
                flipedChamfer.flip();
759 3194 fdiaz
                int i = 1;
760 3289 fdiaz
                for (Point point : flipedChamfer) {
761 3194 fdiaz
                    ((Line) modifiedPrimitive).insertVertex(secondSegmentData.getIdxVertex() + i++, point);
762
                }
763
            } else if (modifiedPrimitive instanceof Polygon) {
764
                ((Polygon) modifiedPrimitive).removeVertex(secondSegmentData.getIdxVertex() + 1);
765 3289 fdiaz
                Line flipedChamfer = (Line)chamfer.cloneGeometry();
766
                flipedChamfer.flip();
767 3194 fdiaz
                int i = 1;
768 3289 fdiaz
                for (Point point : flipedChamfer) {
769 3194 fdiaz
                    ((Polygon) modifiedPrimitive).insertVertex(secondSegmentData.getIdxVertex() + i++, point);
770
                }
771
            }
772
        } else if (Objects.equals(this.firstSegmentData.getPosition(), SEGMENT_POSITION_LAST) && Objects.equals(this.secondSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
773
            if (modifiedPrimitive instanceof Line) {
774
                ((Line) modifiedPrimitive).removeVertex(0);
775
                ((Line) modifiedPrimitive).removeVertex(((Line) modifiedPrimitive).getNumVertices() - 1);
776 3289 fdiaz
                for (Point point : chamfer) {
777 3194 fdiaz
                    ((Line) modifiedPrimitive).addVertex(point); //.insertVertex(secondSegmentData.getIdxVertex() + i++, point);
778
                }
779
780
            } else if (modifiedPrimitive instanceof Polygon) {
781
                ((Polygon) modifiedPrimitive).removeVertex(0);
782
                ((Polygon) modifiedPrimitive).removeVertex(((Polygon) modifiedPrimitive).getNumVertices() - 1);
783
784 3289 fdiaz
                ((Polygon) modifiedPrimitive).insertVertex(0, chamfer.getVertex(chamfer.getNumVertices()-1));
785
                for (Point point : chamfer) {
786 3194 fdiaz
                    ((Polygon) modifiedPrimitive).addVertex(point); //.insertVertex(secondSegmentData.getIdxVertex() + i++, point);
787
                }
788
789
            }
790
        } else if (Objects.equals(this.firstSegmentData.getPosition(), SEGMENT_POSITION_FIRST) && Objects.equals(this.secondSegmentData.getPosition(), SEGMENT_POSITION_LAST)) {
791 3289 fdiaz
            Line flipedChamfer = (Line)chamfer.cloneGeometry();
792
            flipedChamfer.flip();
793 3194 fdiaz
            if (modifiedPrimitive instanceof Line) {
794
                ((Line) modifiedPrimitive).removeVertex(0);
795
                ((Line) modifiedPrimitive).removeVertex(((Line) modifiedPrimitive).getNumVertices() - 1);
796
797
                int i = 1;
798 3289 fdiaz
                for (Point point : flipedChamfer) {
799 3194 fdiaz
                    ((Line) modifiedPrimitive).addVertex(point); //.insertVertex(firstSegmentData.getIdxVertex() + i++, point);
800
                }
801
            } else if (modifiedPrimitive instanceof Polygon) {
802
                ((Polygon) modifiedPrimitive).removeVertex(0);
803
                ((Polygon) modifiedPrimitive).removeVertex(((Polygon) modifiedPrimitive).getNumVertices() - 1);
804
805 3289 fdiaz
                ((Polygon) modifiedPrimitive).insertVertex(0, flipedChamfer.getVertex(flipedChamfer.getNumVertices()-1));
806
                for (Point point : flipedChamfer) {
807 3194 fdiaz
                    ((Polygon) modifiedPrimitive).addVertex(point);//.insertVertex(firstSegmentData.getIdxVertex() + i++, point);
808
                }
809
            }
810
        } else {
811
            throw new IllegalStateException("Invalid segments");
812
        }
813
        return modifiedPrimitive;
814
    }
815
816 3289 fdiaz
    private Primitive chamferPrimitives(Primitive firstPrimitive, Primitive secondPrimitive, Line chamfer) throws IllegalStateException, GeometryException, GeometryOperationNotSupportedException, GeometryOperationException {
817 3194 fdiaz
        //Cannot be polygons
818
        if(firstPrimitive == null){
819
            throw new IllegalArgumentException("firstPrimitive is null");
820
        }
821
        Line firstLine;
822
        if (firstPrimitive instanceof Line) {
823
            firstLine = (Line) firstPrimitive.cloneGeometry();
824
        } else {
825
            MultiLine lines = firstPrimitive.toLines();
826
            if(lines==null){
827
                throw new IllegalArgumentException("Can't find first primitive.");
828
            }
829
            firstLine = (Line) lines.getPrimitiveAt(0);
830
        }
831
        if(secondPrimitive == null){
832
            throw new IllegalArgumentException("secondPrimitive is null");
833
        }
834
        Line secondLine;
835
        if (secondPrimitive instanceof Line) {
836
            secondLine = (Line) secondPrimitive;
837
        } else {
838
            MultiLine lines = secondPrimitive.toLines();
839
            if(lines==null){
840
                throw new IllegalArgumentException("Can't find second primitive.");
841
            }
842
            secondLine = (Line) lines.getPrimitiveAt(0);
843
        }
844
845
        Line modifiedPrimitive = firstLine;
846
        if (Objects.equals(this.firstSegmentData.getPosition(), SEGMENT_POSITION_LAST)) {
847
            modifiedPrimitive.removeVertex(modifiedPrimitive.getNumVertices() - 1);
848 3289 fdiaz
            for (Point point : chamfer) {
849 3194 fdiaz
                modifiedPrimitive.addVertex(point);
850
            }
851
852
            if (Objects.equals(this.secondSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
853
                for (int i = 0; i < secondLine.getNumVertices(); i++) {
854
                    if (i != 0) {
855
                        ((Line) modifiedPrimitive).addVertex(secondLine.getVertex(i));
856
                    }
857
                }
858
            } else { //LAST
859
                for (int i = secondLine.getNumVertices() - 1; i >= 0; i--) {
860
                    if (i != secondLine.getNumVertices() - 1) {
861
                        ((Line) modifiedPrimitive).addVertex(secondLine.getVertex(i));
862
                    }
863
                }
864
            }
865
        } else {
866
            modifiedPrimitive.removeVertex(0);
867 3289 fdiaz
            for (Point point : chamfer) {
868 3194 fdiaz
                modifiedPrimitive.insertVertex(0, point);
869
            }
870
871
            if (Objects.equals(this.secondSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
872
                for (int i = 0; i < secondLine.getNumVertices(); i++) {
873
                    if (i != 0) {
874
                        ((Line) modifiedPrimitive).insertVertex(0, secondLine.getVertex(i));
875
                    }
876
                }
877
            } else { //LAST
878
                for (int i = secondLine.getNumVertices() - 1; i >= 0; i--) {
879
                    if (i != secondLine.getNumVertices() - 1) {
880
                        ((Line) modifiedPrimitive).insertVertex(0, secondLine.getVertex(i));
881
                    }
882
                }
883
            }
884
        }
885
        return modifiedPrimitive;
886
    }
887
888 3289 fdiaz
    private Pair<Point, Point> calculateOpositeToChamferVertices(SegmentData firstSegmentData, SegmentData secondSegmentData) throws GeometryOperationNotSupportedException, GeometryOperationException {
889 3194 fdiaz
        Point firstVertex;
890
        Point secondVertex;
891
        if (Objects.equals(firstSegmentData.getPrimitive(), secondSegmentData.getPrimitive())) {
892
            if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() - 1)) {
893
                firstVertex = firstSegmentData.getLine().getVertex(0);
894
                secondVertex = secondSegmentData.getLine().getVertex(1);
895
            } else if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() + 1)) {
896
                firstVertex = firstSegmentData.getLine().getVertex(1);
897
                secondVertex = secondSegmentData.getLine().getVertex(0);
898
            } else {
899
                if (Objects.equals(firstSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
900
                    firstVertex = firstSegmentData.getLine().getVertex(1);
901 3289 fdiaz
                } else { //SEGMENT_POSITION_LAST
902 3194 fdiaz
                    firstVertex = firstSegmentData.getLine().getVertex(0);
903
                }
904
905
                if (Objects.equals(secondSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
906
                    secondVertex = secondSegmentData.getLine().getVertex(1);
907 3289 fdiaz
                } else { //SEGMENT_POSITION_LAST
908 3194 fdiaz
                    secondVertex = secondSegmentData.getLine().getVertex(0);
909
                }
910
            }
911
        } else {
912
            if (Objects.equals(firstSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
913
                firstVertex = firstSegmentData.getLine().getVertex(1);
914
            } else {
915
                firstVertex = firstSegmentData.getLine().getVertex(0);
916
            }
917
918
            if (Objects.equals(secondSegmentData.getPosition(), SEGMENT_POSITION_FIRST)) {
919
                secondVertex = secondSegmentData.getLine().getVertex(1);
920
            } else {
921
                secondVertex = secondSegmentData.getLine().getVertex(0);
922
            }
923
        }
924
        return new ImmutablePair<>(firstVertex, secondVertex);
925
    }
926
927
    @Override
928
    public void start() throws StartServiceException {
929
        this.values.clear();
930
        this.firstSegmentData = null;
931
        this.secondSegmentData = null;
932 3289 fdiaz
        this.pointToChamfer = null;
933 3194 fdiaz
934
        if (savedDistance != null) {
935 3289 fdiaz
            this.lengthParameter.setDefaultValue(savedDistance);
936 3194 fdiaz
        }
937
    }
938
939
    @Override
940
    public void restart() throws StartServiceException, InvalidEntryException, StopServiceException {
941
        this.values.clear();
942
        this.firstSegmentData = null;
943
        this.secondSegmentData = null;
944 3289 fdiaz
        this.pointToChamfer = null;
945 3194 fdiaz
946
        if (savedDistance != null) {
947 3289 fdiaz
            this.lengthParameter.setDefaultValue(savedDistance);
948 3194 fdiaz
        }
949
950
    }
951
952
    @Override
953
    public void initDefaultValues() {
954
        super.initDefaultValues();
955
        if (deleteSecondFeatureDefaultValue != null) {
956
            this.deleteSecondSelectedGeometryParameter.setDefaultValue(deleteSecondFeatureDefaultValue);
957
        }
958
    }
959
960
961
962
    @Override
963
    public void stop() throws StopServiceException {
964
        this.values.clear();
965
        this.firstSegmentData = null;
966
        this.secondSegmentData = null;
967 3289 fdiaz
        this.pointToChamfer = null;
968 3194 fdiaz
    }
969
970
    @Override
971
    public Object getValue(EditingServiceParameter parameter) {
972
        return values != null ? values.get(parameter) : null;
973
    }
974
975
    private Feature getFeatureNearestPoint(Point point) {
976
        EditingProviderServices editingProviderServices = (EditingProviderServices) getProviderServices();
977
        Feature feature = editingProviderServices.getFeature(point, featureStore, mapContext);
978
        return feature;
979
    }
980
981 3289 fdiaz
    private int validateAsSecondSegmentData(SegmentData segmentData, Point oppositeVertex) throws GeometryOperationNotSupportedException, GeometryOperationException {
982 3194 fdiaz
983
        if (!segmentData.isFilled()) {
984 3289 fdiaz
            return ERR_SEGMENT_DATA_NOT_FILLED;
985 3194 fdiaz
        }
986
        if (this.firstSegmentData == null) {
987 3289 fdiaz
            return ERR_FIRST_SEGMENT_DATA_NULL;
988 3194 fdiaz
        }
989
        Primitive firstPrimitive = this.firstSegmentData.getPrimitive();
990
        Primitive secondPrimitive = segmentData.getPrimitive();
991
        if (Objects.equals(firstPrimitive, secondPrimitive)) {
992
            if (Objects.equals(this.firstSegmentData.getIdxVertex(), segmentData.getIdxVertex())) {
993 3289 fdiaz
                return ERR_SAME_SEGMENT;
994 3194 fdiaz
            }
995 3289 fdiaz
            if (Math.abs(this.firstSegmentData.getIdxVertex() - segmentData.getIdxVertex()) <= 1) {
996
                return validateSegmentsAndLength(firstSegmentData, segmentData, calculatePointToChamfer(firstSegmentData, segmentData));
997 3194 fdiaz
            }
998
            switch (firstPrimitive.getType()) {
999
                case Geometry.TYPES.LINE:
1000
                    if (((Line) firstPrimitive).isClosed()) {
1001
                        if ((this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) && segmentData.getPosition().equals(SEGMENT_POSITION_LAST)
1002
                                || this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST) && segmentData.getPosition().equals(SEGMENT_POSITION_FIRST))) {
1003 3289 fdiaz
                            return validateSegmentsAndLength(firstSegmentData, segmentData, calculatePointToChamfer(firstSegmentData, segmentData));
1004 3194 fdiaz
                        }
1005
1006
                    } else {
1007
                        if ((this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) || this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST))
1008
                                && (segmentData.getPosition().equals(SEGMENT_POSITION_FIRST) || segmentData.getPosition().equals(SEGMENT_POSITION_LAST))) {
1009 3289 fdiaz
                            Point tmpPointToChamfer = calculatePointToChamfer(firstSegmentData, segmentData);
1010 3194 fdiaz
                            if (tmpPointToChamfer == null
1011
                                    || calculateZoneInSegment(tmpPointToChamfer, segmentData) == INVALID_ZONE
1012
                                    || calculateZoneInSegment(tmpPointToChamfer, firstSegmentData) == INVALID_ZONE) {
1013 3289 fdiaz
                                return ERR_CANT_CALCULATE_CHAMFER_POINT;
1014 3194 fdiaz
                            }
1015
                            if (!isPointBetweenTwoPoints(segmentData.getProjectedPoint(), oppositeVertex, tmpPointToChamfer)) {
1016 3289 fdiaz
                                return ERR_CANT_CALCULATE_CHAMFER_POINT;
1017 3194 fdiaz
                            }
1018 3289 fdiaz
                            return validateSegmentsAndLength(firstSegmentData, segmentData, calculatePointToChamfer(firstSegmentData, segmentData));
1019 3194 fdiaz
                        }
1020
                    }
1021 3289 fdiaz
                    return ERR_NON_ADJACENT_SEGMENTS;
1022 3194 fdiaz
1023
                case Geometry.TYPES.POLYGON:
1024
                    if (this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) && segmentData.getPosition().equals(SEGMENT_POSITION_LAST)
1025
                            || this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST) && segmentData.getPosition().equals(SEGMENT_POSITION_FIRST)) {
1026 3289 fdiaz
                        return validateSegmentsAndLength(firstSegmentData, segmentData, calculatePointToChamfer(firstSegmentData, segmentData));
1027 3194 fdiaz
                    }
1028 3289 fdiaz
                    return ERR_NON_ADJACENT_SEGMENTS;
1029 3194 fdiaz
                default:
1030 3289 fdiaz
                    return ERR_NON_ADJACENT_SEGMENTS;
1031 3194 fdiaz
            }
1032
        } else {
1033
            if (firstPrimitive.getType() != Geometry.TYPES.LINE
1034
                    || secondPrimitive.getType() != Geometry.TYPES.LINE) {
1035 3289 fdiaz
                return ERR_DIFFERENT_GEOMETRY_TYPES;
1036 3194 fdiaz
            }
1037
            if (this.firstSegmentData.getPosition().equals(SEGMENT_POSITION_MIDDLE)
1038
                    || segmentData.getPosition().equals(SEGMENT_POSITION_MIDDLE)) {
1039 3289 fdiaz
                return ERR_ONE_OF_THE_TWO_SEGMENTS_ISNT_EXTREME;
1040 3194 fdiaz
            }
1041 3289 fdiaz
            Point tmpPointToChamfer = calculatePointToChamfer(firstSegmentData, segmentData);
1042
            if (tmpPointToChamfer == null || !isPointBetweenTwoPoints(segmentData.getProjectedPoint(), oppositeVertex, tmpPointToChamfer)) {
1043
                return ERR_CANT_CALCULATE_CHAMFER_POINT;
1044 3194 fdiaz
            }
1045 3289 fdiaz
            return validateSegmentsAndLength(firstSegmentData, segmentData, tmpPointToChamfer);
1046 3194 fdiaz
        }
1047
    }
1048 3289 fdiaz
1049
    private int validateSegmentsAndLength(SegmentData firstSegmentData, SegmentData secondSegmentData, Point pointToChamfer) throws GeometryOperationNotSupportedException, GeometryOperationException {
1050
        Pair<Point, Point> oppositeVertices = calculateOpositeToChamferVertices(firstSegmentData, secondSegmentData);
1051
        Double length = (Double) getValue(lengthParameter);
1052
        double maxLength = Math.max(
1053
                oppositeVertices.getLeft().distance(pointToChamfer),
1054
                Math.max(
1055
                        oppositeVertices.getRight().distance(pointToChamfer),
1056
                        oppositeVertices.getRight().distance(oppositeVertices.getLeft())
1057
                )
1058
        );
1059
        if (length > maxLength) {
1060
            return ERR_CHAMFER_TOO_LARGE;
1061
        }
1062
        return ERR_OK;
1063
    }
1064 3194 fdiaz
1065 3289 fdiaz
    private Point calculatePointToChamfer(SegmentData firstSegmentData, SegmentData secondSegmentData) throws GeometryOperationNotSupportedException, GeometryOperationException {
1066 3194 fdiaz
        Primitive firstPrimitive = firstSegmentData.getPrimitive();
1067
        Primitive secondPrimitive = secondSegmentData.getPrimitive();
1068
        if (Objects.equals(firstPrimitive, secondPrimitive)) {
1069
            if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex())) {
1070
                return null;
1071
            }
1072
            switch (firstPrimitive.getType()) {
1073
                case Geometry.TYPES.LINE:
1074
                    if (((Line) firstPrimitive).isClosed()) {
1075
                        if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() - 1)) {
1076
                            return firstSegmentData.getLine().getVertex(1);
1077
                        } else if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() + 1)) {
1078
                            return firstSegmentData.getLine().getVertex(0);
1079
                        } else if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_LAST)) {
1080
                            return firstSegmentData.getLine().getVertex(0);
1081
                        } else if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST)) {
1082
                            return firstSegmentData.getLine().getVertex(1);
1083
                        } else {
1084
                            return null;
1085
                        }
1086
                    } else {
1087
                        if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() - 1)) {
1088
                            return firstSegmentData.getLine().getVertex(1);
1089
                        } else if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() + 1)) {
1090
                            return firstSegmentData.getLine().getVertex(0);
1091
                        } else if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_LAST)
1092
                                || firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST)) {
1093 3289 fdiaz
                            return calculatePointToChamferSeparateSegments(firstSegmentData, secondSegmentData);
1094 3194 fdiaz
                        } else {
1095
                            return null;
1096
                        }
1097
                    }
1098
                case Geometry.TYPES.POLYGON:
1099
                    if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() - 1)) {
1100
                        return firstSegmentData.getLine().getVertex(1);
1101
                    } else if (Objects.equals(firstSegmentData.getIdxVertex(), secondSegmentData.getIdxVertex() + 1)) {
1102
                        return firstSegmentData.getLine().getVertex(0);
1103
                    } else if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_LAST)) {
1104
                        return firstSegmentData.getLine().getVertex(0);
1105
                    } else if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST) && secondSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST)) {
1106
                        return firstSegmentData.getLine().getVertex(1);
1107
                    } else {
1108
                        return null;
1109
                    }
1110
                default:
1111
                    return null;
1112
            }
1113
        } else {
1114
            if (firstPrimitive.getType() != Geometry.TYPES.LINE) {
1115
                return null;
1116
            }
1117
            if (secondPrimitive.getType() != Geometry.TYPES.LINE) {
1118
                return null;
1119
            }
1120
1121
            if ((firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) || firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST))
1122
                    && (secondSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST) || secondSegmentData.getPosition().equals(SEGMENT_POSITION_LAST))) {
1123 3289 fdiaz
                return calculatePointToChamferSeparateSegments(firstSegmentData, secondSegmentData);
1124 3194 fdiaz
            } else {
1125
                return null;
1126
            }
1127
        }
1128
    }
1129
1130 3289 fdiaz
    private Point calculatePointToChamferSeparateSegments(SegmentData firstSegmentData, SegmentData secondSegmentData) throws GeometryOperationNotSupportedException, GeometryOperationException {
1131 3194 fdiaz
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
1132
        EuclideanLine2D firstLine = euclideanManager.createLine2D(
1133
                firstSegmentData.getLine().getVertex(0).getX(),
1134
                firstSegmentData.getLine().getVertex(0).getY(),
1135
                firstSegmentData.getLine().getVertex(1).getX(),
1136
                firstSegmentData.getLine().getVertex(1).getY());
1137
        EuclideanLine2D secondLine = euclideanManager.createLine2D(
1138
                secondSegmentData.getLine().getVertex(0).getX(),
1139
                secondSegmentData.getLine().getVertex(0).getY(),
1140
                secondSegmentData.getLine().getVertex(1).getX(),
1141
                secondSegmentData.getLine().getVertex(1).getY());
1142
        Point2D intersection = firstLine.getIntersection(secondLine);
1143
        Point intersectionPoint = GeometryUtils.createPoint(intersection.getX(), intersection.getY());
1144
        if (intersectionPoint == null) {
1145
            return null; //throw new IllegalArgumentException("Not valid segments.");
1146
        }
1147
        if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_LAST)
1148
                && calculateZoneInSegment(intersectionPoint, firstSegmentData) == INVALID_ZONE) {
1149
            return null;
1150
        }
1151
        if (firstSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST)
1152
                && calculateZoneInSegment(intersectionPoint, firstSegmentData) == INVALID_ZONE) {
1153
            return null;
1154
        }
1155
        if (secondSegmentData.getPosition().equals(SEGMENT_POSITION_LAST)
1156
                && calculateZoneInSegment(intersectionPoint, firstSegmentData) == INVALID_ZONE) {
1157
            return null;
1158
        }
1159
        if (secondSegmentData.getPosition().equals(SEGMENT_POSITION_FIRST)
1160
                && calculateZoneInSegment(intersectionPoint, firstSegmentData) == INVALID_ZONE) {
1161
            return null;
1162
        }
1163
        return intersectionPoint;
1164
    }
1165
1166
    private int calculateZoneInSegment(Point point, SegmentData segmentData) throws GeometryOperationNotSupportedException, GeometryOperationException {
1167
        //We assume that the point is on the line to which the segment belongs.
1168
        Line line = segmentData.getLine();
1169
        if (line.getNumVertices() > 2) {
1170
            throw new IllegalArgumentException("Segment has more than two vertex.");
1171
        }
1172
1173
        Point firstVertex;
1174
        Point secondVertex;
1175
1176
        if (Objects.equals(segmentData.getPosition(), SEGMENT_POSITION_LAST)) {
1177
            firstVertex = line.getVertex(0);
1178
            secondVertex = line.getVertex(1);
1179
        } else { // SEGMENT_POSITION_FIRST,  SEGMENT_POSITION_MIDDLE doesn't matter
1180
            firstVertex = line.getVertex(1);
1181
            secondVertex = line.getVertex(0);
1182
        }
1183
1184
        double segmentLenght = firstVertex.distance(secondVertex);
1185
        if (segmentLenght >= firstVertex.distance(point) && segmentLenght >= secondVertex.distance(point)) {
1186
            return INSIDE_THE_SEGMENT; //0
1187
        } else if (firstVertex.distance(point) > secondVertex.distance(point)) {
1188
            return BEYOND_THE_SEGMENT; //1
1189
        } else {
1190
            return INVALID_ZONE; //-1
1191
        }
1192
    }
1193
1194
    private boolean isPointBetweenTwoPoints(Point point, Point vertex1, Point vertex2) {
1195
        //The three points must be aligned
1196
        if (point.getX() < vertex1.getX() && point.getX() < vertex2.getX()) {
1197
            return false;
1198
        }
1199
        if (point.getX() > vertex1.getX() && point.getX() > vertex2.getX()) {
1200
            return false;
1201
        }
1202
        if (point.getY() < vertex1.getY() && point.getY() < vertex2.getY()) {
1203
            return false;
1204
        }
1205
        if (point.getY() > vertex1.getY() && point.getY() > vertex2.getY()) {
1206
            return false;
1207
        }
1208
        return true;
1209
    }
1210
1211 3289 fdiaz
    private double calculateDefaultAngle(Point pointToChamfer, Pair<Point, Point> oppositeVertices) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException {
1212 3194 fdiaz
1213
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
1214
        Point2D p = euclideanManager.getPointAtDistance(
1215 3289 fdiaz
                pointToChamfer.getX(),
1216
                pointToChamfer.getY(),
1217
                pointToChamfer.distance(oppositeVertices.getLeft()),
1218
                GeometryUtils.calculateAngle(pointToChamfer, oppositeVertices.getRight()),
1219 3194 fdiaz
                null
1220
        );
1221
1222
        Point midPoint = GeometryUtils.getMidPoint(
1223
                oppositeVertices.getLeft(),
1224
                GeometryUtils.createPoint(p.getX(), p.getY()),
1225 3289 fdiaz
                pointToChamfer.getGeometryType().getSubType()
1226 3194 fdiaz
        );
1227
        double angle = GeometryUtils.calculateAngle(
1228 3289 fdiaz
                pointToChamfer,
1229 3194 fdiaz
                midPoint
1230
        );
1231
        angle = angle + Math.PI/2;
1232
        if(angle > 2*Math.PI){
1233
            angle = angle - 2*Math.PI;
1234
        }
1235
        return Math.toDegrees(angle);
1236
    }
1237
1238 3289 fdiaz
    private Line calculateChamfer(SegmentData firstSegmentData, SegmentData secondSegmentData, Double length, Double angle, int subType) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException {
1239 3194 fdiaz
1240 3289 fdiaz
        ScaffoldingToChamfer scaffolding = calculateScaffolding(firstSegmentData, secondSegmentData, pointToChamfer, length, angle, subType);
1241
        if(scaffolding == null){
1242 3194 fdiaz
            return null;
1243
        }
1244 3289 fdiaz
        Line chamfer;
1245
        if(scaffolding.isReversed()) {
1246
            chamfer = GeometryUtils.createLine(
1247
                    scaffolding.chamferRight.getX(),
1248
                    scaffolding.chamferRight.getY(),
1249
                    scaffolding.chamferLeft.getX(),
1250
                    scaffolding.chamferLeft.getY(),
1251
                    subType
1252
            );
1253
        } else {
1254
            chamfer = GeometryUtils.createLine(
1255
                    scaffolding.chamferLeft.getX(),
1256
                    scaffolding.chamferLeft.getY(),
1257
                    scaffolding.chamferRight.getX(),
1258
                    scaffolding.chamferRight.getY(),
1259
                    subType
1260
            );
1261 3194 fdiaz
        }
1262
1263 3289 fdiaz
        return chamfer;
1264 3194 fdiaz
    }
1265
1266
    /**
1267
     *
1268
     * @param firstSegmentData
1269
     * @param secondSegmentData
1270 3289 fdiaz
     * @param pointToChamfer
1271 3194 fdiaz
     * @param distance
1272
     * @param angle must be in radians
1273
     * @param subType
1274
     * @return
1275
     */
1276 3289 fdiaz
    private ScaffoldingToChamfer calculateScaffolding(SegmentData firstSegmentData, SegmentData secondSegmentData, Point pointToChamfer, Double length, Double angle, int subType) throws GeometryOperationNotSupportedException, GeometryOperationException, CreateGeometryException {
1277
1278
        Pair<Point, Point> oppositeVertices = calculateOpositeToChamferVertices(firstSegmentData, secondSegmentData);
1279
        Point p1 = GeometryUtils.createPoint(pointToChamfer, length, angle);
1280
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
1281 3194 fdiaz
1282 3289 fdiaz
        boolean reverse = false;
1283
1284
        EuclideanLine2D base = euclideanManager.createLine2D(
1285
                pointToChamfer.getX(),
1286
                pointToChamfer.getY(),
1287
                p1.getX(),
1288
                p1.getY()
1289 3194 fdiaz
        );
1290
1291 3289 fdiaz
        Point o1 = oppositeVertices.getLeft();
1292
        Point o2 = oppositeVertices.getRight();
1293
1294
        EuclideanLine2D left = euclideanManager.createLine2D(
1295
                pointToChamfer.getX(),
1296
                pointToChamfer.getY(),
1297
                o1.getX(),
1298
                o1.getY()
1299 3194 fdiaz
        );
1300 3289 fdiaz
        EuclideanLine2D leftParallel = left.getParallel(p1.getX(), p1.getY());
1301 3194 fdiaz
1302 3289 fdiaz
        EuclideanLine2D right = euclideanManager.createLine2D(
1303
                pointToChamfer.getX(),
1304
                pointToChamfer.getY(),
1305
                o2.getX(),
1306
                o2.getY()
1307 3194 fdiaz
        );
1308
1309 3289 fdiaz
        Point2D chamferRight = leftParallel.getIntersection(right);
1310 3194 fdiaz
1311 3289 fdiaz
        if (!isPointBetweenTwoPoints(
1312
                GeometryUtils.createPoint(chamferRight.getX(), chamferRight.getY()),
1313
                o2,
1314
                pointToChamfer)) { //Le damos la vuelta a los vertices opuestos y volvemos probar
1315
            reverse = true;
1316
            o1 = oppositeVertices.getRight();
1317
            o2 = oppositeVertices.getLeft();
1318
1319
            left = euclideanManager.createLine2D(
1320
                    pointToChamfer.getX(),
1321
                    pointToChamfer.getY(),
1322
                    o1.getX(),
1323
                    o1.getY()
1324
            );
1325
            leftParallel = left.getParallel(p1.getX(), p1.getY());
1326
1327
            right = euclideanManager.createLine2D(
1328
                    pointToChamfer.getX(),
1329
                    pointToChamfer.getY(),
1330
                    o2.getX(),
1331
                    o2.getY()
1332
            );
1333
1334
            chamferRight = leftParallel.getIntersection(right);
1335
1336
            if (!isPointBetweenTwoPoints(
1337
                    GeometryUtils.createPoint(chamferRight.getX(), chamferRight.getY()),
1338
                    o2,
1339
                    pointToChamfer)) {
1340
                return null;
1341
            }
1342
        }
1343
1344 3194 fdiaz
1345 3289 fdiaz
        EuclideanLine2D baseParallel = base.getParallel(chamferRight);
1346
1347
        Point2D chamferLeft = baseParallel.getIntersection(left);
1348
1349
        if (!isPointBetweenTwoPoints(
1350
                GeometryUtils.createPoint(chamferLeft.getX(), chamferLeft.getY()),
1351
                o1,
1352
                pointToChamfer)
1353
        ) {
1354
            return null;
1355
        }
1356
1357
        ScaffoldingToChamfer scaffolding;
1358
        scaffolding = new ScaffoldingToChamfer(chamferLeft, chamferRight, p1, reverse);
1359
1360 3194 fdiaz
        return scaffolding;
1361
    }
1362
1363 3289 fdiaz
    private class ScaffoldingToChamfer {
1364 3194 fdiaz
1365 3289 fdiaz
        private final Point2D chamferLeft;
1366
        private final Point2D chamferRight;
1367
        private final Point p1;
1368
        private final boolean reverse;
1369 3194 fdiaz
1370 3289 fdiaz
        public ScaffoldingToChamfer(Point2D chamferLeft, Point2D chamferRight, Point p1, boolean reverse) {
1371
            this.chamferLeft = chamferLeft;
1372
            this.chamferRight = chamferRight;
1373
            this.p1 = p1;
1374
            this.reverse = reverse;
1375 3194 fdiaz
        }
1376
1377 3289 fdiaz
1378
        public Point2D getChamferRight() {
1379
            return chamferRight;
1380 3194 fdiaz
        }
1381
1382 3289 fdiaz
        public Point2D getChamferLeft() {
1383
            return chamferLeft;
1384 3194 fdiaz
        }
1385
1386 3289 fdiaz
        public Point getP1() {
1387
            return p1;
1388 3194 fdiaz
        }
1389
1390 3289 fdiaz
        public boolean isReversed() {
1391
            return reverse;
1392
        }
1393
1394
1395 3194 fdiaz
    }
1396
}