| | |
| | | private static final Color HANDHELD_BOUNDARY_FILL = new Color(51, 153, 255, 60); |
| | | private static final Color HANDHELD_BOUNDARY_BORDER = new Color(0, 100, 0, 220); |
| | | private static final Color HANDHELD_BOUNDARY_POINT = new Color(0, 100, 0); |
| | | private static final double BASE_WORLD_MARKER_SIZE = 0.27d; // halve the base diameter for subtler markers |
| | | private static final double MIN_PIXEL_DIAMETER = 3.0d; |
| | | private static final double MAX_PIXEL_DIAMETER = 9.0d; |
| | | private static volatile double cachedMarkerPixelDiameter = -1.0d; |
| | | |
| | | private adddikuaiyulan() { |
| | | } |
| | |
| | | public static void drawPreview(Graphics2D g2d, |
| | | List<Point2D.Double> previewPoints, |
| | | double scale, |
| | | boolean previewActive) { |
| | | boolean previewActive, |
| | | double diameterScale) { |
| | | if (!previewActive) { |
| | | cachedMarkerPixelDiameter = -1.0d; |
| | | } |
| | | |
| | | if (g2d == null || !previewActive || previewPoints == null || previewPoints.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | Path2D.Double path = new Path2D.Double(); |
| | | boolean started = false; |
| | | // 过滤有效点 |
| | | List<Point2D.Double> validPoints = new java.util.ArrayList<>(); |
| | | for (Point2D.Double point : previewPoints) { |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |
| | | continue; |
| | | } |
| | | if (!started) { |
| | | path.moveTo(point.x, point.y); |
| | | started = true; |
| | | } else { |
| | | path.lineTo(point.x, point.y); |
| | | if (point != null && Double.isFinite(point.x) && Double.isFinite(point.y)) { |
| | | validPoints.add(point); |
| | | } |
| | | } |
| | | |
| | | if (!started) { |
| | | if (validPoints.isEmpty()) { |
| | | return; |
| | | } |
| | | |
| | | Stroke originalStroke = g2d.getStroke(); |
| | | Color originalColor = g2d.getColor(); |
| | | |
| | | if (previewPoints.size() >= 3) { |
| | | path.closePath(); |
| | | // 创建填充路径(如果点数>=3,需要闭合以填充) |
| | | Path2D.Double fillPath = new Path2D.Double(); |
| | | if (validPoints.size() >= 3) { |
| | | fillPath.moveTo(validPoints.get(0).x, validPoints.get(0).y); |
| | | for (int i = 1; i < validPoints.size(); i++) { |
| | | fillPath.lineTo(validPoints.get(i).x, validPoints.get(i).y); |
| | | } |
| | | fillPath.closePath(); |
| | | g2d.setColor(HANDHELD_BOUNDARY_FILL); |
| | | g2d.fill(path); |
| | | g2d.fill(fillPath); |
| | | } |
| | | |
| | | float outlineWidth =0.1f; |
| | | g2d.setStroke(new BasicStroke(outlineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); |
| | | g2d.setColor(HANDHELD_BOUNDARY_BORDER); |
| | | g2d.draw(path); |
| | | float outlineWidth = 0.1f; |
| | | |
| | | if (validPoints.size() >= 3) { |
| | | // 点数>=3时,需要分别绘制实线和虚线 |
| | | // 绘制实线部分:从起点依次连接到各个点(不闭合,不包括起点到终点的直接连线) |
| | | Path2D.Double solidPath = new Path2D.Double(); |
| | | solidPath.moveTo(validPoints.get(0).x, validPoints.get(0).y); |
| | | // 从第二个点开始,依次连接到最后一个点(形成不闭合的路径) |
| | | for (int i = 1; i < validPoints.size(); i++) { |
| | | solidPath.lineTo(validPoints.get(i).x, validPoints.get(i).y); |
| | | } |
| | | g2d.setStroke(new BasicStroke(outlineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); |
| | | g2d.setColor(HANDHELD_BOUNDARY_BORDER); |
| | | g2d.draw(solidPath); |
| | | |
| | | // 用虚线绘制起点到终点的连线(闭合线段) |
| | | Point2D.Double startPoint = validPoints.get(0); |
| | | Point2D.Double endPoint = validPoints.get(validPoints.size() - 1); |
| | | |
| | | // 创建虚线样式(根据缩放调整虚线模式) |
| | | double effectiveScale = Math.max(0.01d, scale); |
| | | float dashLength = (float) (0.05 / effectiveScale); // 虚线长度随缩放调整 |
| | | float[] dashPattern = new float[]{dashLength, dashLength}; // 虚线模式:实线、空白 |
| | | BasicStroke dashedStroke = new BasicStroke( |
| | | outlineWidth, |
| | | BasicStroke.CAP_ROUND, |
| | | BasicStroke.JOIN_ROUND, |
| | | 1.0f, |
| | | dashPattern, |
| | | 0.0f |
| | | ); |
| | | |
| | | g2d.setStroke(dashedStroke); |
| | | g2d.setColor(HANDHELD_BOUNDARY_BORDER); |
| | | // 使用Path2D绘制起点到终点的虚线,以便支持浮点坐标 |
| | | Path2D.Double dashedLine = new Path2D.Double(); |
| | | dashedLine.moveTo(startPoint.x, startPoint.y); |
| | | dashedLine.lineTo(endPoint.x, endPoint.y); |
| | | g2d.draw(dashedLine); |
| | | } else if (validPoints.size() == 2) { |
| | | // 如果只有2个点,直接绘制实线 |
| | | Path2D.Double simplePath = new Path2D.Double(); |
| | | simplePath.moveTo(validPoints.get(0).x, validPoints.get(0).y); |
| | | simplePath.lineTo(validPoints.get(1).x, validPoints.get(1).y); |
| | | g2d.setStroke(new BasicStroke(outlineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); |
| | | g2d.setColor(HANDHELD_BOUNDARY_BORDER); |
| | | g2d.draw(simplePath); |
| | | } |
| | | |
| | | double markerSize = 0.2d; |
| | | double markerRadius = markerSize / 2.0d; |
| | | if (cachedMarkerPixelDiameter <= 0.0d) { |
| | | double previousPixelDiameter = Math.abs(BASE_WORLD_MARKER_SIZE * scale); |
| | | if (previousPixelDiameter <= 0.0d) { |
| | | previousPixelDiameter = MIN_PIXEL_DIAMETER; |
| | | } |
| | | cachedMarkerPixelDiameter = Math.max(MIN_PIXEL_DIAMETER, |
| | | Math.min(MAX_PIXEL_DIAMETER, previousPixelDiameter)); |
| | | } |
| | | |
| | | double effectiveScale = Math.max(0.01d, scale); |
| | | double markerSize = cachedMarkerPixelDiameter / effectiveScale; |
| | | double normalizedScale = Double.isFinite(diameterScale) && diameterScale > 0.0d ? diameterScale : 1.0d; |
| | | markerSize *= normalizedScale; |
| | | double markerRadius = markerSize / 2.0d; |
| | | |
| | | for (Point2D.Double point : previewPoints) { |
| | | if (point == null || !Double.isFinite(point.x) || !Double.isFinite(point.y)) { |