如何在C ++中表示线段的矢量方程?

时间:2015-07-07 15:48:56

标签: c++ vector graphics line

我正在使用计算机图形学。

我想用两个端点表示一行,然后我希望我的Line2d类有一个返回Vector2d对象的方法。

假设我有以下几个类:

struct Point2d
{
    int x;
    int y;
};

然后,我可以使用两个点轻松表示一个线段:

class LineSegment2d
{
private:
    Point2d start;
    Point2d end;
public:
    ...
    ...
};

根据定义,矢量由幅度和方向组成。

class Vector2d
{
private:
    Point2d p;
public:
    double Magnitude(void);
    Point Component(void);
    Vector2d Normal();
    Vector2d & Add(Vector & rhs);
    Vector2d & Subtract(Vector & rhs);
    Vector2d & Multiply(int scalar);
    int DotProduct(Vector2d rhs);
    Vector2d & CrossProduct(Vector2d rhs);
};

Point2d的一个对象足以表示向量。例如,向量的大小= sqrt(p.x*p.x + p.y*p.y);。并且,p.xp.y共同代表了方向。

另一方面,我们知道通过(x0,y0,z0)的直线的矢量方程为r =r0 + tv 哪里, r是主题行的向量。 r0是一个位置向量,指向点(x0, y0, z0)的方向。由于r0是位置向量,显然r0的原点是(0,0,0)t是任何实数编号的值,其中−∞<t<∞ –v是一个与我们的主题直线平行的向量。

P(1, 3, 2)Q(-4, 3, 0)之间的线段的矢量方程:

根据上面的公式,线PQ的矢量方程可以是

r =<1,3,2> + tv 

或,

r =<-4,3,0> + tv

连接两个点PQ的向量是

PQ  = <(-4-1), (3-3), (0-2)>
    = <-5, 0, -2>

而且,这个向量肯定与我们的主题行平行。

所以,我们可以写,

r   =<1, 3, 2> + t <-5, 0, -2>
    =<1, 3, 2>+<-5t, 0, -2t>
    = <(1-5t), (3+0), (2-2t)>
    =<1-5t, 3, 2-2t>

根据线段的矢量方程,我认为,我的Vector类应该如下所示:

class LineVector2d
{
private:
    Vector2d v;
    double t;
public:
    ..........
};

这是正确的表示吗?

如果是这样,我如何计算/设置/找到t的值?

6 个答案:

答案 0 :(得分:4)

many forms of line representation

如果你的意思是行(不是段),那么,你可能会发现使用包含BasePoint和UnitDirectionVector的类/结构很方便。

对于线段,请选择(Point pt0, Point pt1)表单和(Point pt, Vector v = pt1 - pt0)表单。

第二个更适合参数化方法,如, X = P0.X + t * D.X等。

答案 1 :(得分:1)

如果要将线段转换为矢量,则必须注意转换没有“通用语义”,您可以自行定义转换的含义。也就是说,我假设你想要一个具有相同(欧几里得)范数的向量作为线段的长度并指向相同的方向,即类似这样的东西:

class LineSegment2d
{
   ....
   Vector2d getVector() const {
      return Vector2d(end) - Vector2d(start);
   }
};

换句话说,将线段偏移到坐标系的原点。然后可以将终点转换为矢量。

编辑:在了解了你想要这个的原因之后,你可能正在寻找另一种表现形式

class LineSegment2d
{
   ....
   Vector2d getVector() const {
      return Vector2d(end);
   }
};

这将为每个线段提供一个向量:终点。如果您的多边形由连接的线段组成,则会为您提供多边形中的所有顶点。

答案 2 :(得分:1)

使用问题中的线段表示。

我会为包含起点LS(a,b)和终点a的线段写b

现在给出两个这样的段LS(a,b)LS(c,d)相交(在你的上下文中,一个来自剪裁多边形,一个来自被剪裁的多边形;我假设你知道如何确定这个) 。

您似乎想要回答的是,如果此交叉点在穿过边LS(c,d)LS(a,b)到达多边形内部。

为此,确定线段方向之间的角度就足够了。这与向量v = b-aw = d-c之间的角度相同。

