C-8 圆、圆弧与平面
圆的定义
- 定义圆心以及半径就可以了
圆弧的定义
- 定义圆心、起始点和结束点
- 起始点和结束点到圆心的距离必须要一样
- 连接方式一般是逆时针连接(一般来说外轮廓是逆时针连接,内轮廓是顺时针)
平面的定义
- 平面定义有很多方式,最常用的是定义平面上的一个点和平面的法向量,occ也采用这样的定义方式
- 当然也可以定义平面上不共线的三个点来定义平面
- 以下是利用occ的接口进行定义
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Dir.hxx>
// 定义原点和法向量
gp_Pnt origin(0.0, 0.0, 0.0); // 原点
gp_Dir normal(0.0, 0.0, 1.0); // 法向量
// 创建平面
gp_Pln plane(origin, normal);
线与圆的位置关系,相切、相离、相交
- 这个问题就是点与线的问题,求圆心与线的距离,并和半径进行判断是否相切、相离、相交
- 和某个点是否落在圆内这一问题等价
离散化圆弧,将某段圆弧离散化为一段段的线段
//输入的是向量的两个点,求该向量与x轴的角度,角度大小是0到2*pi
double angle(Point center,Point point) {
if (center == point) return -1;
double theangle = asin((point.y - center.y)/point.distance(center));
//第一象限不用处理
if ((point.x - center.x) >= 0) {
if (theangle < 0) theangle = theangle + M_PI*2;//第四象限
}
else {
theangle = M_PI - theangle;//第二,第三象限
}
return theangle;
}
//给定角度与需要离散化的段数n对圆弧进行离散化
std::vector<Point> discret(Point Arc_center, double r, double angle_begin, double angle_end, int n) {
std::vector<Point> Points;
if (abs(angle_begin - angle_end)<0.01) return Points;
//std::cout << angle_begin << "," << angle_end << std::endl;
double small_angle = (angle_end - angle_begin) / n;
for (int i = 0; i <= n; i++) {
Point p(Arc_center.x+r * std::cos(angle_begin + small_angle * i), Arc_center.y + r * std::sin(angle_begin + small_angle * i), Arc_center.z );
Points.push_back(p);
}
return Points;
}
//输入圆弧的圆心与起始点、结束点
std::vector<Point> discret(Point Arc_center, Point Arc_begin,Point Arc_end) {
int n = 16;
if (Arc_begin == Arc_end) return discret(Arc_center, Arc_center.distance(Arc_begin), 0, 2 * M_PI, n);
double angle_begin = angle(Arc_center, Arc_begin);
double angle_end = angle(Arc_center, Arc_end);
//分两种情况,要是结束点的角度比起始点大,就按部就班的离散化
//若结束角度比起始角度小,那就分割成两端离散化,一段是起始点到2*pi点,以及2*pi点到结束点
if(angle_end>angle_begin) return discret(Arc_center, Arc_center.distance(Arc_begin), angle_begin, angle_end, n);
else if (angle_end < angle_begin) {
double r = Arc_center.distance(Arc_begin);
std::vector<Point> Points1 = discret(Arc_center , r , angle_begin, 2 * M_PI, n / 2);
std::vector<Point> Points2 = discret(Arc_center , r , 0 ,angle_end, n / 2);
if(Points1.size()>0) Points1.pop_back();
Points1.insert(Points1.end(), Points2.begin(), Points2.end());
return Points1;
}
}
- 利用该代码进行离散化绘制的圆弧
- 外围是利用clipper生成的轮廓线
圆与直线的交点
- 利用参数直线和参数圆进行求交
//求由线段延伸的直线与圆的交点,且该交点是离该线段较近的一个点
//p1,p2是线上面的两个点
Point circleLineIntersection(Point center, double radius, Point p1, Point p2) {
double a = p1.x * p1.x + p2.x * p2.x - 2 * p1.x * p2.x + p1.y * p1.y + p2.y * p2.y - 2 * p1.y * p2.y;
double b = -2 * center.x * p1.x + 2 * center.x * p2.x + 2 * p1.x * p2.x - 2 * p2.x * p2.x - 2 * center.y * p1.y + 2 * center.y * p2.y + 2 * p1.y * p2.y - 2 * p2.y * p2.y;
double c = center.x * center.x + center.y * center.y + p2.x * p2.x - 2 * center.x * p2.x + p2.y * p2.y - 2 * center.y * p2.y - radius * radius;
double d = b * b - 4 * a * c;
double t = (-b + sqrt(d)) / (2 * a);
if (t < 1 && t>0) {
Point p(p1.x * t + p2.x * (1 - t), p1.y * t + p2.y * (1 - t), 0);
return p;
}
else {
t = (-b - sqrt(d)) / (2 * a);
Point p(p1.x * t + p2.x * (1 - t), p1.y * t + p2.y * (1 - t), 0);
return p;
}
}
其余问题
-
两个圆的位置关系,如果相交、相切如何求交点?
- 相切的话很容易求交点
- 相交的话利用参数圆求交点
-
点A在平面内还是平面上,平面下?
- 利用法向量和起始点到点A的向量进行点乘。若是等于0就在平面上,若是小于0就在平面下,若是大于0就是平面上
-
除圆之外还有三维的球,球和平面的截面圆如何计算等等。
相切的话很容易求交点
-
相交的话利用参数圆求交点
-
点A在平面内还是平面上,平面下?
- 利用法向量和起始点到点A的向量进行点乘。若是等于0就在平面上,若是小于0就在平面下,若是大于0就是平面上
-
除圆之外还有三维的球,球和平面的截面圆如何计算等等。