Bläddra i källkod

Merge remote-tracking branch 'origin/develop' into develop

lijie 2 år sedan
förälder
incheckning
14a3558bd8

+ 27 - 14
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/DiagramBuilder.java

@@ -123,10 +123,8 @@ public class DiagramBuilder {
 		initNode(node, DiagramBuilder.getName(obj), con);
 
 		Legend legend = findLegend(node.getObjClassCode(), obj);
-		if(legend != null) {
-			node.setLegendId(legend.getId());
-			node.setLegend(legend);
-		}
+		node.setLegendId(legend.getId());
+		node.setLegend(legend);
 
 		equipMap.put(node.getObjId(), node);
 	}
@@ -169,9 +167,12 @@ public class DiagramBuilder {
 				pn = newPackNode(classCode, con, getTypeName(classCode));
 		}
 
-		if(legend == null)
-			legend = findLegend(classCode, null);
-		if(legend != null) {
+		if (pn.getLegend() == null) {
+			if(con.getEquipPack().getLegendId() != null)
+				legend = dataStrategy.getLegend(con.getEquipPack().getLegendId(), classCode.substring(0, 4));
+			if(legend == null)
+				legend = findLegend(classCode, null);
+
 			pn.setLegendId(legend.getId());
 			pn.setLegend(legend);
 		}
@@ -276,10 +277,7 @@ public class DiagramBuilder {
 		}
 
 		//返回一个缺省图例
-		Legend l = new Legend();
-		l.setWidth(100);
-		l.setHeight(100);
-		return l;
+		return emptyLegend();
 	}
 	
 	public void buildLines(List<ObjectNode> optionalRels){
@@ -375,7 +373,7 @@ public class DiagramBuilder {
 								anchor1 = a;
 						} else {
 							//完全匹配
-							if(CollUtil.isEmpty(a.getLines())) {
+							if(CollUtil.isEmpty(a.getLines())) { //优先每个锚点只有一条连线
 								anchor = a;
 								break;
 							} else if(anchor == null)
@@ -415,8 +413,8 @@ public class DiagramBuilder {
 	}
 
 	private void markAnchorLine(ConnectPoint p, Line line){
-		if (StrUtil.isNotBlank(p.getAnchorCode())) {
-			EquipmentNode en = (EquipmentNode) p.getHostObj();
+		EquipmentNode en = p.getEquipmentNode();
+		if (en != null) {
 			Anchor anchor = en.getLegend().getAnchor(p.getAnchorCode());
 			anchor.addLine(line);
 		}
@@ -430,6 +428,14 @@ public class DiagramBuilder {
 		return refRelTypes;
 	}
 
+	public Diagram getDiagram() {
+		return diagram;
+	}
+
+	public DataStrategy getDataStrategy() {
+		return dataStrategy;
+	}
+
 	public static String getName(ObjectNode obj){
 		String name = null;
 		if(obj.get("localName") != null)
@@ -445,4 +451,11 @@ public class DiagramBuilder {
 		return null;
 	}
 
+	public static Legend emptyLegend(){
+		Legend l = new Legend();
+		l.setWidth(100);
+		l.setHeight(100);
+		return l;
+	}
+
 }

+ 2 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/DiagramDataLoader.java

@@ -65,6 +65,8 @@ public class DiagramDataLoader {
 
 				if(en.getLegendId() != null)
 					en.setLegend(dataStrategy.getLegend(en.getLegendId(), en.getObjSystemCode()));
+				else
+					en.setLegend(DiagramBuilder.emptyLegend());
 			}
 
 			if(obj != null)

+ 37 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/line/Block.java

@@ -0,0 +1,37 @@
+package com.persagy.adm.diagram.core.line;
+
+import com.persagy.adm.diagram.core.model.DiagramNode;
+import com.persagy.adm.diagram.core.model.base.XY;
+import com.persagy.adm.diagram.core.util.GeomUtil;
+import org.locationtech.jts.geom.Polygon;
+
+public class Block {
+
+	private DiagramNode node;
+
+	private XY location;
+
+	private XY size;
+
+	private Polygon polygon;
+
+	public Block(DiagramNode node) {
+		this.node = node;
+		this.location = node.locationToRoot();
+		this.size = node.getSize();
+		this.polygon = GeomUtil.getPolygon(location, size);
+	}
+
+	public XY getLocation() {
+		return location;
+	}
+
+	public XY getSize() {
+		return size;
+	}
+
+	public Polygon getPolygon() {
+		return polygon;
+	}
+
+}

+ 41 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/line/LineEnd.java

@@ -0,0 +1,41 @@
+package com.persagy.adm.diagram.core.line;
+
+import com.persagy.adm.diagram.core.model.base.XY;
+
+/**
+ * 连线的终点
+ */
+public class LineEnd {
+
+	/**
+	 * 与真正连接点的偏移量
+	 */
+	public static int offset = 5;
+
+	/**
+	 * 模式1,点(锚点)
+	 */
+	private XY point;
+
+	/**
+	 * 模式2,线段(干管)
+	 */
+	private XY[] line;
+
+	public XY getPoint() {
+		return point;
+	}
+
+	public void setPoint(XY point) {
+		this.point = point;
+	}
+
+	public XY[] getLine() {
+		return line;
+	}
+
+	public void setLine(XY[] line) {
+		this.line = line;
+	}
+
+}

+ 121 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/line/LineLayoutManager.java

@@ -0,0 +1,121 @@
+package com.persagy.adm.diagram.core.line;
+
+import com.persagy.adm.diagram.core.DiagramBuilder;
+import com.persagy.adm.diagram.core.model.ConnectPoint;
+import com.persagy.adm.diagram.core.model.DiagramNode;
+import com.persagy.adm.diagram.core.model.EquipmentNode;
+import com.persagy.adm.diagram.core.model.Line;
+import com.persagy.adm.diagram.core.model.base.XY;
+import com.persagy.adm.diagram.core.model.template.MainPipe;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 连线布局计算
+ */
+public class LineLayoutManager {
+
+	private DiagramBuilder diagramBuilder;
+
+	private List<Block> blocks = new ArrayList<>();
+
+	public LineLayoutManager(DiagramBuilder diagramBuilder) {
+		this.diagramBuilder = diagramBuilder;
+		initBlocks();
+	}
+
+	private void initBlocks(){
+		for(Object o : diagramBuilder.getEquipMap().values()){
+			if (o instanceof DiagramNode)
+				blocks.add(new Block((DiagramNode)o));
+		}
+	}
+
+	public void layout(Line line){
+		ConnectPoint p1 = line.getFrom();
+		ConnectPoint p2 = line.getTo();
+
+		boolean exchange = false;
+		if(p1.getEquipmentNode() == null) { //先计算点模型的终点
+			if(p2.getEquipmentNode() == null)
+				throw new RuntimeException("do not support 2 main pipe connect");
+
+			ConnectPoint tmp = p2;
+			p2 = p1;
+			p1 = tmp;
+
+			exchange = true;
+		}
+
+		LineEnd[] arr = buildLineEnd(p1, p2);
+
+	}
+
+	private LineEnd[] buildLineEnd(ConnectPoint p1, ConnectPoint p2) {
+		LineEnd[] arr = new LineEnd[2];
+
+		arr[0] = new LineEnd();
+		arr[0].setPoint(anchorEmerge(p1));
+
+		if(p2.getHostObj() instanceof EquipmentNode) {
+			arr[1] = new LineEnd();
+			arr[1].setPoint(anchorEmerge(p2));
+		} else if (p2.getHostObj() instanceof MainPipe) {
+			MainPipe mp = (MainPipe) p2.getHostObj();
+			XY[] nearLine = null;
+			double min = Double.MAX_VALUE;
+			for(List<XY> list : mp.getLocationPath()) {
+				XY pre = null;
+				for(XY xy : list) {
+					if(pre != null) {
+						XY[] line = new XY[]{pre, xy};
+						double distance = distance(line, p1.getLocation());
+						if(distance < min){
+							min = distance;
+							nearLine = line;
+						}
+					}
+					pre = xy;
+				}
+			}
+			arr[1] = new LineEnd();
+			arr[1].setLine(nearLine);
+		}
+
+		return arr;
+	}
+
+	/**
+	 * 就算点和线段的最短距离
+	 */
+	private double distance(XY[] line, XY xy){
+		return 0; //TODO
+	}
+
+	/**
+	 * 锚点出线
+	 */
+	private XY anchorEmerge(ConnectPoint point){
+		if(point.getLocation() == null)
+			point.layout();
+
+		XY xy = new XY(point.getLocation());
+		switch (point.getAnchorCode().charAt(0)) {
+			case 'T':
+				xy.y -= LineEnd.offset;
+				break;
+			case 'B':
+				xy.y += LineEnd.offset;
+				break;
+			case 'L':
+				xy.x -= LineEnd.offset;
+				break;
+			case 'R':
+				xy.x += LineEnd.offset;
+				break;
+		}
+		return xy;
+	}
+
+}

+ 7 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/line/PathBuilder.java

@@ -0,0 +1,7 @@
+package com.persagy.adm.diagram.core.line;
+
+public class PathBuilder {
+
+
+
+}

+ 25 - 5
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/ConnectPoint.java

@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.model.base.XY;
 import com.persagy.adm.diagram.core.model.legend.Anchor;
+import com.persagy.adm.diagram.core.model.template.MainPipe;
 
 /**
  * 线和图例的连接点
@@ -47,12 +48,31 @@ public class ConnectPoint {
 	@JsonIgnore
 	private Object hostObj;
 
-	public void layout(){
+	/**
+	 * 如果hostObj为EquipmentNode类型,则返回
+	 */
+	public EquipmentNode getEquipmentNode(){
+		if(hostObj instanceof EquipmentNode)
+			return (EquipmentNode) hostObj;
+		return null;
+	}
+
+	/**
+	 * 如果hostObj为MainPipe类型,则返回
+	 */
+	public MainPipe getMainPipe(){
+		if(hostObj instanceof MainPipe)
+			return (MainPipe) hostObj;
+		return null;
+	}
+
+	public void layout() {
 		if(hostObj instanceof EquipmentNode) {
-			XY pos = ((EquipmentNode) hostObj).getAnchorLocations().get(anchorCode);
-			location = ((EquipmentNode) hostObj).locationToRoot();
-			location.x += pos.x;
-			location.y += pos.y;
+			EquipmentNode en = (EquipmentNode)hostObj;
+			location = en.locationToRoot();
+			XY anchorLocation = en.getAnchorLocations().get(anchorCode);
+			location.x += anchorLocation.x;
+			location.y += anchorLocation.y;
 		}
 	}
 

+ 3 - 1
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/Diagram.java

@@ -3,6 +3,7 @@ package com.persagy.adm.diagram.core.model;
 import cn.hutool.core.util.StrUtil;
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.DiagramBuilder;
+import com.persagy.adm.diagram.core.line.LineLayoutManager;
 import com.persagy.adm.diagram.core.model.base.Container;
 import com.persagy.adm.diagram.core.model.base.XY;
 import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
@@ -113,8 +114,9 @@ public class Diagram {
 	public void layout(DiagramBuilder builder, boolean absoluteLocation){
 		template.layout(new XY(0, 0));
 
+		LineLayoutManager lineLayoutManager = new LineLayoutManager(builder);
 		for(Line line : lines) {
-			line.layout(builder);
+			line.layout(lineLayoutManager);
 		}
 
 		if(absoluteLocation) {

+ 4 - 3
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/Line.java

@@ -2,6 +2,7 @@ package com.persagy.adm.diagram.core.model;
 
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.DiagramBuilder;
+import com.persagy.adm.diagram.core.line.LineLayoutManager;
 import com.persagy.adm.diagram.core.model.base.XY;
 
 import java.util.ArrayList;
@@ -53,11 +54,11 @@ public class Line extends AbstractLine {
 
 	@Override
 	public void layout(Object layoutContext) {
-		DiagramBuilder builder = (DiagramBuilder) layoutContext;
+		LineLayoutManager layoutManager = (LineLayoutManager) layoutContext;
+		layoutManager.layout(this);
 
+		//test code TODO
 		locationPath = new ArrayList<>();
-		from.layout();
-		to.layout();
 		if(from.getLocation() != null && to.getLocation() != null) {
 			locationPath.add(from.getLocation());
 			locationPath.add(to.getLocation());

+ 214 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/util/GeomUtil.java

@@ -0,0 +1,214 @@
+package com.persagy.adm.diagram.core.util;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.CaseInsensitiveMap;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.persagy.adm.diagram.core.model.base.XY;
+import org.locationtech.jts.geom.*;
+import org.locationtech.jts.io.ParseException;
+import org.locationtech.jts.io.WKTReader;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class GeomUtil {
+
+	private static GeometryFactory geometryFactory = new GeometryFactory();
+
+	public static Polygon getPolygon(XY location, XY size) {
+		Coordinate[] cs = new Coordinate[5];
+		cs[0] = new Coordinate(location.x, location.y);
+		cs[1] = new Coordinate(location.x + size.x, location.y);
+		cs[2] = new Coordinate(location.x + size.x, location.y + size.y);
+		cs[3] = new Coordinate(location.x, location.y + size.y);
+		cs[4] = cs[0];
+		return geometryFactory.createPolygon(cs);
+	}
+
+	public static LineString getLine(XY[] points) {
+		Coordinate[] cs = new Coordinate[points.length];
+		for (int i = 0; i < cs.length; i++) {
+			cs[i] = new Coordinate(points[i].x, points[i].y);
+		}
+		return geometryFactory.createLineString(cs);
+	}
+
+	public Point getPoint(XY xy){
+		return geometryFactory.createPoint(new Coordinate(xy.x, xy.y));
+	}
+
+	public static Polygon[] getPolygon(ArrayNode arrayNode){
+		Polygon[] ps = new Polygon[arrayNode.size()];
+		for (int i = 0; i < ps.length; i++) {
+			ArrayNode arr = (ArrayNode) arrayNode.get(i);
+			ArrayNode shellArrNode = (ArrayNode) arr.get(0);
+			LinearRing shell = geometryFactory.createLinearRing(buildCoords(shellArrNode));
+			LinearRing[] holes = null;
+			if(arr.size() > 1) {
+				holes = new LinearRing[arr.size() - 1];
+				for (int n = 1; n < arr.size(); n++) {
+					holes[n - 1] = geometryFactory.createLinearRing(buildCoords((ArrayNode) arr.get(n)));
+				}
+			}
+			ps[i] = geometryFactory.createPolygon(shell, holes);
+		}
+		return ps;
+	}
+
+	private static Coordinate[] buildCoords(ArrayNode arrayNode){
+		Coordinate[] coords = new Coordinate[arrayNode.size()];
+		for (int i = 0; i < arrayNode.size(); i++) {
+			JsonNode pointNode = arrayNode.get(i);
+			coords[i] = new Coordinate(pointNode.get("x").asDouble(), pointNode.get("y").asDouble());
+		}
+		return coords;
+	}
+
+	public static boolean checkPolygon(ArrayList<ArrayList<ArrayList<CaseInsensitiveMap>>> outline){
+		if(CollUtil.isEmpty(outline))
+			return false;
+
+		try {
+			Polygon[] ps = new Polygon[outline.size()];
+			for (int i = 0; i < ps.length; i++) {
+				List space = (List) outline.get(i);
+				if(CollUtil.isEmpty(space))
+					return false;
+
+				List<Map> shellList = (List) space.get(0);
+				LinearRing shell = geometryFactory.createLinearRing(buildCoords(shellList));
+				LinearRing[] holes = null;
+				if(space.size() > 1) {
+					holes = new LinearRing[space.size() - 1];
+					for (int n = 1; n < space.size(); n++) {
+						holes[n - 1] = geometryFactory.createLinearRing(buildCoords((List<Map>) space.get(n)));
+					}
+				}
+				ps[i] = geometryFactory.createPolygon(shell, holes);
+			}
+		} catch (Exception e) {
+			return false;
+		}
+		return true;
+	}
+
+	private static Coordinate[] buildCoords(List<Map> list){
+		Coordinate[] coords = new Coordinate[list.size()];
+		for (int i = 0; i < list.size(); i++) {
+			Map point = list.get(i);
+			coords[i] = new Coordinate((Double) point.get("x"), (Double)point.get("y"));
+		}
+		return coords;
+	}
+
+	public static boolean checkPolygon(ArrayNode outline){
+		if(outline == null || outline.size() == 0)
+			return false;
+
+		try {
+			Polygon[] ps = new Polygon[outline.size()];
+			for (int i = 0; i < ps.length; i++) {
+				ArrayNode space = (ArrayNode) outline.get(i);
+				if(space == null || space.size() == 0)
+					return false;
+
+				ArrayNode shellList = (ArrayNode) space.get(0);
+				LinearRing shell = geometryFactory.createLinearRing(buildCoords(shellList));
+				LinearRing[] holes = null;
+				if(space.size() > 1) {
+					holes = new LinearRing[space.size() - 1];
+					for (int n = 1; n < space.size(); n++) {
+						holes[n - 1] = geometryFactory.createLinearRing(buildCoords((ArrayNode) space.get(n)));
+					}
+				}
+				ps[i] = geometryFactory.createPolygon(shell, holes);
+			}
+		} catch (Exception e) {
+			return false;
+		}
+		return true;
+	}
+
+
+	/**
+	 *  两个几何对象是否是重叠的
+	 * @return
+	 * @throws ParseException
+	 */
+	public boolean equalsGeo() throws ParseException {
+		WKTReader reader = new WKTReader( geometryFactory );
+		LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
+		LineString geometry2 = (LineString) reader.read("LINESTRING(5 0, 0 0)");
+		return geometry1.equals(geometry2);//true
+	}
+
+	/**
+	 * 几何对象没有交点(相邻)
+	 * @return
+	 * @throws ParseException
+	 */
+	public boolean disjointGeo() throws ParseException{
+		WKTReader reader = new WKTReader( geometryFactory );
+		LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
+		LineString geometry2 = (LineString) reader.read("LINESTRING(0 1, 0 2)");
+		return geometry1.disjoint(geometry2);
+	}
+
+	/**
+	 * 至少一个公共点(相交)
+	 * @return
+	 * @throws ParseException
+	 */
+	public boolean intersectsGeo() throws ParseException{
+		WKTReader reader = new WKTReader( geometryFactory );
+		LineString geometry1 = (LineString) reader.read("LINESTRING(0 0, 2 0, 5 0)");
+		LineString geometry2 = (LineString) reader.read("LINESTRING(0 0, 0 2)");
+		Geometry interPoint = geometry1.intersection(geometry2);//相交点
+		System.out.println(interPoint.toText());//输出 POINT (0 0)
+		return geometry1.intersects(geometry2);
+	}
+
+	/**
+	 * 判断以x,y为坐标的点point(x,y)是否在geometry表示的Polygon中
+	 * @param x
+	 * @param y
+	 * @param geometry wkt格式
+	 * @return
+	 */
+	public boolean withinGeo(double x,double y,String geometry) throws ParseException {
+
+		Coordinate coord = new Coordinate(x,y);
+		Point point = geometryFactory.createPoint( coord );
+
+		WKTReader reader = new WKTReader( geometryFactory );
+		Polygon polygon = (Polygon) reader.read(geometry);
+		return point.within(polygon);
+	}
+
+	public LinearRing createLinearRing(double[]... xys){
+		Coordinate[] coords = new Coordinate[xys.length];
+		for(int i=0;i<xys.length;i++){
+			coords[i] = new Coordinate(xys[i][0], xys[i][1]);
+		}
+		return geometryFactory.createLinearRing(coords);
+	}
+
+	public Polygon createPolygon(double[]... xys){
+		Coordinate[] coords = new Coordinate[xys.length];
+		for(int i=0;i<xys.length;i++){
+			coords[i] = new Coordinate(xys[i][0], xys[i][1]);
+		}
+		return geometryFactory.createPolygon(coords);
+	}
+
+	public LineString createLine(double[]... xys){
+		Coordinate[] coords = new Coordinate[xys.length];
+		for(int i=0;i<xys.length;i++){
+			coords[i] = new Coordinate(xys[i][0], xys[i][1]);
+		}
+		return geometryFactory.createLineString(coords);
+	}
+
+}

+ 9 - 5
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/util/GsonUtil.java

@@ -1,6 +1,7 @@
 package com.persagy.adm.diagram.core.util;
 
 import com.google.gson.*;
+import com.persagy.adm.diagram.core.model.DataPanelNode;
 import com.persagy.adm.diagram.core.model.DiagramNode;
 import com.persagy.adm.diagram.core.model.EquipmentNode;
 import com.persagy.adm.diagram.core.model.Label;
@@ -49,15 +50,18 @@ public class GsonUtil {
 
 		@Override
 		public IComponent deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
-			Class<? extends IComponent> target = Container.class;
-			if(Container.TYPE.equals(jsonElement.getAsJsonObject().get("compType").getAsString()))
+			Class<? extends IComponent> target = null;
+			String compType = jsonElement.getAsJsonObject().get("compType").getAsString();
+			if(Container.TYPE.equals(compType))
 				target = Container.class;
-			else if(EquipmentNode.TYPE.equals(jsonElement.getAsJsonObject().get("compType").getAsString()))
+			else if(EquipmentNode.TYPE.equals(compType))
 				target = EquipmentNode.class;
-			else if(PackNode.TYPE.equals(jsonElement.getAsJsonObject().get("compType").getAsString()))
+			else if(PackNode.TYPE.equals(compType))
 				target = PackNode.class;
-			else if(Label.TYPE.equals(jsonElement.getAsJsonObject().get("compType").getAsString()))
+			else if(Label.TYPE.equals(compType))
 				target = Label.class;
+			else if(DataPanelNode.TYPE.equals(compType))
+				target = DataPanelNode.class;
 			else {
 				//TODO 其他类型
 			}