From 6a80bcdbe667e23eddd04c6ac94ddb7cbff92e36 Mon Sep 17 00:00:00 2001 From: bancika Date: Sun, 9 Jan 2011 12:16:53 +0000 Subject: [PATCH] process shape outline --- .../DIYLC/config.xml | 14 +- .../DIYLC/library/main.jar | Bin 224247 -> 227979 bytes .../src/org/diylc/presenter/G2DWrapper.java | 145 +++++++++++++++--- .../src/org/diylc/presenter/Presenter.java | 6 + 4 files changed, 143 insertions(+), 22 deletions(-) diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/config.xml b/ diy-layout-creator --username bancika@gmail.com/DIYLC/config.xml index f9e9b3ae..02f4b9f6 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/config.xml +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/config.xml @@ -1,7 +1,10 @@ - defaults - + default.org.diylc.components.passive.Resistor:Value + + 100.0 + K + lastPath @@ -11,4 +14,11 @@ metric true + + default.org.diylc.components.passive.AxialFilmCapacitor:Width + + 0.7 + in + + \ No newline at end of file diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar b/ diy-layout-creator --username bancika@gmail.com/DIYLC/library/main.jar index c1c543c0866dcc05170e642fe63541bac98f4a54..7adb3092057a9771089205e02e129f14bb6b9f12 100644 GIT binary patch delta 6115 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%0D`< N{-SV?zby;t{{e$TbZ7to delta 2513 zcmV;?2`=`F^$qve4Gd6A0|XQR2mlBGuL!XW@G6mO5R(imG=EcFa~m}jy>jd%O`XAkje@j#!870r&ohs zU+5XiGYT@@w|{nx)jYHf!6OmX>c3R~zhhJ~LQCFl32kJoeyZ0Pu~&@dtFbbcE8F7T zfhf@M#~4j-NG0tiqp5PG#VB8mBQZx)bfHLdbe_@0hE(G9ptmdZk9@Z)7+q?_Ap&rO z!8tMJZAThLtBo_)x6Wub()^$fJEQC6#vb420Y9+8j(_I;jttFOZM|N1NlmraB1Ts- zJs1@ZWMn%ivyN&yLbf}QVYV&o&qMoixiXQJ7C}#NGtj~WP5HY3#avDFwFtQth;!|S zfwHnETGB|=wxv{TxrLahZ)uoAm#cO##;iNRmWy$bQWC@Nn@rDn&Nm-bQu_@8`@BHg8XXkPjFeWf)+PmtPV zK@Rn-NcZUz^raaObSPd(H)7|9bMwHtL*}MzD}Qd$MMl-^sXO_ZY@|ipM4=DUQ^Loc z4@S_MFrk)x>s8Gw-b4K9VP@Fyf$cbT7q>N6(scR$a?{3pzsCDAM3ddLv}1jU_gFvr zBp|)?&odOS!T7xvZ{%+%KSD6XlJ12h6`+0wv84_p~uCP25lLQDRh z(Fb%D2)Db2-IUMs2G$R~=SKHop!~b;TqfF#yU_1@^ zEE5@^JEtL^XCfb-0l9q~S=vG~KF4V&yTjibO~HFwOH(jUk@LX&^u+|Qf|F~*xs}zw z>G6Adn(oyIj5dGicVE%EUpIWiZ^7d^hHKN%*Yu5{E!s9zrJ4c$TSG7Y15ir`2nrNc zOs94O000vRkzX8>nmjgt8$}fU1_&Wx3lv)Vw57FZl0LQ~wb~$-CT$6g&^9y`AJt(q zBm>EA+}(iqS7~2(^c;^r`$u`aGg(5|gh$TF?#!M0-TTeG-^~8|-=BX2m_j3p9)^VD zmd%pfu3Dz$)as5cY~M4b?F-j(Y+G0~TXwl6qUd8VyL!*9dOo>-_<6xgqLj_8WOmmW zMm*t4UM&jOlaBo&mt|lJ3@0*5V;pCrI710_zACrNX4Yw}R)v9cIL{E>RNGlvV>q42 zCi7vhbPN}9DT)smCJsyVg2)-Tj0uLGT8-iAp@mT1={Ux4)xd|i#?U_#?Cx%&lfu!V zlEoMpJ~9x;Uo`FjSgmqvL;2q{U?|Ifa9-MCu~AzU?lPx@45N9+ zA_Z{L0nN2Bj$VAC*q&6-PYn#=gc{v3FpNQJh+mP^s8s&A>ZFbjlw7`*BQwMK#GW7? zySz@V_olMxTuwE+w>(v%{&e-A4Q8V>1ZeTb`hSu#>sPMW7wOiZL&2neO8gEpC9gy<(OhG+P?W4c6x=wUX^c76ntlW!`YM;wNdGz?6})> zLFd{}G*w*ckAo!^=^Q+D#hUzuHd>-2ltZc$KDf}R(P^33lCHoNs!cC_J|Z|z|9+Z9 zY1V@Q#MB)|enwffqK49uf3!>%7!stDg+QIGAYutE;DSA!5!}MODQJr## zo~Mb>IL({Ej3yMH;jRw*IlgFxg~qVGApP3;f(E9VivduL?jfz$8D{Whz;c#Gz4ZQn ziuT-tIkFAX>;e5V9rE0Z+Oyn+`L(MHuq{X2Y5ZQ#TjY?rUwG z3-T`NR<={y!BUvobXRK6jv4NGINZH|uHoofIWXLfAY2a%$GYDZtEUx5BaE7|2(h z$dNf>@)OOPWmovgmI~g3heNR4yN7^9So?s zLWfyG0f$*a0=HR012!=NuL!r1a|43{4QL1{J``0u0eAx?m+g21L;_7smyvb@7ne$T z15N@(QJ0Z+0~eP{c>@)f#(4uU0=i(A_;~|10-#}+FnR+tCzWCV0BmVuFJx(XY-28J bVRBGQ1qJ{B000sI5&$;_0063G0{{R3Y390e diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/G2DWrapper.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/G2DWrapper.java index 2b75432b..552ffc6a 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/G2DWrapper.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/G2DWrapper.java @@ -21,7 +21,12 @@ import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Area; +import java.awt.geom.CubicCurve2D; 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.RoundRectangle2D; import java.awt.image.BufferedImage; @@ -45,6 +50,9 @@ import java.util.Map; class G2DWrapper extends Graphics2D { public static int LINE_SENSITIVITY_MARGIN = 2; + public static int CURVE_SENSITIVITY = 10; + + private boolean drawingComponent = false; private Graphics2D canvasGraphics; private Stroke originalStroke; @@ -63,13 +71,15 @@ class G2DWrapper extends Graphics2D { public G2DWrapper(Graphics2D canvasGraphics) { super(); this.canvasGraphics = canvasGraphics; - startedDrawingComponent(); + currentArea = new Area(); + currentTx = new AffineTransform(); } /** * Clears out the current area and caches canvas settings. */ public void startedDrawingComponent() { + drawingComponent = true; currentArea = new Area(); originalStroke = canvasGraphics.getStroke(); originalColor = canvasGraphics.getColor(); @@ -86,6 +96,7 @@ class G2DWrapper extends Graphics2D { * @return */ public Area finishedDrawingComponent() { + drawingComponent = false; canvasGraphics.setStroke(originalStroke); canvasGraphics.setColor(originalColor); canvasGraphics.setTransform(originalTx); @@ -94,12 +105,120 @@ class G2DWrapper extends Graphics2D { return currentArea; } + /** + * Appends shape interior to the current component area. + * + * @param s + */ private void appendShape(Shape s) { + if (!drawingComponent) { + return; + } Area area = new Area(s); area.transform(currentTx); 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 public void addRenderingHints(Map hints) { canvasGraphics.addRenderingHints(hints); @@ -113,7 +232,7 @@ class G2DWrapper extends Graphics2D { @Override public void draw(Shape s) { canvasGraphics.draw(s); - appendShape(s); + appendShapeOutline(s); } @Override @@ -380,27 +499,13 @@ class G2DWrapper extends Graphics2D { @Override public void drawLine(int x1, int y1, int x2, int y2) { canvasGraphics.drawLine(x1, y1, x2, y2); - Double theta = Math.atan2(y2 - y1, x2 - x1); - 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); + appendShapeOutline(new Line2D.Double(x1, y1, x2, y2)); } @Override public void drawOval(int x, int y, int width, int height) { canvasGraphics.drawOval(x, y, width, height); - appendShape(new Ellipse2D.Double(x, y, width, height)); + appendShapeOutline(new Ellipse2D.Double(x, y, width, height)); } @Override @@ -416,7 +521,7 @@ class G2DWrapper extends Graphics2D { @Override public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int 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 @@ -440,7 +545,7 @@ class G2DWrapper extends Graphics2D { @Override public void drawRect(int x, int y, int width, int height) { canvasGraphics.drawRect(x, y, width, height); - appendShape(new Rectangle(x, y, width, height)); + appendShapeOutline(new Rectangle(x, y, width, height)); } @Override diff --git a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/Presenter.java b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/Presenter.java index 5d2c81b0..8dac6d3e 100644 --- a/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/Presenter.java +++ b/ diy-layout-creator --username bancika@gmail.com/DIYLC/src/org/diylc/presenter/Presenter.java @@ -728,6 +728,9 @@ public class Presenter implements IPlugInPort { // Add it to the project taking z-order into account. addComponent(component, componentType); + // Select the new component + selectedComponents.clear(); + selectedComponents.add(component); // Translate them to the desired location. if (point != null) { @@ -763,6 +766,9 @@ public class Presenter implements IPlugInPort { messageDispatcher.dispatchMessage(EventType.PROJECT_MODIFIED, oldProject, cloner .deepClone(currentProject), "Add " + componentType.getName()); } + messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents); + messageDispatcher.dispatchMessage(EventType.SELECTION_SIZE_CHANGED, + calculateSelectionDimension()); messageDispatcher.dispatchMessage(EventType.REPAINT); }