mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
Fixed the issue of disappearing components in some edge cases
This commit is contained in:
@@ -181,10 +181,26 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
maxY = p.getY();
|
||||
}
|
||||
}
|
||||
Rectangle2D rect = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
|
||||
double margin = getClipMargin();
|
||||
Rectangle2D rect = new Rectangle2D.Double(minX - margin, minY - margin,
|
||||
maxX - minX + 2 * margin, maxY - minY + 2 * margin);
|
||||
return !clip.intersects(rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Distance in pixels that the drawing may reach beyond the bounding box of the control points,
|
||||
* such as half the width of a stroke running through them. {@link #checkPointsClipped(Shape)}
|
||||
* widens the box by this much before testing it against the clip. The margin must stay positive,
|
||||
* because {@link Shape#intersects(Rectangle2D)} reports a box with no width or height as disjoint
|
||||
* from everything, which would hide a straight horizontal or vertical component whose control
|
||||
* points all lie outside the clip.
|
||||
*
|
||||
* @return margin around the control points.
|
||||
*/
|
||||
protected double getClipMargin() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public IDIYComponent<T> clone() throws CloneNotSupportedException {
|
||||
try {
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
@@ -172,6 +174,37 @@ public class AbstractCurvedComponentTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPointsClipped_keepsAStraightRunThatCrossesTheClipWithBothEndsOutside() {
|
||||
CurvedTestComponent horizontal = new CurvedTestComponent();
|
||||
horizontal.setPointCount(PointCount.TWO);
|
||||
horizontal.stretchBetween(new Point2D.Double(-100, 50), new Point2D.Double(300, 50));
|
||||
assertFalse(horizontal.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
|
||||
|
||||
CurvedTestComponent vertical = new CurvedTestComponent();
|
||||
vertical.setPointCount(PointCount.TWO);
|
||||
vertical.stretchBetween(new Point2D.Double(50, -100), new Point2D.Double(50, 300));
|
||||
assertFalse(vertical.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPointsClipped_skipsAStraightRunThatMissesTheClip() {
|
||||
CurvedTestComponent c = new CurvedTestComponent();
|
||||
c.setPointCount(PointCount.TWO);
|
||||
c.stretchBetween(new Point2D.Double(-100, 500), new Point2D.Double(300, 500));
|
||||
assertTrue(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkPointsClipped_keepsARunWhoseStrokeReachesIntoTheClip() {
|
||||
CurvedTestComponent c = new CurvedTestComponent();
|
||||
c.setPointCount(PointCount.TWO);
|
||||
c.stretchBetween(new Point2D.Double(-100, 105), new Point2D.Double(300, 105));
|
||||
assertTrue(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
|
||||
c.clipMargin = 10;
|
||||
assertFalse(c.checkPointsClipped(new Rectangle(0, 0, 200, 100)));
|
||||
}
|
||||
|
||||
private static void assertPoint(double x, double y, Point2D actual) {
|
||||
assertEquals(x, actual.getX(), DELTA);
|
||||
assertEquals(y, actual.getY(), DELTA);
|
||||
@@ -181,6 +214,13 @@ public class AbstractCurvedComponentTest {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private double clipMargin = 1;
|
||||
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return clipMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
|
||||
IDrawingObserver drawingObserver) {}
|
||||
|
||||
@@ -68,6 +68,11 @@ public class CurvedTrace extends AbstractCurvedComponent<Void> implements ILayer
|
||||
return COLOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return size.convertToPixels() / 2 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
|
||||
float thickness = (float) size.convertToPixels();
|
||||
|
||||
+10
-1
@@ -61,9 +61,18 @@ public class HookupWire extends AbstractCurvedComponent<AWG> implements IContinu
|
||||
return COLOR;
|
||||
}
|
||||
|
||||
private int getThickness() {
|
||||
return (int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)) - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return getThickness() / 2d + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
|
||||
int thickness = (int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)) - 1;
|
||||
int thickness = getThickness();
|
||||
Color curveColor =
|
||||
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
|
||||
: color;
|
||||
|
||||
+6
@@ -78,6 +78,12 @@ public class OrthogonalLine extends AbstractOrthogonalComponent<Void> implements
|
||||
g2d.draw(createIconPath(width, height));
|
||||
}
|
||||
|
||||
// an arrow head spreads one arrow size to either side of the end point it sits on
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return Math.max(getThickness().convertToPixels() / 2, getArrowSize().convertToPixels()) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
|
||||
IDrawingObserver drawingObserver) {
|
||||
|
||||
+10
-1
@@ -65,9 +65,18 @@ public class OrthogonalWire extends AbstractOrthogonalComponent<AWG> implements
|
||||
return COLOR;
|
||||
}
|
||||
|
||||
private int getThickness() {
|
||||
return (int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)) - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return getThickness() / 2d + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState, IDrawingObserver drawingObserver) {
|
||||
int thickness = (int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT)) - 1;
|
||||
int thickness = getThickness();
|
||||
Color curveColor =
|
||||
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
|
||||
: color;
|
||||
|
||||
+12
-3
@@ -83,12 +83,21 @@ public class TwistedWire extends AbstractCurvedComponent<Void> implements IConti
|
||||
return COLOR;
|
||||
}
|
||||
|
||||
private int getThickness() {
|
||||
return (int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT))
|
||||
- 1;
|
||||
}
|
||||
|
||||
// the two leads swing out to either side of the curve as they twist, see recalculate
|
||||
@Override
|
||||
protected double getClipMargin() {
|
||||
return getThickness() * 2 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
|
||||
IDrawingObserver drawingObserver) {
|
||||
int thickness =
|
||||
(int) (gauge.diameterIn() * Constants.PIXELS_PER_INCH * (1 + 2 * INSULATION_THICKNESS_PCT))
|
||||
- 1;
|
||||
int thickness = getThickness();
|
||||
Color curveColor1 =
|
||||
componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING
|
||||
? SELECTION_COLOR
|
||||
|
||||
Reference in New Issue
Block a user