【问题标题】:Most elegant way to clip a line?最优雅的剪线方式?
【发布时间】:2010-10-12 05:25:49
【问题描述】:

我有一个 Rectangle2D 和一个 Line2D。我想“剪裁”这条线,以便只保留矩形内的那部分线。如果没有一条线在矩形内,我希望将线设置为 (0,0,0,0)。基本上类似于a

Rectangle2D.intersect(Line2D src, Line2D dest)

或类似的东西。

有没有办法用 java.awt.geom API 做到这一点?还是一种“手动”编码的优雅方式?

【问题讨论】:

    标签: java algorithm geometry clipping


    【解决方案1】:

    Rectangle2D.intersectLine() 的源代码可能会有所帮助:

    public boolean intersectsLine(double x1, double y1, double x2, double y2) {
        int out1, out2;
        if ((out2 = outcode(x2, y2)) == 0) {
            return true;
        }
        while ((out1 = outcode(x1, y1)) != 0) {
            if ((out1 & out2) != 0) {
                return false;
            }
            if ((out1 & (OUT_LEFT | OUT_RIGHT)) != 0) {
                double x = getX();
                if ((out1 & OUT_RIGHT) != 0) {
                    x += getWidth();
                }
                y1 = y1 + (x - x1) * (y2 - y1) / (x2 - x1);
                x1 = x;
            } else {
                double y = getY();
                if ((out1 & OUT_BOTTOM) != 0) {
                    y += getHeight();
                }
                x1 = x1 + (y - y1) * (x2 - x1) / (y2 - y1);
                y1 = y;
            }
        }
        return true;
    }
    

    其中outcode() 定义为:

    public int outcode(double x, double y) {
        int out = 0;
        if (this.width <= 0) {
            out |= OUT_LEFT | OUT_RIGHT;
        } else if (x < this.x) {
            out |= OUT_LEFT;
        } else if (x > this.x + this.width) {
            out |= OUT_RIGHT;
        }
        if (this.height <= 0) {
            out |= OUT_TOP | OUT_BOTTOM;
        } else if (y < this.y) {
            out |= OUT_TOP;
        } else if (y > this.y + this.height) {
            out |= OUT_BOTTOM;
        }
        return out;
    }
    

    (来自OpenJDK

    将其更改为 clip 而不是返回 true 或 false 应该不是非常困难。

    【讨论】:

    • 虽然这个布尔测试的某些部分类似于 Cohen-Sutherland 算法,但我发现从算法的伪代码开始比适应 AWT intersectsLine() 布尔测试更容易。但我认为outcode() 辅助函数几乎可以按原样使用。
    【解决方案2】:

    使用 AWT 没有很好的方法。你最好的选择是Cohen-Sutherland algorithmHere's a link with example Java code(lern2indent,amirite?)向您展示它是如何完成的。

    【讨论】:

      【解决方案3】:

      通常的做法是使用Graphics2D.clip 限制图形上下文中的剪辑区域。您可能需要调用Graphics.create,以免干扰原始上下文。

      Graphics2D g = (Graphics2D)gOrig.create();
      try {
          g.clip(clip);
          ...
      } finally {
          g.dispose();
      }
      

      【讨论】:

      • 这就是 java.awt.geom 的设计目的。
      • 否则,你有原始数据可以自己计算。
      【解决方案4】:

      好吧,我最终自己做了。

      对于那些感兴趣的人,我最终通过将线变成矩形(使用 getBounds)来解决它,然后使用 Rectangle.intersect(clipRect,lineRect,intersectLineRect) 创建交叉点,然后将交叉点重新变成一条线。

      【讨论】:

      • 这部分可以使用更多细节:“将交叉点重新变成一条线。”剪切线的端点可以位于相交矩形的边缘。
      猜你喜欢
      • 2013-04-23
      • 2012-03-08
      • 1970-01-01
      • 2018-04-01
      • 2013-08-02
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多