整理一下最近使用的几何计算
- 直线与X轴夹角:
-
1 /// <summary> 2 /// 求两点基于X轴所成角度 3 /// </summary> 4 /// <param name="x1"></param> 5 /// <param name="y1"></param> 6 /// <param name="x2"></param> 7 /// <param name="y2"></param> 8 /// <returns></returns> 9 public static double CalulateXYAnagle(double x1, double y1, double x2, double y2) 10 { 11 double x = x2 - x1; 12 double y = y2 - y1; 13 double angle = Math.Atan2(y, x);//返回的是弧度。 14 angle = angle * 180.0 / Math.PI;//将弧度转换成角度 15 if (angle < 0) 16 { 17 angle = 360 + angle; 18 } 19 return angle; 20 }
起初有误差,是因为没有弄清楚Math.Atan与Math.Atan2区别,其中Atan值域是从-90~90,也就是它只处理一四象限;Atan2值域是从-180~180,也就是四个象限。
矢量角度:
矢量V(x, y)的角度定义为从坐标系X轴正向旋转到矢量V所转过的角度,逆时针时为正,顺时针为负,规定零矢量的角度为0。矢量角度为:
angle = acos(x / |V|),得到的角度范围为0到π
angle = asin(y / |V|),得到的角度范围为-π/2到π/2
angle = atan(y / x),得到的角度范围为-π/2到π/2
angle = atan2(y, x),得到的角度范围为-π到π
- 线段偏移算法:
1 /// <summary> 2 /// 根据两点形成直线,同时向两边偏移出两条新直线 3 /// </summary> 4 /// <param name="startPoint">直线起点</param> 5 /// <param name="endPoint">直线终点</param> 6 /// <param name="distance">偏移距离</param> 7 /// <param name="startR">右边起点</param> 8 /// <param name="endR">右边终点</param> 9 /// <param name="startL">左边起点</param> 10 /// <param name="endL">左边终点</param> 11 public static void GetOffsetLine(MxDrawPoint startPoint, MxDrawPoint endPoint, double distance, out MxDrawPoint startR, out MxDrawPoint endR, out MxDrawPoint startL, out MxDrawPoint endL) 12 { 13 //左右没有明确的定义 14 //右边 15 double angle = CalulateXYAnagle(startPoint, endPoint); 16 double radian = 0; 17 radian = (angle + 90) * (Math.PI / 180); 18 double x = startPoint.x + distance * Math.Cos(radian); 19 double y = startPoint.y + distance * Math.Sin(radian); 20 double z = startPoint.z; 21 startR = new MxDrawPoint() { x = x, y = y, z = z }; 22 x = endPoint.x + distance * Math.Cos(radian); 23 y = endPoint.y + distance * Math.Sin(radian); 24 z = endPoint.z; 25 endR = new MxDrawPoint() { x = x, y = y, z = z }; 26 //左边 27 radian = (angle - 90) * (Math.PI / 180); 28 x = startPoint.x + distance * Math.Cos(radian); 29 y = startPoint.y + distance * Math.Sin(radian); 30 z = startPoint.z; 31 startL = new MxDrawPoint() { x = x, y = y, z = z }; 32 x = endPoint.x + distance * Math.Cos(radian); 33 y = endPoint.y + distance * Math.Sin(radian); 34 z = endPoint.z; 35 endL = new MxDrawPoint() { x = x, y = y, z = z }; 36 }
- 两条直线的交点:
1 /// <summary> 2 /// 计算两条直线的交点 3 /// </summary> 4 /// <param name="p1">p1与p2构成直线</param> 5 /// <param name="p2">p1与p2构成直线</param> 6 /// <param name="p3">p3与p4构成直线</param> 7 /// <param name="p4">p3与p4构成直线</param> 8 /// <param name="intersectPoint">交点</param> 9 /// <returns>是否存在</returns> 10 public static bool GetIntersectPoint(MxDrawPoint p1, MxDrawPoint p2, MxDrawPoint p3, MxDrawPoint p4, out MxDrawPoint intersectPoint) 11 { 12 bool Isintersect = false; 13 intersectPoint = new MxDrawPoint(); 14 double num = (p4.y - p3.y) * (p3.x - p1.x) - (p4.x - p3.x) * (p3.y - p1.y); 15 // 如果分母为0 则平行或共线, 不相交 16 double denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y); 17 if (denom == 0) 18 { 19 return false; 20 } 21 else 22 { 23 intersectPoint.x = p1.x + (p2.x - p1.x) * num / denom; 24 intersectPoint.y = p1.y + (p2.y - p1.y) * num / denom; 25 Isintersect = true; 26 } 27 return Isintersect; 28 }
- 三维空间线段,求线段上任意一点的Z值:
1 /// <summary> 2 /// 根据起始点,结束点求任意点Z值 3 /// </summary> 4 /// <param name="startPt">起始点</param> 5 /// <param name="centerPt">线上的点</param> 6 /// <param name="endPt">结束点</param> 7 /// <returns>返回线上的点的Z值</returns> 8 public static double CalculateZValue(MxDrawPoint startPt, MxDrawPoint centerPt, MxDrawPoint endPt) 9 { 10 double z = 0; 11 if (startPt != null && endPt != null && centerPt != null) 12 { 13 double xie_c = VectorHelp.Distance(startPt, endPt);//计算两点距离 14 double xie_d = VectorHelp.Distance(startPt, centerPt);//计算两点距离 15 double di_c = endPt.z - startPt.z; 16 z = (xie_d * di_c) / xie_c; //求得最近点的Z值 17 z += startPt.z; 18 } 19 else 20 { 21 z = 0; 22 } 23 return z; 24 }
这里自己写通过比例算的,计算的结果跟CAD上捕捉结果一致。还有另外的插值算法计算。可惜我是没搞懂。
这里的算法都是从网络上找到,在通过自己整理。