private static boolean contains(CubicCurve2D.Double cubic, Rectangle2D... rects) { for (Rectangle2D r : rects) { if (r.contains(cubic.getP1()) && r.contains(cubic.getP2())) { return true; } } return false; }
private void cutAllCubic(List<CubicCurve2D.Double> all) { final List<CubicCurve2D.Double> tmp = new ArrayList<CubicCurve2D.Double>(all); all.clear(); for (CubicCurve2D.Double bez : tmp) { final CubicCurve2D.Double left = new CubicCurve2D.Double(); final CubicCurve2D.Double right = new CubicCurve2D.Double(); bez.subdivide(left, right); all.add(left); all.add(right); } }
@Override @SuppressWarnings("unchecked") public Object clone() throws CloneNotSupportedException { StateTransitionObj copy = (StateTransitionObj) super.clone(); copy.startPt = (Point) startPt.clone(); copy.pageS = (Point) pageS.clone(); copy.curve = (CubicCurve2D.Double) curve.clone(); copy.endPt = (Point) endPt.clone(); copy.startCtrlPt = (Point) startCtrlPt.clone(); copy.endCtrlPt = (Point) endCtrlPt.clone(); copy.pageSC = (Point) pageSC.clone(); copy.pageE = (Point) pageE.clone(); copy.pageEC = (Point) pageEC.clone(); copy.startBorderPts = (Vector<Point>) startBorderPts.clone(); copy.endBorderPts = (Vector<Point>) endBorderPts.clone(); if (attrib != null) { copy.attrib = (LinkedList<ObjAttribute>) copy.attrib.clone(); for (int i = 0; i < attrib.size(); i++) { copy.attrib.set(i, (ObjAttribute) attrib.get(i).clone()); } } return copy; }
public Map<Point2D, Double> somePoints() { final Map<Point2D, Double> result = new HashMap<Point2D, Double>(); for (CubicCurve2D.Double bez : beziers) { final CubicCurve2D.Double left = new CubicCurve2D.Double(); final CubicCurve2D.Double right = new CubicCurve2D.Double(); bez.subdivide(left, right); result.put(left.getP1(), BezierUtils.getStartingAngle(left)); result.put(left.getP2(), BezierUtils.getEndingAngle(left)); result.put(right.getP1(), BezierUtils.getStartingAngle(right)); result.put(right.getP2(), BezierUtils.getEndingAngle(right)); } return result; }
public PointDirected getIntersection(CubicCurve2D.Double bez) { if (contains(bez.x1, bez.y1) == contains(bez.x2, bez.y2)) { return null; } final double dist = bez.getP1().distance(bez.getP2()); if (dist < 2) { final double angle = BezierUtils.getStartingAngle(bez); return new PointDirected(bez.getP1(), angle); } final CubicCurve2D.Double left = new CubicCurve2D.Double(); final CubicCurve2D.Double right = new CubicCurve2D.Double(); bez.subdivide(left, right); final PointDirected int1 = getIntersection(left); if (int1 != null) { return int1; } final PointDirected int2 = getIntersection(right); if (int2 != null) { return int2; } throw new IllegalStateException(); }
public Point2D getFrontierIntersection(Shape shape, Rectangle2D... notIn) { final List<CubicCurve2D.Double> all = new ArrayList<CubicCurve2D.Double>(beziers); for (int i = 0; i < 8; i++) { for (CubicCurve2D.Double immutable : all) { if (contains(immutable, notIn)) { continue; } final CubicCurve2D.Double bez = new CubicCurve2D.Double(); bez.setCurve(immutable); if (BezierUtils.isCutting(bez, shape)) { while (BezierUtils.dist(bez) > 1.0) { BezierUtils.shorten(bez, shape); } final Point2D.Double result = new Point2D.Double((bez.x1 + bez.x2) / 2, (bez.y1 + bez.y2) / 2); if (contains(result, notIn) == false) { return result; } } } cutAllCubic(all); } throw new IllegalArgumentException("shape=" + shape); }
@Override public void updateObj() { int oldS = sPage; int oldE = ePage; sPage = startState.getPage(); myPage = sPage; ePage = endState.getPage(); if (oldS != sPage && oldS != oldE) { for (int i = 0; i < attrib.size(); i++) { ObjAttribute obj = attrib.get(i); if (obj.getPage() == oldS) obj.setPage(sPage); } } if (oldE != ePage && oldS != oldE) { for (int i = 0; i < attrib.size(); i++) { ObjAttribute obj = attrib.get(i); if (obj.getPage() == oldE) obj.setPage(ePage); } } if (sPage != ePage && oldS == oldE) { for (int i = 0; i < attrib.size(); i++) { ObjAttribute obj = attrib.get(i); obj.setPage(sPage); } } if ((startState.getSelectStatus() != SelectOptions.TXT && startState.getSelectStatus() != SelectOptions.NONE) || (endState.getSelectStatus() != SelectOptions.TXT && endState.getSelectStatus() != SelectOptions.NONE)) { if (oldS != oldE && sPage == ePage) setEndPts(); else moveEndPts(); curve.setCurve( startPt.getX(), startPt.getY(), startCtrlPt.getX(), startCtrlPt.getY(), endCtrlPt.getX(), endCtrlPt.getY(), endPt.getX(), endPt.getY()); } }
private GeneralPath subdivide(Point b0, Point b1, Point b2, Point b3) { double cutDistance = getTargetAnchorShape().getCutDistance(); double minDistance = cutDistance - ENDPOINT_DEVIATION; /** * if the cutDistance is valid the last segment of the curve gets reduced by subdivision until * the distance of the endpoint(epDistance) satisfys the condition (cutDistance > epDistance > * (cutDistance - ENDPOINT-DEVIATION) */ if (cutDistance > minDistance && minDistance > 0) { GeneralPath path = new GeneralPath(); path.moveTo(b0.x, b0.y); CubicCurve2D.Double left = new CubicCurve2D.Double( b0.x, b0.y, b1.x, b1.y, b2.x, b2.y, b3.x, b3.y); CubicCurve2D right = new CubicCurve2D.Double(); left.subdivide(left, right); double distance = b3.distance(left.getP2()); // if the distance is bigger as the cutDistance the left segment is added // and the right segment is divided again while (distance > cutDistance) { path.append(left, true); right.subdivide(left, right); distance = b3.distance(left.getP2()); // if the devision removed to much the left segment is divided while (distance < minDistance) { // changes the distance to ~ (distance+distance/2) left.subdivide(left, right); distance = b3.distance(left.getP2()); } } // append the last segment with (minDistance < distance < cutDistance) // actually we should check if the a division happend, but this is very unlikly path.append(left, true); return path; } return null; }
@Override public void adjustShapeOrPosition(int x, int y) { if (selectStatus == SelectOptions.START) { Point currPt = new Point(x, y); double temp; double max = 1000000; for (int i = 0; i < 36; i++) { temp = currPt.distanceSq(startBorderPts.get(i)); if (temp < max) { startStateIndex = i; max = temp; } } startPt.setLocation( startBorderPts.get(startStateIndex).getX(), startBorderPts.get(startStateIndex).getY()); if (stub) { angle = getAngle(startPt, startState.getRealCenter(myPage)); pageS.setLocation( new Point( (int) (startPt.getX() + len * Math.cos(angle)), (int) (startPt.getY() - len * Math.sin(angle)))); } } if (selectStatus == SelectOptions.STARTCTRL) startCtrlPt.setLocation(x, y); if (selectStatus == SelectOptions.ENDCTRL) endCtrlPt.setLocation(x, y); if (selectStatus == SelectOptions.END) { Point currPt = new Point(x, y); double temp; double max = 1000000; for (int i = 0; i < 36; i++) { temp = currPt.distanceSq(endBorderPts.get(i)); if (temp < max) { endStateIndex = i; max = temp; } } endPt.setLocation( endBorderPts.get(endStateIndex).getX(), endBorderPts.get(endStateIndex).getY()); } if (selectStatus == SelectOptions.PAGES) { pageS.setLocation(pageS.getX() + x - xTemp, pageS.getY() + y - yTemp); xTemp = x; yTemp = y; if (stub) { angle = getAngle(pageS, startState.getRealCenter(myPage)); int index = 36 - (int) Math.round((angle / (Math.PI * 2)) * 36); if (index > 35) index -= 36; startStateIndex = index; startPt = startBorderPts.get(index); len = (int) startPt.distance(pageS); } } if (selectStatus == SelectOptions.PAGESC) pageSC.setLocation(x, y); if (selectStatus == SelectOptions.PAGEEC) pageEC.setLocation(x, y); if (selectStatus == SelectOptions.PAGEE) { pageE.setLocation(pageE.getX() + x - xTemp, pageE.getY() + y - yTemp); xTemp = x; yTemp = y; } if (selectStatus == SelectOptions.TXT) { if (attrib != null) { for (int i = 0; i < attrib.size(); i++) { ObjAttribute s = attrib.get(i); if (s.getSelectStatus() != 0) { s.adjustShapeOrPosition(x, y); break; } } } } if (startState.getPage() == endState.getPage()) curve.setCurve( startPt.getX(), startPt.getY(), startCtrlPt.getX(), startCtrlPt.getY(), endCtrlPt.getX(), endCtrlPt.getY(), endPt.getX(), endPt.getY()); if (selectStatus != SelectOptions.ALL) modified = true; }
@Override public void paintComponent(Graphics g) { // check if something needs to be painted at all if (ready) { sPage = startState.getPage(); myPage = sPage; ePage = endState.getPage(); } // check if anything needs to be drawn if (ready && (sPage == currPage || ePage == currPage)) { Graphics2D g2D = (Graphics2D) g; g2D.setColor(color); // draw arrow head for non-stub transitions if (currPage == ePage && !stub) { // find angle between end point and end control point int dx = (int) endCtrlPt.getX() - (int) endPt.getX(); int dy = (int) endCtrlPt.getY() - (int) endPt.getY(); double alpha = 0; if (dx == 0) { if (dy <= 0) alpha = Math.PI / 2; else alpha = 3 * Math.PI / 2; } else if (dx > 0 && dy > 0) alpha = 2 * Math.PI - Math.atan((double) dy / dx); else if (dx > 0 && dy <= 0) { if (dy == 0) alpha = 0; else alpha = -Math.atan((double) dy / (dx)); } else if (dx < 0) alpha = Math.PI - Math.atan((double) dy / dx); double adj = Math.PI / 6; int[] xP = { (int) endPt.getX(), (int) endPt.getX() + (int) (13 * Math.cos(alpha + adj)), (int) endPt.getX() + (int) (13 * Math.cos(alpha - adj)) }; int[] yP = { (int) endPt.getY(), (int) endPt.getY() - (int) (13 * Math.sin(alpha + adj)), (int) endPt.getY() - (int) (13 * Math.sin(alpha - adj)) }; g2D.drawPolygon(xP, yP, 3); g2D.fillPolygon(xP, yP, 3); } // draw stub if (currPage == sPage && stub) { g2D.drawLine( (int) startPt.getX(), (int) startPt.getY(), (int) pageS.getX(), (int) pageS.getY()); int x = (int) pageS.getX(); int y = (int) pageS.getY(); double cos = Math.cos(angle); double sin = Math.sin(angle); g2D.drawLine( x - (int) Math.round(6 * sin + 7 * cos), y - (int) Math.round(6 * cos - 7 * sin), x, y); g2D.drawLine( x, y, x + (int) Math.round(6 * sin - 7 * cos), y + (int) Math.round(6 * cos + 7 * sin)); FontMetrics fm = g2D.getFontMetrics(); int width = fm.stringWidth(endState.getName()); int height = fm.getHeight(); g2D.drawString( endState.getName(), (int) (pageS.getX() + (12 + width / 2) * Math.cos(angle) - width / 2), (int) (pageS.getY() - 12 * Math.sin(angle) + height / 3)); // draw control points if needed if (selectStatus != SelectOptions.NONE) { g2D.setColor(Color.red); g2D.fillRect((int) startPt.getX() - 3, (int) startPt.getY() - 3, 7, 7); g2D.fillRect((int) pageS.getX() - 3, (int) pageS.getY() - 3, 7, 7); g2D.setColor(color); } } // draw normal transition if (sPage == ePage && !stub) { g2D.draw(curve); // draw control points if (selectStatus != SelectOptions.NONE) { g2D.setColor(Color.red); g2D.fillRect((int) startPt.getX() - 3, (int) startPt.getY() - 3, 7, 7); g2D.fillRect((int) endPt.getX() - 3, (int) endPt.getY() - 3, 7, 7); g2D.fillRect((int) startCtrlPt.getX() - 3, (int) startCtrlPt.getY() - 3, 7, 7); g2D.fillRect((int) endCtrlPt.getX() - 3, (int) endCtrlPt.getY() - 3, 7, 7); g2D.drawLine( (int) startPt.getX(), (int) startPt.getY(), (int) startCtrlPt.getX(), (int) startCtrlPt.getY()); g2D.drawLine( (int) endPt.getX(), (int) endPt.getY(), (int) endCtrlPt.getX(), (int) endCtrlPt.getY()); g2D.setColor(color); } } // draw page connector if (sPage != ePage && !stub) { // if one start page if (sPage == currPage) { curve.setCurve( startPt.getX(), startPt.getY(), startCtrlPt.getX(), startCtrlPt.getY(), pageSC.getX(), pageSC.getY(), pageS.getX(), pageS.getY()); int x = (int) pageS.getX(); int y = (int) pageS.getY(); g2D.drawLine(x, y, x, y + 10); g2D.drawLine(x, y + 10, x + 30, y + 10); g2D.drawLine(x + 30, y + 10, x + 40, y); g2D.drawLine(x + 40, y, x + 30, y - 10); g2D.drawLine(x + 30, y - 10, x, y - 10); g2D.drawLine(x, y - 10, x, y); FontMetrics fm = g2D.getFontMetrics(); String pageName = drawArea.getPageName(endState.getPage()); String text = endState.getName() + " (" + pageName + ")"; int tW = fm.stringWidth(text); if (tW > 40) g2D.drawString(text, x + 40 - tW, y + 25); else g2D.drawString(text, x, y + 25); // draw control points if needed if (selectStatus != SelectOptions.NONE) { g2D.setColor(Color.red); g2D.fillRect((int) startPt.getX() - 3, (int) startPt.getY() - 3, 7, 7); g2D.fillRect((int) pageS.getX() - 3, (int) pageS.getY() - 3, 7, 7); g2D.fillRect((int) startCtrlPt.getX() - 3, (int) startCtrlPt.getY() - 3, 7, 7); g2D.fillRect((int) pageSC.getX() - 3, (int) pageSC.getY() - 3, 7, 7); g2D.drawLine( (int) startPt.getX(), (int) startPt.getY(), (int) startCtrlPt.getX(), (int) startCtrlPt.getY()); g2D.drawLine( (int) pageS.getX(), (int) pageS.getY(), (int) pageSC.getX(), (int) pageSC.getY()); } g2D.setColor(color); g2D.draw(curve); } // in on end page else if (ePage == currPage) { curve.setCurve( pageE.getX(), pageE.getY(), pageEC.getX(), pageEC.getY(), endCtrlPt.getX(), endCtrlPt.getY(), endPt.getX(), endPt.getY()); int x = (int) pageE.getX() - 40; int y = (int) pageE.getY(); g2D.drawLine(x, y, x, y + 10); g2D.drawLine(x, y + 10, x + 30, y + 10); g2D.drawLine(x + 30, y + 10, x + 40, y); g2D.drawLine(x + 40, y, x + 30, y - 10); g2D.drawLine(x + 30, y - 10, x, y - 10); g2D.drawLine(x, y - 10, x, y); g2D.drawString( startState.getName() + " (" + drawArea.getPageName(startState.getPage()) + ")", x, y + 25); // control points if needed if (selectStatus != SelectOptions.NONE) { g2D.setColor(Color.red); g2D.fillRect((int) endPt.getX() - 3, (int) endPt.getY() - 3, 7, 7); g2D.fillRect((int) pageE.getX() - 3, (int) pageE.getY() - 3, 7, 7); g2D.fillRect((int) endCtrlPt.getX() - 3, (int) endCtrlPt.getY() - 3, 7, 7); g2D.fillRect((int) pageEC.getX() - 3, (int) pageEC.getY() - 3, 7, 7); g2D.drawLine( (int) endPt.getX(), (int) endPt.getY(), (int) endCtrlPt.getX(), (int) endCtrlPt.getY()); g2D.drawLine( (int) pageE.getX(), (int) pageE.getY(), (int) pageEC.getX(), (int) pageEC.getY()); } g2D.setColor(color); g2D.draw(curve); } } } }
public boolean isConnector(Point point) { final int padding = 5; return curve.intersects(point.x - padding, point.y - padding, padding * 2, padding * 2); }
/** Resizes the repaint range */ private void updateRange() { range.addRect(curve.getBounds()); }