package org.simantics.district.region; import java.awt.Shape; import java.awt.geom.FlatteningPathIterator; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; 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.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.QueryIndexUtils; import org.simantics.db.layer0.request.PossibleActiveModel; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.district.region.ontology.DiagramRegionsResource; import org.simantics.layer0.Layer0; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class DiagramRegions { private static final Logger LOGGER = LoggerFactory.getLogger(DiagramRegions.class); public static Resource createRegionForDiagram(WriteGraph graph, Resource diagram, String label, double[] coordinates) throws DatabaseException { if (coordinates == null || coordinates.length < 6 || coordinates.length % 2 != 0) throw new IllegalArgumentException("Provided coordinates are not valid : " + Arrays.toString(coordinates)); Path2D path = new Path2D.Double(); double startX = coordinates[0]; double startY = coordinates[1]; path.moveTo(startX, startY); for (int i = 2; i < coordinates.length; i++) path.lineTo(coordinates[i], coordinates[++i]); path.closePath(); // might not be needed DiagramRegionsResource DRR = DiagramRegionsResource.getInstance(graph); Layer0 L0 = Layer0.getInstance(graph); Resource region = graph.newResource(); graph.claim(region, L0.InstanceOf, DRR.Region); graph.claim(diagram, DRR.hasRegion, region); graph.claim(region, DRR.regionOf, diagram); graph.claimLiteral(region, L0.HasName, UUID.randomUUID().toString(), Bindings.STRING); graph.claimLiteral(region, L0.HasLabel, label, Bindings.STRING); graph.claimLiteral(region, DRR.Region_area, coordinates, Bindings.DOUBLE_ARRAY); if (LOGGER.isDebugEnabled()) LOGGER.debug("Created region for diagram {} with label {} and area {}", diagram, label, Arrays.toString(coordinates)); return region; } public static void removeRegion(WriteGraph graph, Resource region) throws DatabaseException { RemoverUtil.remove(graph, region); } public static class DiagramRegion { private Resource resource; private String label; private Shape shape; public DiagramRegion(Resource resource, String label, Shape coordinatesToShape) { this.resource = resource; this.label = label; this.shape = coordinatesToShape; } public Resource getResource() { return resource; } public String getLabel() { return label; } public Shape getShape() { return shape; } } public static Collection findRegions(ReadGraph graph, Resource model) throws DatabaseException { List diagrams = QueryIndexUtils.searchByType(graph, model, DiagramResource.getInstance(graph).Diagram); Set regions = new HashSet<>(); Layer0 L0 = Layer0.getInstance(graph); for (Resource diagram : diagrams) { Collection region = graph.getObjects(diagram, DiagramRegionsResource.getInstance(graph).hasRegion); for (Resource r : region) { String label = graph.getRelatedValue(r, L0.HasLabel, Bindings.STRING); Shape coordinatesToShape = DiagramRegions.coordinatesToShape(graph, r); regions.add(new DiagramRegion(r, label, coordinatesToShape)); } } return regions; } public static class DiagramRegionsRequest extends UniqueRead> { @Override public Collection perform(ReadGraph graph) throws DatabaseException { return findRegions(graph, graph.syncRequest(new PossibleActiveModel(Simantics.getProjectResource()))); } } public static Shape coordinatesToShape(ReadGraph graph, Resource region) throws DatabaseException { DiagramRegionsResource DRR = DiagramRegionsResource.getInstance(graph); double[] coordinates = graph.getRelatedValue(region, DRR.Region_area, Bindings.DOUBLE_ARRAY); Path2D path = new Path2D.Double(); double startX = coordinates[0]; double startY = coordinates[1]; path.moveTo(startX, startY); for (int i = 2; i < coordinates.length; i++) path.lineTo(coordinates[i], coordinates[++i]); path.closePath(); // might not be needed return path; } public static double[] shapeToCoordinates(Shape shape) { PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), 1); double points[] = new double[6]; double moveX = 0, moveY = 0; double thisX = 0, thisY = 0; int type = 0; List coords = new ArrayList<>(); // float factor = 1; while (!it.isDone()) { type = it.currentSegment(points); switch (type) { case PathIterator.SEG_MOVETO: moveX = points[0]; moveY = points[1]; coords.add(moveX); coords.add(moveY); break; case PathIterator.SEG_CLOSE: points[0] = moveX; points[1] = moveY; // Fall into.... case PathIterator.SEG_LINETO: thisX = points[0]; thisY = points[1]; coords.add(thisX); coords.add(thisY); break; } it.next(); } double[] finalCoords = new double[coords.size()]; for (int i = 0; i < coords.size(); i++) { double d = coords.get(i); finalCoords[i] = d; } return finalCoords; } public static Resource getDiagramForRegion(ReadGraph graph, Resource region) throws DatabaseException { DiagramRegionsResource DRR = DiagramRegionsResource.getInstance(graph); Resource diagram = graph.getSingleObject(region, DRR.regionOf); return diagram; } }