此外,你甚至不需要角度,你只需要看角度是正还是负;所以看看向量w-v。如果LS(c,d)越过LS(a,b)到内部,则此向量将位于下半平面中。如果LS(c,d)LS(a,b)交叉到外部,则此向量将位于上半平面中。

确定下半平面的上半部分意味着查看end-start的第二个坐标。

为文本墙道歉,但mathjax在此网站上似乎不活跃。也没有代码,但我相信(如果我没有犯任何错误)我提到的所有操作都很容易翻译成代码。

答案 3 :(得分:1)

如果你想要非常数学,也许这会有所帮助:https://en.wikipedia.org/wiki/Homogeneous_coordinates

在2d中,这意味着位置是(x,y,1)和方向(dx,dy,0)。其原因是投影,这在2d中很少见,但在3d中很常见。

所以试着回答:一直使用4个分量向量。位置w = 1,方向a w = 0。

尝试使用基于两点A和B的线,两者都有w = 1。从A到B的向量是B-A,其最终为w = 0。

除非您最终优化特殊情况,否则您在代码中使用的内容确实很重要。只需寻找最小的数据结构。开始和结束应该没问题。

也许想想索引:所有顶点的平面数组和每一行只是顶点数组中的两个索引。

答案 4 :(得分:1)

我认为由于以下内容存在一些混淆

  

根据定义,矢量由幅度和方向组成。

表示矢量的方法不止一种。我认为在你的问题中,你的意思是矢量可以用幅度(标量)和表示方向的单位矢量来表示。向量可以只是一个有序的三元组(三维),表示幅度(sqrt(x^2 + y^2 + z^2))和来自原点的方向。

我认为你的问题的答案是,你不需要计算t。如果我弄错了,请纠正我,但我认为你将t解释为量级?您可以使用vsqrt(x^2 + y^2 + z^2)计算出来,但v可以将量值和方向同时保持为有序三元组。

修改

template <typename T>
struct Point2d
{
    T x;
    T y;

    Point2d operator + (const Point2d<T>& rhs) const
    {
        return Point2d<T>{x + rhs.x, y + rhs.y};
    }
    Point2d operator - (const Point2d<T>& rhs) const
    {
        return Point2d<T>{x - rhs.x, y - rhs.y};
    }
    // ...

    Point2d operator * (const T value) const
    {
        return Point2d<T>{x*value, y*value};
    }
    Point2d operator / (const T value) const
    {
        return Point2d<T>{x/value, y/value};
    }
    // ...
};

template <typename T>
class Vector2d
{
private:
    Point2d<T> p;
public:
    Vector2d(const Point2d<T>& point) : p{point} {}

    /*double Magnitude();
    Point2d<T> Component();
    Vector2d Normal();
    int DotProduct(Vector2d rhs);
    Vector2d& CrossProduct(Vector2d rhs);*/

    Vector2d operator + (const Vector2d<T>& rhs) const
    {
        return p + rhs.p;
    }
    Vector2d operator - (const Vector2d<T>& rhs) const
    {
        return p - rhs.p;
    }
    // ...

    Vector2d operator * (const T value) const
    {
        return p*value;
    }
    Vector2d operator / (const T value) const
    {
        return p/value;
    }
    // ...
};

template <typename T>
class LineVector2d
{
private:
    Point2d<T>  p;
    Vector2d<T> v;

public:
    LineVector2d() = default;
    LineVector2d(const Point2d<T>& point, const Vector2d<T>& direction) : p{point}, v{direction} {}

    /// Returns the point on the line for the time/value `t`
    Point2d<T> valueAt(T t)
    {
        return p + v*t;
    }
};

答案 5 :(得分:0)

您对班级LineSegment2d的陈述很好。但是类Vector2d的表示是不正确的。这是因为您只考虑那些通过原点的矢量。 2d平面上的矢量可以用与3d空间中相同的方式用3个分量表示。矢量的3个分量是:方向,幅度和它通过的A点。如果我们为3d空间定义x,y和z轴,那么对于xy平面中的一个点,z分量等于0.此外,3d空间中的方向以方向余弦的形式定义(即,余弦的余弦。矢量和轴之间的角度)。因此,对于x-y平面中的向量,向量和z轴之间的角度余弦等于零(因为角度= 90度)。