你能告诉我Cohen-Sutherland算法的实现有什么问题吗?

Can you tell me what's wrong with this implementation of Cohen-Sutherland Algorithm?

本文关键字:什么 问题 实现 告诉我 Cohen-Sutherland 算法      更新时间:2023-10-16

请帮我修复这个Cohen-Sutherland算法实现的代码。

理论见第91页。

这是整个项目。

#include "Line2d.h"
#include "Rectangle2d.h"
#include "Coordinates2d.h"
class ClippingLine2d
{
private:
    Rectangle2d rectangle;//clipping rectangle
    Line2d line;//line to be clipped
private:
    Bits startPointBits;//bits for start point of line
    Bits endPointsBits;//bits for end point of line
public:
    ClippingLine2d(Rectangle2d rect, Line2d line)
    {
        this->rectangle = rect;
        this->line = line;      
    }       
private:        
    Line2d GetClippedLine(std::vector<Line2d> clippingRegionLines, Line2d ln)
    {
        Point2d start = ln.GetStart();
        Point2d end = ln.GetEnd();
        if(startPointBits.bit4 == 1)
        {
            start = ln.GetIntersection(clippingRegionLines[3]);//DA
        }
        else if(startPointBits.bit3 == 1)
        {
            start = ln.GetIntersection(clippingRegionLines[1]);//BC
        }
        else if(startPointBits.bit2 == 1)
        {
            start = ln.GetIntersection(clippingRegionLines[0]);//AB
        }
        else if(startPointBits.bit1 == 1)
        {
            start = ln.GetIntersection(clippingRegionLines[2]);//CD
        }

        if(endPointsBits.bit4 == 1)
        {
            end = ln.GetIntersection(clippingRegionLines[3]);//DA
        }
        else if(endPointsBits.bit3 == 1)
        {
            end = ln.GetIntersection(clippingRegionLines[1]);//BC
        }
        else if(endPointsBits.bit2 == 1)
        {
            end = ln.GetIntersection(clippingRegionLines[0]);//AB
        }
        else if(endPointsBits.bit1 == 1)
        {
            end = ln.GetIntersection(clippingRegionLines[2]);//CD
        }
        return Line2d(start.Round(), end.Round());
    }
public:
    Line2d GetClippedLine()
    {
        Point2d min = rectangle.GetStart();
        Point2d max = rectangle.GetEnd();
        startPointBits.PointToBits(max, min, line.GetStart());
        endPointsBits.PointToBits(max, min, line.GetEnd());
        std::vector<Line2d> clippingRegionLines = rectangle.GetLines();
        Line2d tempLine = this->line;
        Bits start = startPointBits;
        Bits end = endPointsBits;
        while(start.IsClippingCandidate(end))
        {
            tempLine = GetClippedLine(clippingRegionLines, tempLine);
            Point2d startP = tempLine.GetStart();
            Point2d endP = tempLine.GetEnd();
            start.PointToBits(max, min, startP);
            end.PointToBits(max, min, endP);
            Coordinates2d::Draw(tempLine);
        }
        return tempLine;
    }
};
#define LINENUM 3
int main()
{
    Line2d ln(Point2d(-120, -40), Point2d(270, 160)); 
    Rectangle2d rect(Point2d(0, 0), Point2d(170, 120)); 
    Coordinates2d::ShowWindow("Cohen-Sutherland Line Clipping");
    Coordinates2d::Draw(ln);
    Coordinates2d::Draw(rect);  
    ClippingLine2d clip(rect, ln);
    Line2d clippedLine = clip.GetClippedLine();
    Coordinates2d::Draw(clippedLine);
    Coordinates2d::Wait();
    return 0;
}

GetClippedLine()陷入无限循环。


落选者和落选者,请留言

您的Bits类中的==操作符包含一个错误:

bool operator == (Bits & b)
{
    bool b1 = bit1 == b.bit1;
    bool b2 = bit2 == b.bit2; // <-- change bit1 to bit2
    bool b3 = bit3 == b.bit3; // <-- change bit1 to bit3
    bool b4 = bit4 == b.bit4; // <-- change bit1 to bit4
    if(b1==true && b2==true && b3==true && b4==true) return true;
    else return false;
}

GetClippedLine()内部的IsClippingCandidate()调用算子函数

同样,您的剪切测试将与零进行比较,如果线的端点大于或等于剪切线,则返回1(需要剪切),这意味着如果它被精确地剪切到该线,它将始终为1。因此,将比较值更改为大于而不是大于或等于。

int Sign(int a)
{
    if(a>0) return 1;
    else return 0;
}

另外,如果你得到不准确的结果,你可以尝试在浮点数而不是整数中进行裁剪,在这种情况下,你应该将a的类型更改为float或double,并为比较添加一个小的公差,例如if(a > 0.0001f)

只要在start或end中设置了位,剪辑函数就应该执行,因此将IsClippingCandidate更改为or,当结果为零时返回false(两者都没有设置位),否则返回true:

bool IsClippingCandidate(Bits & bits)
{
    Bits zeroBits;
    Bits orredBits = *this | bits;
    if(orredBits == zeroBits) return false;
    else return true;
}

您还可以测试该行是否完全在剪切区域之外,并且可以像这样丢弃:

bool IsInvisible(Bits & bits)
{
    Bits zeroBits;
    Bits andedBits = *this & bits;
    if(andedBits == zeroBits) return false;
    else return true;
}

如果两个点都在给定的剪切线之外,则该线不可见。