mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 17:22:09 +10:00
reorg area calc code
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AreaUtils {
|
||||
|
||||
/**
|
||||
* Merges all areas that either overlap or are joined by connections.
|
||||
*
|
||||
* @param areas
|
||||
* @param connections
|
||||
* @return
|
||||
*/
|
||||
public static boolean crunchAreas(List<Area> areas, Set<Connection> connections) {
|
||||
boolean isChanged = false;
|
||||
|
||||
List<Area> newAreas = new ArrayList<Area>();
|
||||
List<Boolean> consumed = new ArrayList<Boolean>();
|
||||
for (int i = 0; i < areas.size(); i++) {
|
||||
consumed.add(false);
|
||||
}
|
||||
for (int i = 0; i < areas.size(); i++) {
|
||||
for (int j = i + 1; j < areas.size(); j++) {
|
||||
if (consumed.get(j))
|
||||
continue;
|
||||
Area a1 = areas.get(i);
|
||||
Area a2 = areas.get(j);
|
||||
Area intersection = null;
|
||||
if (a1.getBounds2D().intersects(a2.getBounds())) {
|
||||
intersection = new Area(a1);
|
||||
intersection.intersect(a2);
|
||||
}
|
||||
// if the two areas intersect, make a union and consume the second area
|
||||
if (intersection != null && !intersection.isEmpty()) {
|
||||
a1.add(a2);
|
||||
consumed.set(j, true);
|
||||
} else { // maybe there's a connection between them
|
||||
for (Connection p : connections) { // use getBounds to optimize the computation, don't get into complex math if not needed
|
||||
if ((a1.getBounds().contains(p.getP1()) && a2.getBounds().contains(p.getP2()) && a1.contains(p.getP1()) && a2.contains(p.getP2())) ||
|
||||
(a1.getBounds().contains(p.getP2()) && a2.getBounds().contains(p.getP1())) && a1.contains(p.getP2()) && a2.contains(p.getP1())) {
|
||||
a1.add(a2);
|
||||
consumed.set(j, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < areas.size(); i++)
|
||||
if (!consumed.get(i))
|
||||
newAreas.add(areas.get(i));
|
||||
else
|
||||
isChanged = true;
|
||||
|
||||
if (isChanged) {
|
||||
areas.clear();
|
||||
areas.addAll(newAreas);
|
||||
crunchAreas(areas, connections);
|
||||
}
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public static List<Area> tryAreaBreakout(Area a) {
|
||||
List<Area> toReturn = new ArrayList<Area>();
|
||||
Path2D p = null;
|
||||
PathIterator pathIterator = a.getPathIterator(null);
|
||||
while (!pathIterator.isDone()) {
|
||||
double[] coord = new double[6];
|
||||
int type = pathIterator.currentSegment(coord);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
if (p != null) {
|
||||
Area partArea = new Area(p);
|
||||
toReturn.add(partArea);
|
||||
}
|
||||
p = new Path2D.Double();
|
||||
p.moveTo(coord[0], coord[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
p.lineTo(coord[0], coord[1]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
p.curveTo(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
p.quadTo(coord[0], coord[1], coord[2], coord[3]);
|
||||
break;
|
||||
}
|
||||
pathIterator.next();
|
||||
}
|
||||
if (p != null) {
|
||||
Area partArea = new Area(p);
|
||||
toReturn.add(partArea);
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,9 @@
|
||||
package org.diylc.presenter;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.measures.Size;
|
||||
@@ -56,5 +58,24 @@ public class CalcUtils {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void expandConnections(Set<Connection> connections) {
|
||||
Set<Connection> toAdd = new HashSet<Connection>();
|
||||
for (Connection c1 : connections)
|
||||
for (Connection c2 : connections) {
|
||||
if (c1 == c2)
|
||||
continue;
|
||||
if (c1.getP1().distance(c2.getP1()) < DrawingManager.CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP2(), c2.getP2()));
|
||||
if (c1.getP1().distance(c2.getP2()) < DrawingManager.CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP2(), c2.getP1()));
|
||||
if (c1.getP2().distance(c2.getP1()) < DrawingManager.CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP1(), c2.getP2()));
|
||||
if (c1.getP2().distance(c2.getP2()) < DrawingManager.CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP1(), c2.getP1()));
|
||||
}
|
||||
if (connections.addAll(toAdd))
|
||||
expandConnections(connections);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -631,127 +629,15 @@ public class DrawingManager {
|
||||
for (int i = 0; i < preliminaryAreas.size(); i++) {
|
||||
Area a = preliminaryAreas.get(i);
|
||||
if (checkBreakout.get(i))
|
||||
areas.addAll(tryBreakout(a));
|
||||
areas.addAll(AreaUtils.tryAreaBreakout(a));
|
||||
else
|
||||
areas.add(a);
|
||||
}
|
||||
|
||||
expandConnections(connections);
|
||||
CalcUtils.expandConnections(connections);
|
||||
|
||||
crunchAreas(areas, connections);
|
||||
AreaUtils.crunchAreas(areas, connections);
|
||||
|
||||
return areas;
|
||||
}
|
||||
|
||||
public void expandConnections(Set<Connection> connections) {
|
||||
Set<Connection> toAdd = new HashSet<Connection>();
|
||||
for (Connection c1 : connections)
|
||||
for (Connection c2 : connections) {
|
||||
if (c1 == c2)
|
||||
continue;
|
||||
if (c1.getP1().distance(c2.getP1()) < CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP2(), c2.getP2()));
|
||||
if (c1.getP1().distance(c2.getP2()) < CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP2(), c2.getP1()));
|
||||
if (c1.getP2().distance(c2.getP1()) < CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP1(), c2.getP2()));
|
||||
if (c1.getP2().distance(c2.getP2()) < CONTROL_POINT_SIZE)
|
||||
toAdd.add(new Connection(c1.getP1(), c2.getP1()));
|
||||
}
|
||||
if (connections.addAll(toAdd))
|
||||
expandConnections(connections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges all areas that either overlap or are joined by connections.
|
||||
*
|
||||
* @param areas
|
||||
* @param connections
|
||||
* @return
|
||||
*/
|
||||
private boolean crunchAreas(List<Area> areas, Set<Connection> connections) {
|
||||
boolean isChanged = false;
|
||||
|
||||
List<Area> newAreas = new ArrayList<Area>();
|
||||
List<Boolean> consumed = new ArrayList<Boolean>();
|
||||
for (int i = 0; i < areas.size(); i++) {
|
||||
consumed.add(false);
|
||||
}
|
||||
for (int i = 0; i < areas.size(); i++) {
|
||||
for (int j = i + 1; j < areas.size(); j++) {
|
||||
if (consumed.get(j))
|
||||
continue;
|
||||
Area a1 = areas.get(i);
|
||||
Area a2 = areas.get(j);
|
||||
Area intersection = null;
|
||||
if (a1.getBounds2D().intersects(a2.getBounds())) {
|
||||
intersection = new Area(a1);
|
||||
intersection.intersect(a2);
|
||||
}
|
||||
// if the two areas intersect, make a union and consume the second area
|
||||
if (intersection != null && !intersection.isEmpty()) {
|
||||
a1.add(a2);
|
||||
consumed.set(j, true);
|
||||
} else { // maybe there's a connection between them
|
||||
for (Connection p : connections) { // use getBounds to optimize the computation, don't get into complex math if not needed
|
||||
if ((a1.getBounds().contains(p.getP1()) && a2.getBounds().contains(p.getP2()) && a1.contains(p.getP1()) && a2.contains(p.getP2())) ||
|
||||
(a1.getBounds().contains(p.getP2()) && a2.getBounds().contains(p.getP1())) && a1.contains(p.getP2()) && a2.contains(p.getP1())) {
|
||||
a1.add(a2);
|
||||
consumed.set(j, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < areas.size(); i++)
|
||||
if (!consumed.get(i))
|
||||
newAreas.add(areas.get(i));
|
||||
else
|
||||
isChanged = true;
|
||||
|
||||
if (isChanged) {
|
||||
areas.clear();
|
||||
areas.addAll(newAreas);
|
||||
crunchAreas(areas, connections);
|
||||
}
|
||||
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
private List<Area> tryBreakout(Area a) {
|
||||
List<Area> toReturn = new ArrayList<Area>();
|
||||
Path2D p = null;
|
||||
PathIterator pathIterator = a.getPathIterator(null);
|
||||
while (!pathIterator.isDone()) {
|
||||
double[] coord = new double[6];
|
||||
int type = pathIterator.currentSegment(coord);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
if (p != null) {
|
||||
Area partArea = new Area(p);
|
||||
toReturn.add(partArea);
|
||||
}
|
||||
p = new Path2D.Double();
|
||||
p.moveTo(coord[0], coord[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
p.lineTo(coord[0], coord[1]);
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
p.curveTo(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]);
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
p.quadTo(coord[0], coord[1], coord[2], coord[3]);
|
||||
break;
|
||||
}
|
||||
pathIterator.next();
|
||||
}
|
||||
if (p != null) {
|
||||
Area partArea = new Area(p);
|
||||
toReturn.add(partArea);
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3141,7 +3141,7 @@ public class Presenter implements IPlugInPort {
|
||||
}
|
||||
}
|
||||
|
||||
drawingManager.expandConnections(connections);
|
||||
CalcUtils.expandConnections(connections);
|
||||
|
||||
return new ArrayList<Connection>(connections);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user