process shape outline

This commit is contained in:
bancika
2011-01-09 12:16:53 +00:00
parent 37a74f7918
commit 6a80bcdbe6
4 changed files with 143 additions and 22 deletions
@@ -1,7 +1,10 @@
<map> <map>
<entry> <entry>
<string>defaults</string> <string>default.org.diylc.components.passive.Resistor:Value</string>
<map/> <org.diylc.core.measures.Resistance>
<value>100.0</value>
<unit class="org.diylc.core.measures.ResistanceUnit">K</unit>
</org.diylc.core.measures.Resistance>
</entry> </entry>
<entry> <entry>
<string>lastPath</string> <string>lastPath</string>
@@ -11,4 +14,11 @@
<string>metric</string> <string>metric</string>
<boolean>true</boolean> <boolean>true</boolean>
</entry> </entry>
<entry>
<string>default.org.diylc.components.passive.AxialFilmCapacitor:Width</string>
<org.diylc.core.measures.Size>
<value>0.7</value>
<unit class="org.diylc.core.measures.SizeUnit">in</unit>
</org.diylc.core.measures.Size>
</entry>
</map> </map>
@@ -21,7 +21,12 @@ import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D; import java.awt.geom.Arc2D;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@@ -45,6 +50,9 @@ import java.util.Map;
class G2DWrapper extends Graphics2D { class G2DWrapper extends Graphics2D {
public static int LINE_SENSITIVITY_MARGIN = 2; public static int LINE_SENSITIVITY_MARGIN = 2;
public static int CURVE_SENSITIVITY = 10;
private boolean drawingComponent = false;
private Graphics2D canvasGraphics; private Graphics2D canvasGraphics;
private Stroke originalStroke; private Stroke originalStroke;
@@ -63,13 +71,15 @@ class G2DWrapper extends Graphics2D {
public G2DWrapper(Graphics2D canvasGraphics) { public G2DWrapper(Graphics2D canvasGraphics) {
super(); super();
this.canvasGraphics = canvasGraphics; this.canvasGraphics = canvasGraphics;
startedDrawingComponent(); currentArea = new Area();
currentTx = new AffineTransform();
} }
/** /**
* Clears out the current area and caches canvas settings. * Clears out the current area and caches canvas settings.
*/ */
public void startedDrawingComponent() { public void startedDrawingComponent() {
drawingComponent = true;
currentArea = new Area(); currentArea = new Area();
originalStroke = canvasGraphics.getStroke(); originalStroke = canvasGraphics.getStroke();
originalColor = canvasGraphics.getColor(); originalColor = canvasGraphics.getColor();
@@ -86,6 +96,7 @@ class G2DWrapper extends Graphics2D {
* @return * @return
*/ */
public Area finishedDrawingComponent() { public Area finishedDrawingComponent() {
drawingComponent = false;
canvasGraphics.setStroke(originalStroke); canvasGraphics.setStroke(originalStroke);
canvasGraphics.setColor(originalColor); canvasGraphics.setColor(originalColor);
canvasGraphics.setTransform(originalTx); canvasGraphics.setTransform(originalTx);
@@ -94,12 +105,120 @@ class G2DWrapper extends Graphics2D {
return currentArea; return currentArea;
} }
/**
* Appends shape interior to the current component area.
*
* @param s
*/
private void appendShape(Shape s) { private void appendShape(Shape s) {
if (!drawingComponent) {
return;
}
Area area = new Area(s); Area area = new Area(s);
area.transform(currentTx); area.transform(currentTx);
currentArea.add(area); currentArea.add(area);
} }
/**
* Appends shape outline to the current component area.
*
* @param s
*/
private void appendShapeOutline(Shape s) {
if (!drawingComponent) {
return;
}
PathIterator pathIterator = s.getPathIterator(null);
double thickness;
if (getStroke() instanceof BasicStroke) {
thickness = ((BasicStroke) getStroke()).getLineWidth() + 2 * LINE_SENSITIVITY_MARGIN;
} else {
thickness = 2 * LINE_SENSITIVITY_MARGIN;
}
Point2D prevPoint = null;
while (!pathIterator.isDone()) {
double[] coord = new double[6];
int type = pathIterator.currentSegment(coord);
switch (type) {
case PathIterator.SEG_MOVETO:
prevPoint = new Point2D.Double(coord[0], coord[1]);
break;
case PathIterator.SEG_LINETO:
// Represent straight line with a rectangle.
Point2D nextPoint = new Point2D.Double(coord[0], coord[1]);
Double theta = Math.atan2(nextPoint.getY() - prevPoint.getY(), nextPoint.getX()
- prevPoint.getX());
double width = Math.sqrt(Math.pow(nextPoint.getX() - prevPoint.getX(), 2)
+ Math.pow(nextPoint.getY() - prevPoint.getY(), 2));
double midX = (prevPoint.getX() + nextPoint.getX()) / 2;
double midY = (prevPoint.getY() + nextPoint.getY()) / 2;
Rectangle2D rect = new Rectangle2D.Double(midX - width / 2, midY - thickness / 2,
width, thickness);
Area area = new Area(rect);
area.transform(AffineTransform.getRotateInstance(theta, midX, midY));
appendShape(area);
// Set the prev point to line end
prevPoint = nextPoint;
break;
case PathIterator.SEG_CUBICTO:
CubicCurve2D cubicCurve = new CubicCurve2D.Double(prevPoint.getX(), prevPoint
.getY(), coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]);
addCubicCurveArea(cubicCurve);
prevPoint = new Point2D.Double(coord[4], coord[5]);
break;
case PathIterator.SEG_QUADTO:
QuadCurve2D quadCurve = new QuadCurve2D.Double(prevPoint.getX(), prevPoint.getY(),
coord[0], coord[1], coord[2], coord[3]);
addQuadCurveArea(quadCurve);
prevPoint = new Point2D.Double(coord[3], coord[3]);
break;
}
pathIterator.next();
}
}
/**
* Adds a cubic curve to the component area. It uses subdivision to
* approximate the curve with a series of straight lines.
*
* @param curve
*/
private void addCubicCurveArea(CubicCurve2D curve) {
double d = curve.getP1().distance(curve.getP2());
// When end points are close enough, approximate the curve with a
// straight line.
if (d < CURVE_SENSITIVITY) {
appendShapeOutline(new Line2D.Double(curve.getP1(), curve.getP2()));
} else {
CubicCurve2D leftSubcurve = new CubicCurve2D.Double();
CubicCurve2D rightSubcurve = new CubicCurve2D.Double();
curve.subdivide(leftSubcurve, rightSubcurve);
addCubicCurveArea(leftSubcurve);
addCubicCurveArea(rightSubcurve);
}
}
/**
* Adds a quad curve to the component area. It uses subdivision to
* approximate the curve with a series of straight lines.
*
* @param curve
*/
private void addQuadCurveArea(QuadCurve2D curve) {
double d = curve.getP1().distance(curve.getP2());
// When end points are close enough, approximate the curve with a
// straight line.
if (d < CURVE_SENSITIVITY) {
appendShapeOutline(new Line2D.Double(curve.getP1(), curve.getP2()));
} else {
QuadCurve2D leftSubcurve = new QuadCurve2D.Double();
QuadCurve2D rightSubcurve = new QuadCurve2D.Double();
curve.subdivide(leftSubcurve, rightSubcurve);
addQuadCurveArea(leftSubcurve);
addQuadCurveArea(rightSubcurve);
}
}
@Override @Override
public void addRenderingHints(Map<?, ?> hints) { public void addRenderingHints(Map<?, ?> hints) {
canvasGraphics.addRenderingHints(hints); canvasGraphics.addRenderingHints(hints);
@@ -113,7 +232,7 @@ class G2DWrapper extends Graphics2D {
@Override @Override
public void draw(Shape s) { public void draw(Shape s) {
canvasGraphics.draw(s); canvasGraphics.draw(s);
appendShape(s); appendShapeOutline(s);
} }
@Override @Override
@@ -380,27 +499,13 @@ class G2DWrapper extends Graphics2D {
@Override @Override
public void drawLine(int x1, int y1, int x2, int y2) { public void drawLine(int x1, int y1, int x2, int y2) {
canvasGraphics.drawLine(x1, y1, x2, y2); canvasGraphics.drawLine(x1, y1, x2, y2);
Double theta = Math.atan2(y2 - y1, x2 - x1); appendShapeOutline(new Line2D.Double(x1, y1, x2, y2));
double width = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
double height;
if (getStroke() instanceof BasicStroke) {
height = ((BasicStroke) getStroke()).getLineWidth() + 2 * LINE_SENSITIVITY_MARGIN;
} else {
height = 2 * LINE_SENSITIVITY_MARGIN;
}
int midX = (x1 + x2) / 2;
int midY = (y1 + y2) / 2;
Rectangle2D rect = new Rectangle2D.Double(midX - width / 2, midY - height / 2, width,
height);
Area area = new Area(rect);
area.transform(AffineTransform.getRotateInstance(theta, midX, midY));
appendShape(area);
} }
@Override @Override
public void drawOval(int x, int y, int width, int height) { public void drawOval(int x, int y, int width, int height) {
canvasGraphics.drawOval(x, y, width, height); canvasGraphics.drawOval(x, y, width, height);
appendShape(new Ellipse2D.Double(x, y, width, height)); appendShapeOutline(new Ellipse2D.Double(x, y, width, height));
} }
@Override @Override
@@ -416,7 +521,7 @@ class G2DWrapper extends Graphics2D {
@Override @Override
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight); canvasGraphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
appendShape(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight)); appendShapeOutline(new RoundRectangle2D.Double(x, y, width, height, arcWidth, arcHeight));
} }
@Override @Override
@@ -440,7 +545,7 @@ class G2DWrapper extends Graphics2D {
@Override @Override
public void drawRect(int x, int y, int width, int height) { public void drawRect(int x, int y, int width, int height) {
canvasGraphics.drawRect(x, y, width, height); canvasGraphics.drawRect(x, y, width, height);
appendShape(new Rectangle(x, y, width, height)); appendShapeOutline(new Rectangle(x, y, width, height));
} }
@Override @Override
@@ -728,6 +728,9 @@ public class Presenter implements IPlugInPort {
// Add it to the project taking z-order into account. // Add it to the project taking z-order into account.
addComponent(component, componentType); addComponent(component, componentType);
// Select the new component
selectedComponents.clear();
selectedComponents.add(component);
// Translate them to the desired location. // Translate them to the desired location.
if (point != null) { if (point != null) {
@@ -763,6 +766,9 @@ public class Presenter implements IPlugInPort {
messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner
.deepClone(currentProject), "Add " + componentType.getName()); .deepClone(currentProject), "Add " + componentType.getName());
} }
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents);
messageDispatcher.dispatchMessage(EventType.SELECTION_SIZE_CHANGED,
calculateSelectionDimension());
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }