📄 polybase.java
字号:
Poly.Type style = Poly.Type.getTextTypeFromAngle(angle); return style; } /** * Method to unrotate a text Type according to the rotation of the object on which it resides. * Unrotation implies converting apparent anchor information to actual stored anchor information * on a transformed node. For example, if the node is rotated, and the anchor appears to be at the * bottom, then the actual anchor that is stored with the node will be different (and when transformed * will appear to be at the bottom). * @param origType the original text Type. * @param eObj the ElectricObject on which the text resides. * @return the new text Type that accounts for the rotation. */ public static Poly.Type unRotateType(Poly.Type origType, ElectricObject eObj) { // centered text does not rotate its anchor if (origType == Poly.Type.TEXTCENT || origType == Poly.Type.TEXTBOX) return origType; // get node this sits on NodeInst ni; if (eObj instanceof NodeInst) { ni = (NodeInst)eObj; } else if (eObj instanceof Export) { Export pp = (Export)eObj; ni = pp.getOriginalPort().getNodeInst(); } else return origType; // no need to rotate anchor if the node is not transformed int nodeAngle = ni.getAngle(); if (nodeAngle == 0 && !ni.isMirroredAboutXAxis() && !ni.isMirroredAboutYAxis()) return origType; // can only rotate anchor when node is in a manhattan orientation if ((nodeAngle%900) != 0) return origType; // rotate the anchor int angle = origType.getTextAngle(); int rotAngle = ni.getAngle(); if (ni.isMirroredAboutXAxis() != ni.isMirroredAboutYAxis()) rotAngle = -rotAngle; Orientation orient = Orientation.fromJava(rotAngle, ni.isMirroredAboutXAxis(), ni.isMirroredAboutYAxis()); AffineTransform trans = orient.pureRotate();// AffineTransform trans = NodeInst.pureRotate(rotAngle, ni.isMirroredAboutXAxis(), ni.isMirroredAboutYAxis()); Point2D pt = new Point2D.Double(100, 0); trans.transform(pt, pt); int xAngle = GenMath.figureAngle(new Point2D.Double(0, 0), pt); if (ni.isMirroredAboutXAxis() != ni.isMirroredAboutYAxis() && ((angle%1800) == 0 || (angle%1800) == 1350)) angle += 1800; angle = (angle - xAngle + 3600) % 3600; return Poly.Type.getTextTypeFromAngle(angle); } /** * Method to return the scaling factor between database and screen for the given text. * @param wnd the window with the text. * @param gv the GlyphVector describing the text. * @param style the anchor information for the text. * @param lX the low X bound of the polygon containing the text. * @param hX the high X bound of the polygon containing the text. * @param lY the low Y bound of the polygon containing the text. * @param hY the high Y bound of the polygon containing the text. * @return the scale of the text (from database to screen). */ protected double getTextScale(EditWindow0 wnd, GlyphVector gv, Poly.Type style, double lX, double hX, double lY, double hY) { double textScale = 1.0/wnd.getScale(); if (style == Poly.Type.TEXTBOX) { Rectangle2D glyphBounds = gv.getVisualBounds(); double textWidth = glyphBounds.getWidth() * textScale; if (textWidth > hX - lX) { // text too big for box: scale it down textScale *= (hX - lX) / textWidth; } } return textScale; } /** * Method to report the distance of a point to this Poly. * @param x coordinate of a point. * @param y coordinate of a point. * @return the distance of the point to the Poly. * The method returns a negative amount if the point is a direct hit on or inside * the polygon (the more negative, the closer to the center). */ public double polyDistance(double x, double y) { return polyDistance(new Rectangle2D.Double(x, y, 0, 0)); } /** * Method to report the distance of a rectangle or point to this Poly. * @param otherBounds the area to test for distance to the Poly. * @return the distance of the area to the Poly. * The method returns a negative amount if the point/area is a direct hit on or inside * the polygon (the more negative, the closer to the center). */ public double polyDistance(Rectangle2D otherBounds) { // get information about this Poly Rectangle2D polyBounds = getBounds2D(); double polyCX = polyBounds.getCenterX(); double polyCY = polyBounds.getCenterY(); Point2D polyCenter = new Point2D.Double(polyCX, polyCY); Poly.Type localStyle = style; boolean thisIsPoint = (polyBounds.getWidth() == 0 && polyBounds.getHeight() == 0); // get information about the other area being tested boolean otherIsPoint = (otherBounds.getWidth() == 0 && otherBounds.getHeight() == 0); double otherCX = otherBounds.getCenterX(); double otherCY = otherBounds.getCenterY(); Point2D otherPt = new Point2D.Double(otherCX, otherCY); // handle single point polygons if (thisIsPoint) { if (otherIsPoint) { if (polyCX == otherCX && polyCY == otherCY) return Double.MIN_VALUE; } else { if (otherBounds.contains(polyCenter)) return Double.MIN_VALUE; } return otherPt.distance(polyCenter); } // handle polygons that are filled in if (localStyle == Poly.Type.FILLED || localStyle == Poly.Type.CROSSED || localStyle.isText()) { if (otherIsPoint) { // give special returned value if point is a direct hit if (isInside(otherPt)) { return otherPt.distance(polyCenter) - Double.MAX_VALUE; } // if polygon is a box, use M.B.R. information Rectangle2D box = getBox(); if (box != null) { if (otherCX > box.getMaxX()) polyCX = otherCX - box.getMaxX(); else if (otherCX < box.getMinX()) polyCX = box.getMinX() - otherCX; else polyCX = 0; if (otherCY > box.getMaxY()) polyCY = otherCY - box.getMaxY(); else if (otherCY < box.getMinY()) polyCY = box.getMinY() - otherCY; else polyCY = 0; if (polyCX == 0 || polyCY == 0) return polyCX + polyCY; polyCenter.setLocation(polyCX, polyCY); return polyCenter.distance(new Point2D.Double(0,0)); } // point is outside of irregular polygon: fall into to next case localStyle = Poly.Type.CLOSED; } else { if (otherBounds.intersects(polyBounds)) return Double.MIN_VALUE; return otherPt.distance(polyCenter); } } // handle closed outline figures if (localStyle == Poly.Type.CLOSED) { if (otherIsPoint) { double bestDist = Double.MAX_VALUE; Point2D lastPt = points[points.length-1]; for(int i=0; i<points.length; i++) { if (i != 0) lastPt = points[i-1]; Point2D thisPt = points[i]; // compute distance of close point to "otherPt" double dist = DBMath.distToLine(lastPt, thisPt, otherPt); if (dist < bestDist) bestDist = dist; } return bestDist; } else { if (otherBounds.intersects(polyBounds)) return Double.MIN_VALUE; return otherPt.distance(polyCenter); } } // handle opened outline figures if (localStyle == Poly.Type.OPENED || localStyle == Poly.Type.OPENEDT1 || localStyle == Poly.Type.OPENEDT2 || localStyle == Poly.Type.OPENEDT3) { if (otherIsPoint) { double bestDist = Double.MAX_VALUE; for(int i=1; i<points.length; i++) { Point2D lastPt = points[i-1]; Point2D thisPt = points[i]; // compute distance of close point to "otherPt" double dist = DBMath.distToLine(lastPt, thisPt, otherPt); if (dist < bestDist) bestDist = dist; } return bestDist; } else { if (DBMath.rectsIntersect(otherBounds,polyBounds)) return Double.MIN_VALUE;// if (otherBounds.intersects(polyBounds)) return Double.MIN_VALUE; return otherPt.distance(polyCenter); } } // handle outline vector lists if (localStyle == Poly.Type.VECTORS) { if (otherIsPoint) { double bestDist = Double.MAX_VALUE; for(int i=0; i<points.length; i += 2) { Point2D lastPt = points[i]; Point2D thisPt = points[i+1]; // compute distance of close point to "otherPt" double dist = DBMath.distToLine(lastPt, thisPt, otherPt); if (dist < bestDist) bestDist = dist; } return bestDist; } else { if (DBMath.rectsIntersect(otherBounds,polyBounds)) return Double.MIN_VALUE; return otherPt.distance(polyCenter); } } // handle circular objects if (localStyle == Poly.Type.CIRCLE || localStyle == Poly.Type.THICKCIRCLE || localStyle == Poly.Type.DISC) { double odist = points[0].distance(points[1]); double dist = points[0].distance(otherPt); if (otherIsPoint) { if (localStyle == Poly.Type.DISC && dist < odist) return dist-Double.MAX_VALUE; return Math.abs(dist-odist); } else { if (points[0].getX() + dist < otherBounds.getMinX()) return dist; if (points[0].getX() - dist > otherBounds.getMaxX()) return dist; if (points[0].getY() + dist < otherBounds.getMinY()) return dist; if (points[0].getY() - dist > otherBounds.getMaxY()) return dist; return Double.MIN_VALUE; } } if (localStyle == Poly.Type.CIRCLEARC || localStyle == Poly.Type.THICKCIRCLEARC) { if (otherIsPoint) { // determine closest point to ends of arc double sdist = otherPt.distance(points[1]); double edist = otherPt.distance(points[2]); double dist = Math.min(sdist, edist); // see if the point is in the segment of the arc int pang = DBMath.figureAngle(points[0], otherPt); int sang = DBMath.figureAngle(points[0], points[1]); int eang = DBMath.figureAngle(points[0], points[2]); if (eang > sang) { if (pang < eang && pang > sang) return dist; } else { if (pang < eang || pang > sang) return dist; } // point in arc: determine distance double odist = points[0].distance(points[1]); dist = points[0].distance(otherPt); return Math.abs(dist-odist); } else { Point2D [] savePoints = points; clipArc(otherBounds.getMinX(), otherBounds.getMaxX(), otherBounds.getMinY(), otherBounds.getMaxY()); Point2D [] newPoints = points; points = savePoints; if (newPoints.length > 0) return Double.MIN_VALUE; double dist = points[0].distance(points[1]); return points[0].distance(otherPt) - dist; } } // can't figure out others: use distance to polygon center return otherPt.distance(polyCenter); } /** * Method to calculate fast distance between two manhattan * polygons that do not intersect * @param polyOther the other polygon being examined with this. * @return non-negative distance if both polygons are manhattan types, * -1 if at least one of them is not manhattan. */ public double separationBox(PolyBase polyOther) { Rectangle2D thisBounds = getBox(); Rectangle2D otherBounds = polyOther.getBox(); // Both polygons must be manhattan-shaped if (thisBounds == null || otherBounds == null) return -1; double lX1 = thisBounds.getMinX(); double hX1 = thisBounds.getMaxX(); double lY1 = thisBounds.getMinY(); double hY1 = thisBounds.getMaxY(); double lX2 = otherBounds.getMinX(); double hX2 = otherBounds.getMaxX(); double lY2 = otherBounds.getMinY(); double hY2 = otherBounds.getMaxY(); double pdx = Math.max(lX2-hX1, lX1-hX2); double pdy = Math.max(lY2-hY1, lY1-hY2); double pd = (pdx > 0 && pdy > 0) ? // Diagonal Math.hypot(pdx, pdy) : Math.max(pdx, pdy); return pd; } /** * Method to return the distance between this Poly and another. * @param polyOther the other Poly to consider. * @return the distance between them (returns 0 if they touch or overlap). */ public double separation(PolyBase polyOther) { // stop now if they touch if (intersects(polyOther)) return 0; // look at all points on polygon 1 double minPD = 0; for(int i=0; i<points.length; i++) { Point2D c = polyOther.closestPoint(points[i]); double pd = c.distance(points[i]); if (pd <= 0) return 0; if (i == 0) minPD = pd; else { if (pd < minPD) minPD = pd; } } // look at all points on polygon 2 for (Point2D point : polyOther.points) { Point2D c = closestPoint(point); double pd = c.distance(point); if (pd <= 0) return 0; if (pd < minPD) minPD = pd; } // also compute manhattan separation and use it if better double minPDman = separationBox(polyOther); if (minPDman != -1 && minPDman < minPD) minPD = minPDman; return minPD; } /** * Method to find the point on this polygon closest to a given point. * @param pt the given point * @return a point on this Poly that is closest. */ public Point2D closestPoint(Point2D pt) { Poly.Type localStyle = style; if (localStyle == Poly.Type.FILLED || localStyle == Poly.Type.CROSSED || localStyle == Poly.Type.TEXTCENT || localStyle.isText()) { // filled polygon: check for regularity first Rectangle2D bounds = getBox(); if (bounds != null) { double x = pt.getX(); double y = pt.getY(); if (x < bounds.getMinX()) x = bounds.getMinX(); if (x > bounds.getMaxX()) x = bounds.getMaxX(); if (y < bounds.getMinY()) y = bounds.getMinY(); if (y > bounds.getMaxY()) y = bounds.getMaxY(); return new Point2D.Double(x, y); } if (localStyle == Poly.Type.FILLED) { if (isInside(pt)) return pt; } localStyle = Poly.Type.CLOSED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -