这是rs_vector.cpp文件,实现了rs_vector.h中声明的RS_Vector和RS_VectorSolutions类的所有成员函数。以下是详细的实现分析:
文件概述
- 实现内容:提供向量和向量集合的完整实现
- 数学依赖:使用标准C++数学库和Qt的QPointF
- 精度处理 :包含各种容差检查(
RS_TOLERANCE)
RS_Vector 类实现详解
1. 构造函数实现
cpp
RS_Vector::RS_Vector(double vx, double vy, double vz):
x(vx), y(vy), z(vz), valid(true) {}
- 坐标构造:设置x,y,z并标记为有效
cpp
RS_Vector::RS_Vector(double angle):
x(std::cos(angle)), y(std::sin(angle)), valid(true) {}
- 角度构造:创建单位方向向量
cpp
RS_Vector::RS_Vector(bool valid): valid(valid) {}
- 有效性构造:仅设置有效性标志
2. 基本设置方法
cpp
void RS_Vector::set(double vx, double vy, double vz) {
x = vx; y = vy; z = vz; valid = true;
}
- 直接设置坐标值
cpp
void RS_Vector::setPolar(double radius, double angle) {
x = radius * std::cos(angle);
y = radius * std::sin(angle);
z = 0.0;
valid = true;
}
- 极坐标设置: x = r ⋅ cos ( θ ) x = r \cdot \cos(\theta) x=r⋅cos(θ), y = r ⋅ sin ( θ ) y = r \cdot \sin(\theta) y=r⋅sin(θ)
3. 几何计算实现
向量长度计算
cpp
double RS_Vector::magnitude() const {
if (valid)
return std::hypot(std::hypot(x, y), z);
return 0.0;
}
- 使用
std::hypot避免数值溢出
角度计算
cpp
double RS_Vector::angle() const {
return RS_Math::correctAngle(std::atan2(y,x));
}
double RS_Vector::angleTo(const RS_Vector& v) const {
return (v-(*this)).angle();
}
atan2计算方位角,经过角度修正angleTo计算两点连线与X轴夹角
三点夹角计算
cpp
double RS_Vector::angleBetween(const RS_Vector& v1, const RS_Vector& v2) const {
RS_Vector const vStart(v1 - (*this));
RS_Vector const vEnd(v2 - (*this));
return RS_Math::correctAngle(
std::atan2(vStart.x * vEnd.y - vStart.y * vEnd.x,
vStart.x * vEnd.x + vStart.y * vEnd.y));
}
- 使用向量叉积和点积公式: θ = atan2 ( v 1 × v 2 , v 1 ⋅ v 2 ) \theta = \text{atan2}(v_1 \times v_2, v_1 \cdot v_2) θ=atan2(v1×v2,v1⋅v2)
4. 几何变换实现
旋转实现
cpp
RS_Vector& RS_Vector::rotate(const RS_Vector& angleVector) {
double x0 = x * angleVector.x - y * angleVector.y;
y = x * angleVector.y + y * angleVector.x;
x = x0;
return *this;
}
- 使用旋转矩阵: [ cos θ − sin θ sin θ cos θ ] \begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} [cosθsinθ−sinθcosθ]
- 如果angleVector是单位向量,表示旋转角度
镜像实现
cpp
RS_Vector& RS_Vector::mirror(const RS_Vector& axisPoint1,
const RS_Vector& axisPoint2) {
RS_Vector direction(axisPoint2-axisPoint1);
double a= direction.squared();
if(a<RS_TOLERANCE2) return *this; // 轴太短
RS_Vector ret= axisPoint1 + direction* dotP(*this - axisPoint1,direction)/a;
*this = ret + ret - *this;
return *this;
}
- 计算点在线上的投影
- 镜像公式: P ′ = 2 × proj − P P' = 2 \times \text{proj} - P P′=2×proj−P
剪切变换
cpp
RS_Vector& RS_Vector::shear(double k) {
x += k * y;
return *this;
}
- x坐标受y坐标影响: x ′ = x + k ⋅ y x' = x + k \cdot y x′=x+k⋅y
5. 运算符重载实现
算术运算
cpp
RS_Vector RS_Vector::operator * (const RS_Vector& v) const {
return {x * v.x, y * v.y, z * v.z};
}
RS_Vector RS_Vector::operator / (const RS_Vector& v) const {
if(fabs(v.x)> RS_TOLERANCE && fabs(v.y)>RS_TOLERANCE)
return {x / v.x, y / v.y, z / v.z};
return *this; // 防止除以零
}
- 逐分量运算
- 除法有容差检查
比较运算
cpp
bool RS_Vector::operator == (const RS_Vector& v) const {
return valid && v.valid
&& RS_Math::equal(x, v.x)
&& RS_Math::equal(y, v.y)
&& RS_Math::equal(z, v.z);
}
- 严格相等,考虑有效性和容差
6. 静态方法实现
最小/最大值向量
cpp
RS_Vector RS_Vector::minimum(const RS_Vector& v1, const RS_Vector& v2) {
if (!v2) return v1;
if (!v1) return v2;
return {std::min(v1.x, v2.x),
std::min(v1.y, v2.y),
std::min(v1.z, v2.z)};
}
- 对每个分量取最小值
叉积计算
cpp
RS_Vector RS_Vector::crossP(const RS_Vector& v1, const RS_Vector& v2) {
return {v1.y*v2.z - v1.z*v2.y,
v1.z*v2.x - v1.x*v2.z,
v1.x*v2.y - v1.y*v2.x};
}
- 标准3D向量叉积公式
RS_VectorSolutions 类实现详解
1. 存储管理
cpp
void RS_VectorSolutions::alloc(size_t num) {
if(num <= vector.size()){
vector.resize(num);
} else {
vector.insert(vector.end(), num - vector.size(), RS_Vector(false));
}
}
- 动态调整向量数组大小
2. 安全访问
cpp
RS_Vector RS_VectorSolutions::get(size_t i) const {
if(i < vector.size())
return vector.at(i);
return {}; // 返回无效向量
}
- 带边界检查的访问方法
3. 最近点搜索
cpp
RS_Vector RS_VectorSolutions::getClosest(const RS_Vector &coord,
double* dist, size_t* index) const {
double curDist{0.};
double minDist = RS_MAXDOUBLE;
RS_Vector closestPoint{false};
int pos(0);
for (size_t i=0; i<vector.size(); i++) {
if (vector[i].valid) {
curDist = (coord - vector[i]).squared(); // 用平方距离避免开方
if (curDist < minDist) {
closestPoint = vector[i];
minDist = curDist;
pos = i;
}
}
}
if (dist) *dist = std::sqrt(minDist);
if (index) *index = pos;
return closestPoint;
}
- 平方距离优化性能
- 返回最近点、距离和索引
4. 批量变换
cpp
void RS_VectorSolutions::rotate(const RS_Vector& center, double ang) {
const RS_Vector angleVector(ang);
for (auto& vp: vector) {
if (vp.valid) {
vp.rotate(center, angleVector);
}
}
}
- 对集合中所有有效向量应用相同变换
关键算法和技术细节
1. 数值稳定性处理
cpp
if(fabs(v.x)> RS_TOLERANCE && fabs(v.y)>RS_TOLERANCE)
- 所有除法操作都检查除数是否足够大
2. 性能优化
- 使用平方距离比较避免开方运算
- 使用
std::hypot避免数值溢出 - 移动语义减少复制
3. 错误处理
cpp
if(a<RS_TOLERANCE2) {
ret = RS_Vector{false};
return ret;
}
- 对无效几何条件返回无效向量
4. 数学精度
- 使用
RS_Math::equal进行浮点数比较 - 使用
RS_Math::correctAngle进行角度规范化
使用注意事项
- 有效性检查:始终检查向量是否有效
- 容差处理:几何计算包含容差处理
- 性能考虑 :批量操作时使用
RS_VectorSolutions - 坐标系统:Z坐标通常为0(2D CAD)
这个实现文件提供了完整、健壮且高效的向量运算功能,是LibreCAD几何计算的核心。