我正在申请学校,我必须点击特定的对象。
编辑:这是在2D中进行的
我有一个矩形,我用X旋转这个矩形。 矩形的旋转使我的矩形(x,y,宽度,高度)成为旋转矩形周围的新矩形。
http://i.stack.imgur.com/MejMA.png (请原谅我糟糕的油漆技巧)
黑线描述旋转的矩形,红线是我的新矩形。 我需要找出我的鼠标是否在黑色矩形内。无论我做什么旋转,我都有一个函数来获取黑色矩形每个角的(X,Y)。
现在我正在尝试实施此Check if point is within triangle (The same side technique)。
所以我可以检查我的鼠标是否在每个三角形内,或者是否可以检查我的鼠标是否在旋转的矩形中更好。
我几乎理解三角形文档中的所有内容,但我根本没有数学技能来计算两个交叉产品的交叉积和点积。
这应该是交叉产品:
a×b = | a | | B | sin(θ)n
| A |是矢量a的大小(长度)
| B |是矢量b的幅度(长度)
θ是a和b之间的角度
n是与a和b
成直角的单位向量
但是如何计算a和b的单位向量? 我如何获得向量的大小?
编辑: 我忘了要求计算2个交叉产品之间的dotproduct。
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
谢谢大家的帮助,我想我现在已经掌握了它,我希望我能接受多个答案。
答案 0 :(得分:0)
矢量的大小是长度。在C ++中,如果有一个表示为double[3]
的向量,则可以通过
#include <math.h>
double a_length = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
但是,我明白你真正想要的是跨产品?在这种情况下,您可能想直接计算它。结果是矢量,即c = a×b。 你可以这样编码,例如:
double c[3];
c[0] = ( a[2]*b[3] - a[3]*b[2] );
c[1] = ( a[3]*b[1] - a[1]*b[3] );
c[2] = ( a[1]*b[2] - a[2]*b[1] );
答案 1 :(得分:0)
您可以按sqrt(x*x + y*y)
计算向量的大小。您还可以更简单地计算crossproduct:a x b = a.x * b.y - a.y * b.x
。通过计算所有4个三角形的面积,可以检查点是否在三角形内部。例如,a是源三角形的面积,b,c,d是其他区域。如果b + c + d = a那么该点就在里面。计算三角形的面积很简单:我们有矢量a,b是三角形的顶点。然后三角形区域为(a x b) / 2
答案 2 :(得分:0)
如果你不得不进行大量检查,我会回避使用平方根功能:它们的计算成本很高。为了进行比较,只需将所有内容相乘,就可以绕过平方根:
向量的大小=向量的长度
如果vector定义为float [3],则可以按如下方式计算长度:
double magnitude = sqrt( a[0]*a[0] + a[1]*a[1] + a[2]*a[2] );
然而,这在计算上是昂贵的,所以我会使用
double magnitudeSquared = a[0]*a[0] + a[1]*a[1] + a[2]*a[2];
然后修改任何比较计算以使用距离或幅度的平方版本,它将更具性能。
对于交叉产品,请原谅我,如果这个数学是不稳定的,自从我为此编写函数已经过了几年(代码重用很棒,但记住事情很糟糕):
double c[3];
c[0] = ( a[1]*b[2] - a[2]*b[1] );
c[1] = ( a[2]*b[0] - a[0]*b[2] );
c[2] = ( a[0]*b[1] - a[1]*b[0] );
为了简化这一切,我将vec3d放在一个自己的类中,其中一个非常简单的表示形式为:
class vec3d
{
public:
float x, y, z;
vec3d crossProduct(vec3d secondVector)
{
vec3d retval;
retval.x = (this.y * secondVector.z)-(secondVector.y * this.z);
retval.y = -(this.x * secondVector.z)+(secondVector.x * this.z);
retval.z = (this.x * secondVector.y)-(this.y * secondVector.x);
return retval;
}
// to get the unit vector divide by a vectors length...
void normalise() // this will make the vector into a 1 unit long variant of itself, or a unit vector
{
if(fabs(x) > 0.0001){
x= x / this.magnitude();
}
if(fabs(y) > 0.0001){
y= y / this.magnitude();
}
if(fabs(z) > 0.0001){
z = / this.magnitude();
}
}
double magnitude()
{
return sqrt((x*x) + (y*y) + (z*z));
}
double magnitudeSquared()
{
return ((x*x) + (y*y) + (z*z));
}
};
我可以从旧的第二年编码练习中获得更全面的vec3d课程:.h file和.cpp file。
这是一个极简主义的2d实现(做到这一点,请原谅我们的简洁代码,并告诉我是否有错误):
#ifndef VEC2D_H
#define VEC2D_H
#include <iostream>
using namespace std;
class Vec2D {
private:
double x, y;
public:
Vec2D(); // default, takes no args
Vec2D(double, double); // user can specify init values
void setX(double);
void setY(double);
double getX() const;
double getY() const;
double getMagnitude() const;
double getMagnitudeSquared() const;
double getMagnitude2() const;
Vec2D normalize() const;
double crossProduct(Vec2D secondVector);
Vec2D crossProduct(Vec2D secondVector);
friend Vec2D operator+(const Vec2D&, const Vec2D&);
friend ostream &operator<<(ostream&, const Vec2D&);
};
double dotProduct(const Vec2D, const Vec2D);
#endif
#include <iostream>
#include <cmath>
using namespace std;
#include "Vec2D.h"
// Constructors
Vec2D::Vec2D() { x = y = 0.0; }
Vec2D::Vec2D(double a, double b) { x = a; y = b; }
// Mutators
void Vec2D::setX(double a) { x = a; }
void Vec2D::setY(double a) { y = a; }
// Accessors
double Vec2D::getX() const { return x; }
double Vec2D::getY() const { return y; }
double Vec2D::getMagnitude() const { return sqrt((x*x) + (y*y)); }
double Vec2D::getMagnitudeSquared() const { return ((x*x) + (y*y)); }
double Vec2D::getMagnitude2 const { return getMagnitudeSquared(); }
double Vec2d::crossProduct(Vec2D secondVector) { return ((this.x * secondVector.getY())-(this.y * secondVector.getX()));}
Vec2D crossProduct(Vec2D secondVector) {return new Vec2D(this.y,-(this.x));}
Vec2D Vec2D::normalize() const { return Vec2D(x/getMagnitude(), y/getMagnitude());}
Vec2D operator+(const Vec2D& a, const Vec2D& b) { return Vec2D(a.x + b.x, a.y + b.y);}
ostream& operator<<(ostream& output, const Vec2D& a) { output << "(" << a.x << ", " << a.y << ")" << endl; return output;}
double dotProduct(const Vec2D a, const Vec2D b) { return a.getX() * b.getX() + a.getY() * b.getY();}
float calculateSign(Vec2D v1, Vec2D v2, Vec2D v3)
{
return (v1.getX() - v3.getX()) * (v2.getY() - v3.getY()) - (v2.getX() - v3.getX()) * (v1.getY() - v3.getY());
}
bool isPointInsideTriangle(Vec2D point2d, Vec2D v1, Vec2D v2, Vec2D v3)
{
bool b1, b2, b3;
// the < 0.0f is arbitrary, could have just as easily been > (would have flipped the results but would compare the same)
b1 = calculateSign(point2d, v1, v2) < 0.0f;
b2 = calculateSign(point2d, v2, v3) < 0.0f;
b3 = calculateSign(point2d, v3, v1) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
在上面的代码中,如果calculateSign
位于三角形中,您将获得true
返回:)
希望这会有所帮助,如果您需要更多信息或更全面的vec3d或2d课程,请告知我们,我可以发布:)
我添加了一个小的2d-vector类,以显示2d和3d中的差异。
答案 3 :(得分:0)
没有进入矢量的一个简单方法是检查区域。 例如,假设您有一个带角A,B,C,D的矩形。并指出P.
首先计算矩形的面积,只需找到矩形的高度和宽度并乘以。
B D
| /
| /
|/____ C
A
为了计算高度,宽度取一个点让我们说A,找到它与所有其他三个点的距离,即AB,AC,AD第1和第2最小值将是宽度,而height,max将是对角线长度。 现在存储从中获得高度,宽度的点,让我们说这些点是B,C。
现在你知道矩形看起来如何,即
B _____ D
| |
|_____|
A C
然后计算三角形ACP,ABP,BDP,CDP的面积之和(使用heros公式计算矩形区域),如果它等于矩形区域,则点P位于矩形外的其他位置。