From: jsimomaa Date: Thu, 4 Apr 2019 17:53:10 +0000 (+0300) Subject: Make vertices smaller on map UI & CSV import performance improvements X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;ds=sidebyside;h=d4d53a3987be0c2b771c8093b7e8c2286738a6c8;p=simantics%2Fdistrict.git Make vertices smaller on map UI & CSV import performance improvements gitlab #41 APROS-15329 Change-Id: I593b35c1d571b9d1a7f291bd3e81c77fc39b67b3 --- diff --git a/org.simantics.district.geotools/META-INF/MANIFEST.MF b/org.simantics.district.geotools/META-INF/MANIFEST.MF index f8eee2dd..05b21c22 100644 --- a/org.simantics.district.geotools/META-INF/MANIFEST.MF +++ b/org.simantics.district.geotools/META-INF/MANIFEST.MF @@ -20,7 +20,15 @@ Bundle-ClassPath: lib/commons-pool-1.5.4.jar, ., lib/gt-epsg-hsql-16.0.jar, lib/hsqldb-2.3.4.jar -Export-Package: org.geotools.geometry, +Export-Package: com.vividsolutions.jts, + com.vividsolutions.jts.geom, + com.vividsolutions.jts.geom.impl, + com.vividsolutions.jts.geom.prep, + com.vividsolutions.jts.geom.util, + com.vividsolutions.jts.geomgraph, + com.vividsolutions.jts.geomgraph.index, + com.vividsolutions.jts.index.quadtree, + org.geotools.geometry, org.geotools.referencing, org.opengis.geometry, org.opengis.referencing, diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java index 93646ded..6861b5c4 100644 --- a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportModel.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVRecord; import org.simantics.db.Resource; import org.simantics.district.imports.DistrictImportUtils; @@ -95,9 +96,9 @@ public class CSVImportModel { return source; } - public List getRows(int amount) throws IOException { + public List getRows(int amount, boolean readFirstAsHeader) throws IOException { if (source != null) - return DistrictImportUtils.readRows(source, delimiter, amount); + return DistrictImportUtils.readRows(source, delimiter, readFirstAsHeader, amount); else return Collections.emptyList(); } @@ -132,7 +133,7 @@ public class CSVImportModel { public List> readRows(int amount) throws IOException { if (source != null) - return DistrictImportUtils.readRows(source, delimiter, readFirstAsHeader, amount); + return DistrictImportUtils.readRows(source, CSVFormat.newFormat(delimiter), readFirstAsHeader, amount); else return Collections.emptyList(); } diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java index 8c087210..c0d756d3 100644 --- a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizard.java @@ -1,10 +1,11 @@ package org.simantics.district.imports.ui; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; -import java.util.List; +import java.util.Optional; import org.apache.commons.csv.CSVRecord; import org.eclipse.core.runtime.IProgressMonitor; @@ -23,11 +24,14 @@ import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; import org.simantics.Simantics; import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; -import org.simantics.db.request.Write; +import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.imports.DistrictImportUtils; import org.simantics.district.network.DistrictNetworkUtil; @@ -37,6 +41,9 @@ import org.simantics.district.network.ui.DNEdgeBuilder.ResourceVertex; import org.simantics.layer0.Layer0; import org.simantics.utils.ui.ExceptionUtils; +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.index.quadtree.Quadtree; + public class CSVImportWizard extends Wizard implements IImportWizard { private CSVImportModel model; @@ -66,8 +73,7 @@ public class CSVImportWizard extends Wizard implements IImportWizard { Path csvFile = model.getSource(); char delim = model.getDelimiter(); - List rows = DistrictImportUtils.readRows(csvFile, delim, -1); - monitor.beginTask("Importing CSV", rows.size()); + monitor.beginTask("Importing CSV", 1); // Path wktFile = model.getWKTFile(); @@ -128,135 +134,161 @@ public class CSVImportWizard extends Wizard implements IImportWizard { } final boolean actualDoTransform = doTransform; final MathTransform actualTransform = transform; - Simantics.getSession().syncRequest(new Write() { - + + double halfPadding = padding / 2; + + Quadtree vv = Simantics.getSession().syncRequest(new UniqueRead() { + @Override - public void perform(WriteGraph graph) throws DatabaseException { - graph.markUndoPoint(); - - DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); - + public Quadtree perform(ReadGraph graph) throws DatabaseException { Collection vertices = graph.syncRequest(new ObjectsWithType(model.getParentDiagram(), Layer0.getInstance(graph).ConsistsOf, DistrictNetworkResource.getInstance(graph).Vertex)); - List vv = new ArrayList<>(vertices.size()); + Quadtree vv = new Quadtree(); for (Resource vertex : vertices) { - double[] existingCoords = graph.getRelatedValue2(vertex, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY); - vv.add(new ResourceVertex(vertex, existingCoords)); + double[] coords = graph.getRelatedValue2(vertex, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY); + double x1 = coords[0] - halfPadding; + double y1= coords[1] - halfPadding; + double x2 = coords[0] + halfPadding; + double y2= coords[1] + halfPadding; + Envelope e = new Envelope(x1, x2, y1, y2); + vv.insert(e, new ResourceVertex(vertex, coords, true)); } - - for (int k = 1; k < rows.size(); k++) { - CSVRecord row = rows.get(k); + return vv; + } + }); + + Simantics.getSession().syncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + try { + Layer0Utils.setDependenciesIndexingDisabled(graph, true); + graph.markUndoPoint(); - String mappingValue = row.get(mappingColumn); - - try { - if (model.isVertexImport()) { - String xCoords = row.get(xCoordColumnIndex); - String yCoords = row.get(yCoordColumnIndex); - double xCoord = Double.parseDouble(xCoords); - double yCoord = Double.parseDouble(yCoords); - - double z = 0; - if (zCoordColumnIndex != -1) { - String zs = row.get(zCoordColumnIndex); + DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + + DistrictImportUtils.consumeCSV(csvFile, delim, true, row -> { + String mappingValue = row.get(mappingColumn); + + try { + if (model.isVertexImport()) { + String xCoords = row.get(xCoordColumnIndex); + String yCoords = row.get(yCoordColumnIndex); + double xCoord = Double.parseDouble(xCoords); + double yCoord = Double.parseDouble(yCoords); - if (!zs.isEmpty()) { - try { - z = Double.parseDouble(zs); - } catch (NumberFormatException e) { - throw new DatabaseException(e); + double z = 0; + if (zCoordColumnIndex != -1) { + String zs = row.get(zCoordColumnIndex); + + if (!zs.isEmpty()) { + try { + z = Double.parseDouble(zs); + } catch (NumberFormatException e1) { + throw new DatabaseException(e1); + } } } - } - - double[] coords; - if (actualDoTransform) { - DirectPosition2D targetPos = new DirectPosition2D(); - DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord); - DirectPosition res = actualTransform.transform(sourcePos, targetPos); - coords = res.getCoordinate(); - } else { - coords = new double[] { xCoord, yCoord }; - } - - // Switch to (longitude, latitude) - flipAxes(coords); - - Resource vertex = DistrictNetworkUtil.createVertex(graph, model.getParentDiagram(), coords, model.getComponentMappings().get(mappingValue)); - - writeStringValue(graph, row, idColumn, vertex, DN.HasId); - - graph.claimLiteral(vertex, DN.Vertex_HasElevation, z, Bindings.DOUBLE); - - writeValue(graph, row, supplyTempColumnIndex, vertex, DN.Vertex_HasSupplyTemperature); - writeValue(graph, row, returnTempColumnIndex, vertex, DN.Vertex_HasReturnTemperature); - writeValue(graph, row, supplyPressureColumnIndex, vertex, DN.Vertex_HasSupplyPressure); - writeValue(graph, row, returnPressureColumnIndex, vertex, DN.Vertex_HasReturnPressure); - writeValue(graph, row, dpIndex, vertex, DN.Vertex_HasDeltaPressure); - writeValue(graph, row, dtIndex, vertex, DN.Vertex_HasDeltaTemperature); - writeValue(graph, row, heatPowerIndex, vertex, DN.Vertex_HasHeatPower); - writeValue(graph, row, valvePositionIndex, vertex, DN.Vertex_HasValvePosition); - writeValue(graph, row, nominalHeadMIndex, vertex, DN.Vertex_HasNominalHeadM); - writeValue(graph, row, nominalHeadBIndex, vertex, DN.Vertex_HasNominalHeadB); - writeValue(graph, row, nominalFlowIndex, vertex, DN.Vertex_HasNominalFlow); - writeValue(graph, row, maximumHeadMIndex, vertex, DN.Vertex_HasMaximumHeadM); - writeValue(graph, row, heatLoadDsIndex, vertex, DN.Vertex_HasHeatLoadDs); - writeValue(graph, row, massFlowIndex, vertex, DN.Vertex_HasMassFlow); - writeValue(graph, row, volFlowIndex, vertex, DN.Vertex_HasVolFlow); - writeValue(graph, row, velocityIndex, vertex, DN.Vertex_HasVelocity); - writeValue(graph, row, flowAreaIndex, vertex, DN.Vertex_HasFlowArea); - writeValue(graph, row, nominalPressureLossIndex, vertex, DN.Vertex_HasNominalPressureLoss); - writeStringValue(graph, row, addressIndex, vertex, DN.Vertex_HasAddress); - - } else { - String startXCoords = row.get(startXCoordColumnIndex); - String startYCoords = row.get(startYCoordColumnIndex); - String endXCoords = row.get(endXCoordColumnIndex); - String endYCoords = row.get(endYCoordColumnIndex); - - double startXCoord = Double.parseDouble(startXCoords); // make negative - double startYCoord = Double.parseDouble(startYCoords); - - double endXCoord = Double.parseDouble(endXCoords); // make negative - double endYCoord = Double.parseDouble(endYCoords); - - double[] startCoords; - double[] endCoords; - if (actualDoTransform) { - DirectPosition2D startTargetPos = new DirectPosition2D(); - DirectPosition2D startSourcePos = new DirectPosition2D(startXCoord, startYCoord); - DirectPosition startRes = actualTransform.transform(startSourcePos, startTargetPos); - startCoords = startRes.getCoordinate(); + + double[] coords; + if (actualDoTransform) { + DirectPosition2D targetPos = new DirectPosition2D(); + DirectPosition2D sourcePos = new DirectPosition2D(xCoord, yCoord); + DirectPosition res = actualTransform.transform(sourcePos, targetPos); + coords = res.getCoordinate(); + } else { + coords = new double[] { xCoord, yCoord }; + } - DirectPosition2D endTargetPos = new DirectPosition2D(); - DirectPosition2D endSourcePos = new DirectPosition2D(endXCoord, endYCoord); - DirectPosition endRes = actualTransform.transform(endSourcePos, endTargetPos); - endCoords = endRes.getCoordinate(); + // Switch to (longitude, latitude) + flipAxes(coords); + + Resource vertex = DistrictNetworkUtil.createVertex(graph, model.getParentDiagram(), coords, z, model.getComponentMappings().get(mappingValue)); + + writeStringValue(graph, row, idColumn, vertex, DN.HasId); + + writeValue(graph, row, supplyTempColumnIndex, vertex, DN.Vertex_HasSupplyTemperature); + writeValue(graph, row, returnTempColumnIndex, vertex, DN.Vertex_HasReturnTemperature); + writeValue(graph, row, supplyPressureColumnIndex, vertex, DN.Vertex_HasSupplyPressure); + writeValue(graph, row, returnPressureColumnIndex, vertex, DN.Vertex_HasReturnPressure); + writeValue(graph, row, dpIndex, vertex, DN.Vertex_HasDeltaPressure); + writeValue(graph, row, dtIndex, vertex, DN.Vertex_HasDeltaTemperature); + writeValue(graph, row, heatPowerIndex, vertex, DN.Vertex_HasHeatPower); + writeValue(graph, row, valvePositionIndex, vertex, DN.Vertex_HasValvePosition); + writeValue(graph, row, nominalHeadMIndex, vertex, DN.Vertex_HasNominalHeadM); + writeValue(graph, row, nominalHeadBIndex, vertex, DN.Vertex_HasNominalHeadB); + writeValue(graph, row, nominalFlowIndex, vertex, DN.Vertex_HasNominalFlow); + writeValue(graph, row, maximumHeadMIndex, vertex, DN.Vertex_HasMaximumHeadM); + writeValue(graph, row, heatLoadDsIndex, vertex, DN.Vertex_HasHeatLoadDs); + writeValue(graph, row, massFlowIndex, vertex, DN.Vertex_HasMassFlow); + writeValue(graph, row, volFlowIndex, vertex, DN.Vertex_HasVolFlow); + writeValue(graph, row, velocityIndex, vertex, DN.Vertex_HasVelocity); + writeValue(graph, row, flowAreaIndex, vertex, DN.Vertex_HasFlowArea); + writeValue(graph, row, nominalPressureLossIndex, vertex, DN.Vertex_HasNominalPressureLoss); + writeStringValue(graph, row, addressIndex, vertex, DN.Vertex_HasAddress); + } else { - startCoords = new double[] { startXCoord , startYCoord }; - endCoords = new double[] { endXCoord , endYCoord }; + String startXCoords = row.get(startXCoordColumnIndex); + String startYCoords = row.get(startYCoordColumnIndex); + String startZCoords = row.get(startZValueColumnIndex); + String endXCoords = row.get(endXCoordColumnIndex); + String endYCoords = row.get(endYCoordColumnIndex); + String endZCoords = row.get(endZValueColumnIndex); + + double startXCoord = Double.parseDouble(startXCoords); // make negative + double startYCoord = Double.parseDouble(startYCoords); + double startZCoord = Double.parseDouble(startZCoords); + + double endXCoord = Double.parseDouble(endXCoords); // make negative + double endYCoord = Double.parseDouble(endYCoords); + double endZCoord = Double.parseDouble(endZCoords); + + double[] startCoords; + double[] endCoords; + if (actualDoTransform) { + DirectPosition2D startTargetPos = new DirectPosition2D(); + DirectPosition2D startSourcePos = new DirectPosition2D(startXCoord, startYCoord); + DirectPosition startRes = actualTransform.transform(startSourcePos, startTargetPos); + startCoords = startRes.getCoordinate(); + + DirectPosition2D endTargetPos = new DirectPosition2D(); + DirectPosition2D endSourcePos = new DirectPosition2D(endXCoord, endYCoord); + DirectPosition endRes = actualTransform.transform(endSourcePos, endTargetPos); + endCoords = endRes.getCoordinate(); + } else { + startCoords = new double[] { startXCoord , startYCoord }; + endCoords = new double[] { endXCoord , endYCoord }; + } + + // Switch to (longitude, latitude) + flipAxes(startCoords); + flipAxes(endCoords); + + Optional oedge = DNEdgeBuilder.create(graph, vv, model.getParentDiagram(), model.getComponentMappings().get(mappingValue), startCoords, startZCoord, endCoords, endZCoord, padding, true); + if (oedge.isPresent()) { + Resource edge = oedge.get(); + writeStringValue(graph, row, idColumn, edge, DN.HasId); + + writeValue(graph, row, diameterColumnIndex, edge, DN.Edge_HasDiameter); + writeValue(graph, row, outerDiameterColumnIndex, edge, DN.Edge_HasOuterDiameter); + writeValue(graph, row, nominalMassFlowIndex, edge, DN.Edge_HasNominalMassFlow); + writeValue(graph, row, tGroundIndex, edge, DN.Edge_HasTGround); + writeValue(graph, row, kReturnIndex, edge, DN.Edge_HasKReturn); + writeValue(graph, row, kSupplyIndex, edge, DN.Edge_HasKSupply); + writeValue(graph, row, edgeFlowAreaIndex, edge, DN.Edge_HasFlowArea); + writeValue(graph, row, lengthIndex, edge, DN.Edge_HasLength); + writeDoubleArrayFromString(graph, row, detailedGeometryIndex, edge, DN.Edge_HasGeometry, actualTransform); + } } - - // Switch to (longitude, latitude) - flipAxes(startCoords); - flipAxes(endCoords); - - Resource edge = DNEdgeBuilder.create(graph, vv, model.getParentDiagram(), model.getComponentMappings().get(mappingValue), startCoords, endCoords, padding, true); - writeStringValue(graph, row, idColumn, edge, DN.HasId); - - writeValue(graph, row, diameterColumnIndex, edge, DN.Edge_HasDiameter); - writeValue(graph, row, outerDiameterColumnIndex, edge, DN.Edge_HasOuterDiameter); - writeValue(graph, row, nominalMassFlowIndex, edge, DN.Edge_HasNominalMassFlow); - writeValue(graph, row, tGroundIndex, edge, DN.Edge_HasTGround); - writeValue(graph, row, kReturnIndex, edge, DN.Edge_HasKReturn); - writeValue(graph, row, kSupplyIndex, edge, DN.Edge_HasKSupply); - writeValue(graph, row, edgeFlowAreaIndex, edge, DN.Edge_HasFlowArea); - writeValue(graph, row, lengthIndex, edge, DN.Edge_HasLength); - writeDoubleArrayFromString(graph, row, detailedGeometryIndex, edge, DN.Edge_HasGeometry, actualTransform); + } catch (MismatchedDimensionException | TransformException | DatabaseException e2) { + throw new RuntimeException(e2); } - } catch (MismatchedDimensionException | TransformException | DatabaseException e) { - throw new DatabaseException(e); - } - monitor.worked(1); + monitor.worked(1); + return true; + }); + } catch (IOException e) { + e.printStackTrace(); + } finally { + Layer0Utils.setDependenciesIndexingDisabled(graph, false); } } }); @@ -314,7 +346,9 @@ public class CSVImportWizard extends Wizard implements IImportWizard { if (index != -1) { String stringValue = row.get(index); if (!stringValue.isEmpty()) { - stringValue = stringValue.substring(1, stringValue.length() - 1); + if (stringValue.startsWith("\"") && stringValue.endsWith("\"")) { + stringValue = stringValue.substring(1, stringValue.length() - 1); + } String[] coordPairs = stringValue.split(";"); ArrayList dd = new ArrayList<>(coordPairs.length * 2); for (int i = 0; i < coordPairs.length; i++) { diff --git a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java index 552f7e60..6c852dab 100644 --- a/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java +++ b/org.simantics.district.imports.ui/src/org/simantics/district/imports/ui/CSVImportWizardPage.java @@ -300,7 +300,7 @@ public class CSVImportWizardPage extends WizardPage { @Override public void modifyText(ModifyEvent e) { try { - double padding = Double.parseDouble(""); + double padding = Double.parseDouble(edgeConnectionPadding.getText()); model.setEdgePapping(padding); } catch (NumberFormatException ee) { // ignore @@ -967,7 +967,7 @@ public class CSVImportWizardPage extends WizardPage { headerIndexAndValues.clear(); try { - List rows = model.getRows(5); + List rows = model.getRows(5, false); for (int k = 0; k < rows.size(); k++) { CSVRecord row = rows.get(k); diff --git a/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java b/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java index 6b22746c..ca3f4be5 100644 --- a/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java +++ b/org.simantics.district.imports/src/org/simantics/district/imports/DistrictImportUtils.java @@ -11,6 +11,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.function.Function; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; @@ -50,10 +53,6 @@ public class DistrictImportUtils { return delimiters; } - public static List> readRows(Path source, char delimiter, boolean firstAsHeader, int amount) throws IOException { - return readRows(source, CSVFormat.newFormat(delimiter), firstAsHeader, amount); - } - public static List> readRows(Path source, CSVFormat format, boolean firstAsHeader, int amount) throws IOException { if (firstAsHeader) format = format.withFirstRecordAsHeader(); @@ -70,25 +69,31 @@ public class DistrictImportUtils { } } - public static List readRows(Path source, char delim, int rowAmount) throws IOException { + public static List readRows(Path source, char delim, boolean firstAsHeader, int rowAmount) throws IOException { List results = new ArrayList<>(); + AtomicInteger count = new AtomicInteger(0); + consumeCSV(source, delim, firstAsHeader, t -> { + results.add(t); + int current = count.incrementAndGet(); + return current < rowAmount; + }); + return results; + } + + public static void consumeCSV(Path source, char delim, boolean firstAsHeader, Function consumer) throws IOException { CSVFormat format = CSVFormat.newFormat(delim); + if (firstAsHeader) { + format = format.withFirstRecordAsHeader(); + } try (CSVParser parser = format.parse(Files.newBufferedReader(source))) { Iterator records = parser.iterator(); - int rows = 0; - if (rowAmount == -1) { - while (records.hasNext()) { - results.add(records.next()); - rows++; - } - } else { - while (rows < rowAmount && records.hasNext()) { - results.add(records.next()); - rows++; + while (records.hasNext()) { + Boolean cont = consumer.apply(records.next()); + if (!cont) { + break; } } } - return results; } diff --git a/org.simantics.district.network.ui/META-INF/MANIFEST.MF b/org.simantics.district.network.ui/META-INF/MANIFEST.MF index d2c3962a..42d812c2 100644 --- a/org.simantics.district.network.ui/META-INF/MANIFEST.MF +++ b/org.simantics.district.network.ui/META-INF/MANIFEST.MF @@ -32,7 +32,8 @@ Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.1.100.v20150 org.eclipse.jface, org.simantics.scl.osgi, org.simantics.district.route, - org.simantics.scenegraph.profile + org.simantics.scenegraph.profile, + org.simantics.district.geotools;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Import-Package: javax.annotation;version="1.0.0";resolution:=optional, javax.inject;version="1.0.0" diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DNEdgeBuilder.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DNEdgeBuilder.java index 0df72c51..7ed99c36 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DNEdgeBuilder.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DNEdgeBuilder.java @@ -4,6 +4,7 @@ import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Optional; import org.simantics.databoard.Bindings; import org.simantics.db.Resource; @@ -23,9 +24,16 @@ import org.simantics.district.network.DistrictNetworkUtil; import org.simantics.district.network.ontology.DistrictNetworkResource; import org.simantics.g2d.diagram.IDiagram; import org.simantics.layer0.Layer0; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.vividsolutions.jts.geom.Envelope; +import com.vividsolutions.jts.index.quadtree.Quadtree; public class DNEdgeBuilder { - + + private static final Logger LOGGER = LoggerFactory.getLogger(DNEdgeBuilder.class); + private Resource diagramResource; private IDiagram diagram; private GraphLayerManager glm; @@ -38,26 +46,38 @@ public class DNEdgeBuilder { glm = context.get(GraphSynchronizationHints.GRAPH_LAYER_MANAGER); } - public static Resource create(WriteGraph graph, Resource diagramResource, double[] start, double[] end, double padding) throws DatabaseException { + public static Optional create(WriteGraph graph, Resource diagramResource, double[] start, double startElevation, double[] end, double endElevation, double padding) throws DatabaseException { Collection vertices = graph.syncRequest(new ObjectsWithType(diagramResource, Layer0.getInstance(graph).ConsistsOf, DistrictNetworkResource.getInstance(graph).Vertex)); - List vv = new ArrayList<>(vertices.size()); + double halfPadding = padding / 2; + + Quadtree vv = new Quadtree(); for (Resource vertex : vertices) { - double[] existingCoords = graph.getRelatedValue2(vertex, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY); - vv.add(new ResourceVertex(vertex, existingCoords)); + double[] coords = graph.getRelatedValue2(vertex, DiagramResource.getInstance(graph).HasLocation, Bindings.DOUBLE_ARRAY); + double x1 = coords[0] - halfPadding; + double y1= coords[1] - halfPadding; + double x2 = coords[0] + halfPadding; + double y2= coords[1] + halfPadding; + Envelope e = new Envelope(x1, x2, y1, y2); + vv.insert(e, new ResourceVertex(vertex, coords, false)); } - return create(graph, vv, diagramResource, null, start, end, padding, false); + return create(graph, vv, diagramResource, null, start, startElevation, end, endElevation, padding, false); } - public static Resource create(WriteGraph graph, Collection vertices, Resource diagramResource, Resource mapping, double[] start, double[] end, double padding, boolean writeElevationToEdgeFromPoints) throws DatabaseException { + public static Optional create(WriteGraph graph, Quadtree vertices, Resource diagramResource, Resource mapping, double[] start, double startElevation, double[] end, double endElevation, double padding, boolean writeElevationToEdgeFromPoints) throws DatabaseException { DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); + + // 2. Add vertices + Resource startVertex = getOrCreateVertex(graph, diagramResource, vertices, start, startElevation, padding); + Resource endVertex = getOrCreateVertex(graph, diagramResource, vertices, end, endElevation, padding); + if (startVertex.equals(endVertex)) { + LOGGER.info("Circular edges are not supported, startVertex: {}, endVertex: {}", startVertex, endVertex); + return Optional.empty(); + } // 1. Get diagram edge to construct Resource edge = getOrCreateEdge(graph, diagramResource, mapping); - // 2. Add vertices - Resource startVertex = getOrCreateVertex(graph, diagramResource, vertices, start, padding, null); - Resource endVertex = getOrCreateVertex(graph, diagramResource, vertices, end, padding, startVertex); if (writeElevationToEdgeFromPoints) { graph.claimLiteral(edge, DN.Edge_HasElevation, calculateElevationFromVertices(graph, startVertex, endVertex), Bindings.DOUBLE); } @@ -76,7 +96,7 @@ public class DNEdgeBuilder { // }); // } // - return edge; + return Optional.of(edge); } private static double calculateElevationFromVertices(WriteGraph graph, Resource startVertex, Resource endVertex) throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException { DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); @@ -88,15 +108,15 @@ public class DNEdgeBuilder { return 0; } - public void create(WriteGraph graph, double[] start, double[] end, double padding) throws DatabaseException { + public void create(WriteGraph graph, double[] start, double startElevation, double[] end, double endElevation, double padding) throws DatabaseException { - Resource edge = create(graph, diagramResource, start, end, padding); + Optional edge = create(graph, diagramResource, start, startElevation, end, endElevation, padding); // 7. Put the element on all the currently active layers if possible. if (glm != null) { - putOnActiveLayer(graph, edge); + putOnActiveLayer(graph, edge.get()); } - Layer0Utils.addCommentMetadata(graph, "Added edge " + edge); + Layer0Utils.addCommentMetadata(graph, "Added edge " + edge.get()); graph.markUndoPoint(); } @@ -105,24 +125,32 @@ public class DNEdgeBuilder { glm.putElementOnVisibleLayers(diagram, graph, res); } - private static Resource getOrCreateVertex(WriteGraph graph, Resource diagramResource, Collection vertices, double[] coords, double padding, Resource startVertex) throws DatabaseException { + private static Resource getOrCreateVertex(WriteGraph graph, Resource diagramResource, Quadtree qtree, double[] coords, double elevation, double padding) throws DatabaseException { Resource vertex = null; double halfPadding = padding / 2; double maxDistance = Double.MAX_VALUE; + double x1 = coords[0] - halfPadding; + double y1= coords[1] - halfPadding; + double x2 = coords[0] + halfPadding; + double y2= coords[1] + halfPadding; + Envelope e = new Envelope(x1, x2, y1, y2); + + List result = qtree.query(e); + List vertices = (List) result; for (ResourceVertex vertx : vertices) { Rectangle2D existing = new Rectangle2D.Double(vertx.coords[0] - halfPadding, vertx.coords[1] - halfPadding, padding, padding); - Rectangle2D tobecreated = new Rectangle2D.Double(coords[0] - halfPadding, coords[1] - halfPadding, padding, padding); + Rectangle2D tobecreated = new Rectangle2D.Double(x1, y1, padding, padding); if (existing.intersects(tobecreated)) { double dist = Math.sqrt((Math.pow(coords[0] - vertx.coords[0], 2) + (Math.pow(coords[1] - vertx.coords[1], 2)))); - if (dist <= maxDistance && !vertx.vertex.equals(startVertex)) { + if (dist <= maxDistance) { vertex = vertx.vertex; maxDistance = dist; } } } if (vertex == null) { - vertex = DistrictNetworkUtil.createVertex(graph, diagramResource, coords); - vertices.add(new ResourceVertex(vertex, coords)); + vertex = DistrictNetworkUtil.createVertex(graph, diagramResource, coords, elevation); + qtree.insert(e, new ResourceVertex(vertex, coords, false)); } return vertex; } @@ -133,12 +161,14 @@ public class DNEdgeBuilder { public static class ResourceVertex { + final boolean isConsumer; final Resource vertex; final double[] coords; - public ResourceVertex(Resource vertex, double[] coords) { + public ResourceVertex(Resource vertex, double[] coords, boolean isConsumer) { this.vertex = vertex; this.coords = coords; + this.isConsumer = isConsumer; } } } diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java index c48693ac..08253bb2 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java @@ -39,9 +39,7 @@ public class DistrictNetworkNodeUtils { public static double calculateScaleRecip(AffineTransform tr) { int zoomLevel = MapScalingTransform.zoomLevel(tr); - double scale = GeometryUtils.getScale(tr); - double sqrt = Math.sqrt(scale / zoomLevel); - double viewScaleRecip = (sqrt / zoomLevel); - return viewScaleRecip; + double t = 1.0 / Math.sqrt(zoomLevel); + return t; } } diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java index 221ed714..929ad935 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java @@ -47,7 +47,7 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti private transient Rectangle2D rect; private transient AffineTransform symbolTransform; - private double nodeSize = 1; + private double nodeSize = 3; @Override public void init() { @@ -90,7 +90,7 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti if (NodeUtil.isSelected(this, 1)) { changeColor = true; g2d.setColor(SELECTION_COLOR); - BasicStroke ss = GeometryUtils.scaleStroke(STROKE, (float) (viewScaleRecip*0.5)); + BasicStroke ss = GeometryUtils.scaleStroke(STROKE, (float) (viewScaleRecip * nodeSize)); g2d.setStroke(ss); g2d.draw(toDraw); } diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java index 674702b8..b2121bf7 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java @@ -193,7 +193,7 @@ public class NetworkDrawingNode extends G2DNode { @Override public void perform(WriteGraph graph) throws DatabaseException { - builder.create(graph, startCoords, endCoords, padding); + builder.create(graph, startCoords, 0, endCoords, 0, padding); } }); diff --git a/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java b/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java index 24a77575..fde334f7 100644 --- a/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java +++ b/org.simantics.district.network/src/org/simantics/district/network/DistrictNetworkUtil.java @@ -63,18 +63,19 @@ public class DistrictNetworkUtil { return edge; } - public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords) throws DatabaseException { + public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords, double elevation) throws DatabaseException { Resource defaultVertexMapping = graph.getPossibleObject(composite, DistrictNetworkResource.getInstance(graph).VertexDefaultMapping); - return createVertex(graph, composite, coords, defaultVertexMapping); + return createVertex(graph, composite, coords, elevation, defaultVertexMapping); } - public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords, Resource mapping) throws DatabaseException { + public static Resource createVertex(WriteGraph graph, Resource composite, double[] coords, double elevation, Resource mapping) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); DistrictNetworkResource DN = DistrictNetworkResource.getInstance(graph); DiagramResource DIA = DiagramResource.getInstance(graph); Resource vertex = graph.newResource(); graph.claim(vertex, L0.InstanceOf, DN.Vertex); graph.claimLiteral(vertex, DIA.HasLocation, coords); + graph.claimLiteral(vertex, DN.Vertex_HasElevation, elevation, Bindings.DOUBLE); graph.claim(vertex, DN.HasMapping, null, mapping);