1 package org.simantics.district.network.ui.contributions;
3 import java.awt.geom.AffineTransform;
4 import java.awt.geom.NoninvertibleTransformException;
5 import java.awt.geom.Point2D;
6 import java.lang.reflect.InvocationTargetException;
8 import java.util.Optional;
9 import java.util.concurrent.TimeUnit;
11 import javax.inject.Named;
13 import org.eclipse.core.commands.ParameterizedCommand;
14 import org.eclipse.e4.core.di.annotations.CanExecute;
15 import org.eclipse.e4.core.di.annotations.Execute;
16 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
17 import org.eclipse.e4.ui.services.IServiceConstants;
18 import org.eclipse.jface.viewers.ISelection;
19 import org.eclipse.ui.IEditorPart;
20 import org.simantics.Simantics;
21 import org.simantics.databoard.Bindings;
22 import org.simantics.db.ReadGraph;
23 import org.simantics.db.Resource;
24 import org.simantics.db.WriteGraph;
25 import org.simantics.db.common.request.ReadRequest;
26 import org.simantics.db.common.request.WriteRequest;
27 import org.simantics.db.exception.DatabaseException;
28 import org.simantics.db.layer0.SelectionHints;
29 import org.simantics.db.layer0.util.RemoverUtil;
30 import org.simantics.db.request.Read;
31 import org.simantics.diagram.stubs.DiagramResource;
32 import org.simantics.district.network.DistrictNetworkUtil;
33 import org.simantics.district.network.ModelledCRS;
34 import org.simantics.district.network.ontology.DistrictNetworkResource;
35 import org.simantics.district.network.ui.DNEdgeBuilder;
36 import org.simantics.district.network.ui.DistrictDiagramEditor;
37 import org.simantics.district.network.ui.NetworkDrawingParticipant;
38 import org.simantics.g2d.canvas.ICanvasContext;
39 import org.simantics.g2d.participant.MouseUtil;
40 import org.simantics.g2d.participant.MouseUtil.MouseInfo;
41 import org.simantics.maps.elevation.server.SingletonTiffTileInterface;
42 import org.simantics.maps.elevation.server.prefs.MapsElevationServerPreferences;
43 import org.simantics.ui.workbench.e4.E4WorkbenchUtils;
44 import org.simantics.utils.threads.ThreadUtils;
45 import org.simantics.utils.ui.ISelectionUtils;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class ChangeRoutePointToVertexHandler {
51 private static final Logger LOGGER = LoggerFactory.getLogger(ChangeRoutePointToVertexHandler.class);
52 static List<Resource> elements;
53 static boolean cut = true;
56 public boolean canExecute(@Named(IServiceConstants.ACTIVE_SELECTION) ISelection selection) {
57 List<Resource> elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class);
58 if (elements.size() != 1)
61 return Simantics.getSession().syncRequest(new Read<Boolean>() {
64 public Boolean perform(ReadGraph graph) throws DatabaseException {
65 DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
66 for (Resource selection : elements) {
67 if (!graph.isInstanceOf(selection, DN.Edge)) {
74 } catch (DatabaseException e) {
75 LOGGER.error("Could not evaluate if mapping can be changed for selection {}", elements, e);
81 public void execute(@Named(IServiceConstants.ACTIVE_PART) MPart mActiveEditorPart, @Named(IServiceConstants.ACTIVE_SELECTION) Object selection, ParameterizedCommand command) {
82 final List<Resource> elements = ISelectionUtils.getPossibleKeys(selection, SelectionHints.KEY_MAIN, Resource.class);
84 Resource edge = elements.get(0);
86 Point2D mouseClicked = mouseClickedOnEditor(mActiveEditorPart);
87 if (mouseClicked != null) {
89 IEditorPart activeEditorPart = E4WorkbenchUtils.getActiveIEditorPart(mActiveEditorPart);
90 if (activeEditorPart == null)
92 if (!(activeEditorPart instanceof DistrictDiagramEditor))
94 DistrictDiagramEditor editor = (DistrictDiagramEditor) activeEditorPart;
95 Resource diagram = editor.getInputResource();
97 Simantics.getSession().asyncRequest(new ReadRequest() {
100 public void run(ReadGraph graph) throws DatabaseException {
101 DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph);
102 double[] detailedGeom = graph.getPossibleRelatedValue(edge, DN.Edge_HasGeometry, Bindings.DOUBLE_ARRAY);
103 if (detailedGeom != null) {
104 double closestDistance = Double.MAX_VALUE;
105 Point2D closestPoint = null;
107 for (int i = 0; i < detailedGeom.length; i += 2) {
108 double x = detailedGeom[i];
109 double y = detailedGeom[i + 1];
110 Point2D currentPoint = new Point2D.Double(x, y);
111 double currentDistance = mouseClicked.distance(currentPoint);
112 if (currentDistance < closestDistance) {
113 closestDistance = currentDistance;
114 closestPoint = currentPoint;
119 final Point2D finalClosestPoint = closestPoint;
121 DiagramResource DIA = DiagramResource.getInstance(graph);
122 Resource currentStartVertex = graph.getSingleObject(edge, DN.HasStartVertex);
123 double[] currentStartVertexCoords = graph.getRelatedValue(currentStartVertex, DIA.HasLocation, Bindings.DOUBLE_ARRAY);
124 Resource currentEndVertex = graph.getSingleObject(edge, DN.HasEndVertex);
125 double[] currentEndVertexCoords = graph.getRelatedValue(currentEndVertex, DIA.HasLocation, Bindings.DOUBLE_ARRAY);
127 double[] detailedLeftEdgeGeometryCoords = new double[j];
128 for (int k = 0; k < j; k += 2) {
129 double x = detailedGeom[k];
130 double y = detailedGeom[k + 1];
131 detailedLeftEdgeGeometryCoords[k] = x;
132 detailedLeftEdgeGeometryCoords[k + 1] = y;
135 double[] detailedRightEdgeGeometryCoords = new double[detailedGeom.length - j - 2];
137 for (int k = j + 2; k < detailedGeom.length; k += 2) {
138 double x = detailedGeom[k];
139 double y = detailedGeom[k + 1];
140 detailedRightEdgeGeometryCoords[i++] = x;
141 detailedRightEdgeGeometryCoords[i++] = y;
144 Simantics.getSession().asyncRequest(new WriteRequest() {
147 public void perform(WriteGraph graph) throws DatabaseException {
148 RemoverUtil.remove(graph, edge);
150 ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> {
151 Simantics.getSession().asyncRequest(new WriteRequest() {
154 public void perform(WriteGraph graph) throws DatabaseException {
155 // we might have closest point
156 if (finalClosestPoint != null) {
157 Resource mapping = graph.getSingleObject(diagram, DistrictNetworkResource.getInstance(graph).VertexDefaultMapping);
158 double x = finalClosestPoint.getX();
159 double y = finalClosestPoint.getY();
160 double[] midVertexCoords = new double[] { x, y };
162 double elevation = 0;
163 if (MapsElevationServerPreferences.useElevationServer()) {
164 // ok! we use new elevation API to resolve possible elevations for the starting points
166 elevation = SingletonTiffTileInterface.lookup(x, y).doubleValue();
167 } catch (Exception ee) {
168 LOGGER.error("Could not get elevation from tiff interface", ee);
172 Resource createdVertex = DistrictNetworkUtil.createVertex(graph, diagram, midVertexCoords, elevation, mapping);
174 Optional<Resource> leftEdge = DNEdgeBuilder.create(graph, diagram, currentStartVertexCoords, 0, midVertexCoords, 0, detailedLeftEdgeGeometryCoords, 0.001);
175 Optional<Resource> rightEdge = DNEdgeBuilder.create(graph, diagram, midVertexCoords, 0, currentEndVertexCoords, 0, detailedRightEdgeGeometryCoords, 0.001);
180 }, 500, TimeUnit.MILLISECONDS);
186 // no can do - or it would be possible to split the edge here in to two different edges
191 LOGGER.warn("No mouseClicked for editor {}", mActiveEditorPart);
193 } catch (InvocationTargetException e) {
194 LOGGER.error("Could not change route point to vertex", e);
198 private static Point2D mouseClickedOnEditor(MPart mActiveEditorPart) throws InvocationTargetException {
199 IEditorPart activeEditorPart = E4WorkbenchUtils.getActiveIEditorPart(mActiveEditorPart);
200 if (activeEditorPart == null)
202 if (!(activeEditorPart instanceof DistrictDiagramEditor))
204 DistrictDiagramEditor editor = (DistrictDiagramEditor) activeEditorPart;
206 ICanvasContext ctx = editor.getAdapter(ICanvasContext.class);
207 NetworkDrawingParticipant drawingParticipant = ctx.getAtMostOneItemOfClass(NetworkDrawingParticipant.class);
208 AffineTransform drawingTransform = drawingParticipant.getTransform();
209 MouseUtil util = ctx.getAtMostOneItemOfClass(MouseUtil.class);
210 MouseInfo mouseInfo = util.getMousePressedInfo(0);
211 if (mouseInfo == null) {
214 Point2D canvasPosition = mouseInfo.canvasPosition;
215 Point2D transformed = null;
217 transformed = drawingTransform.inverseTransform(canvasPosition, new Point2D.Double());
218 } catch (NoninvertibleTransformException e) {
219 LOGGER.error("Could not create inverse transform of {}", drawingTransform, e);
220 throw new InvocationTargetException(e);
222 double x = ModelledCRS.xToLongitude(transformed.getX());
223 double y = ModelledCRS.yToLatitude(-transformed.getY());
224 return new Point2D.Double(x, y);