最优雅的剪线方式?

Posted

技术标签:

【中文标题】最优雅的剪线方式?【英文标题】: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 做到这一点?还是一种“手动”编码的优雅方式?

【问题讨论】:

【参考方案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 algorithm。 Here'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) 创建交叉点,然后将交叉点重新变成一条线。

【讨论】:

这部分可以使用更多细节:“将交叉点重新变成一条线。”剪切线的端点可以位于相交矩形的边缘。

以上是关于最优雅的剪线方式?的主要内容,如果未能解决你的问题,请参考以下文章

强制 TEXTAREA 元素换行的最优雅方式,*不管*空格

在 Vim 中注释/取消注释 ruby​​ 代码块的最优雅的方式是啥?

怎样做才是最优雅方式切换 web 项目数据源 ?

Spring 优雅注册 Bean 的方式

在 Flutter 和 Dart 中重构小部件的最优雅/高效的方式

最优雅退出 Android 应用程序的 6 种方式