CAD二次开发 学习笔记(2)
作者:互联网
CAD二次开发 学习笔记(2)
三点法画圆的预备知识(点径法和两点法相对比较简单,不作详述):
思路:
- 已知三个点:p1点p2点p3点
- 求出两个向量v1(p1-p2),v2(p2-p3);
- 上述两个向量叉乘,得到圆所在平面的法向量n=v1×v2;
- 上述两个向量分别和n叉乘,得到两条直径的方向向量n1=v1×n,n2=v2×n;
- 求出两个中点m1(p1,p2之间)m2(p2,p3之间);
- 根据两个中点和两个方向向量,得到两个直线的点向式方程L1,L2;
- 联立两个方程,求出交点(也就是圆心)的坐标表达式
两个点向式方程
联立求出圆心坐标表达式
注意事项:
上述表达式中,分母可能为0;
如果圆的平面在XY平面,那么z坐标表达式的分母则为0,会导致错误;
有两种解决方案(等效的):
方案一:
在使用坐标表达式之前对分母进行判定,如果分母为0,则表示该坐标为0,而不用调用坐标表达式;
方案二:
使用圆所在平面的法向量进行判定,如果法向量的x,y坐标都是0,说明圆所在平面为xy平面,那么z就可以直接赋值0,而不用调用坐标表达式;
三种画圆的方法及其实现
[CommandMethod("circleTest")]
public void CircleTest()
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
//点径法创建圆
Point3d center = new Point3d(10, 10, 0);
Circle circle1 = CreatCircle(center, 30);
circle1.ColorIndex = 1;
DBPoint dbCenter = new DBPoint(center);
btr.AppendEntity(circle1);
tr.AddNewlyCreatedDBObject(circle1, true);
btr.AppendEntity(dbCenter);
tr.AddNewlyCreatedDBObject(dbCenter, true);
//两点法创建圆
Point3d point1 = new Point3d(300, 300, 0);
Point3d point2 = new Point3d(200, 200, 0);
DBPoint dbPoint1 = new DBPoint(point1);
DBPoint dbPoint2 = new DBPoint(point2);
Circle circle2 = CreatCircle(point1, point2);
circle2.ColorIndex = 2;
btr.AppendEntity(circle2);
tr.AddNewlyCreatedDBObject(circle2, true);
btr.AppendEntity(dbPoint1);
tr.AddNewlyCreatedDBObject(dbPoint1, true);
btr.AppendEntity(dbPoint2);
tr.AddNewlyCreatedDBObject(dbPoint2, true);
//三点法创建圆
Point3d p1 = new Point3d(100, 0, 0);
Point3d p2 = new Point3d(200, 0, 0);
Point3d p3 = new Point3d(100, 100, 0);
DBPoint dbP1 = new DBPoint(p1);
DBPoint dbP2 = new DBPoint(p2);
DBPoint dbP3 = new DBPoint(p3);
Circle circle3 = CreatCircle(p1, p2, p3);
circle3.ColorIndex = 3;
btr.AppendEntity(circle3);
tr.AddNewlyCreatedDBObject(circle3, true);
btr.AppendEntity(dbP1);
tr.AddNewlyCreatedDBObject(dbP1, true);
btr.AppendEntity(dbP2);
tr.AddNewlyCreatedDBObject(dbP2, true);
btr.AppendEntity(dbP3);
tr.AddNewlyCreatedDBObject(dbP3, true);
db.Pdmode = 34;
db.Pdsize = 1;
tr.Commit();
}
}
//点径法创建圆
public Circle CreatCircle(Point3d center, double radius)
{
return new Circle(center, Vector3d.ZAxis, radius);
}
//两点法创建圆
public Circle CreatCircle(Point3d point1, Point3d point2)
{
Point3d center = MiddlePoint(point1, point2);
double radius = center.DistanceTo(point2);
return new Circle(center, Vector3d.ZAxis, radius);
}
//三点法创建圆
public Circle CreatCircle(Point3d point1, Point3d point2, Point3d point3)
{
if (IsCollinear(point1, point2, point3)) return new Circle();
Vector3d v1 = point1.GetVectorTo(point2);
Vector3d v2 = point2.GetVectorTo(point3);
Vector3d n = v1.CrossProduct(v2);
Point3d p1 = MiddlePoint(point1, point2);
Point3d p2 = MiddlePoint(point2, point3);
Vector3d n1 = v1.CrossProduct(n);
Vector3d n2 = v2.CrossProduct(n);
double x = Math.Abs(n1.Y * n2.X - n2.Y * n1.X) < 0.000001 ? 0 : (p2.Y * n1.X * n2.X - p1.Y * n1.X * n2.X + p1.X * n1.Y * n2.X - p2.X * n2.Y * n1.X) / (n1.Y * n2.X - n2.Y * n1.X);
double y = Math.Abs(n1.X * n2.Y - n2.X * n1.Y) < 0.000001 ? 0 : (p2.X * n1.Y * n2.Y - p1.X * n1.Y * n2.Y + p1.Y * n1.X * n2.Y - p2.Y * n2.X * n1.Y) / (n1.X * n2.Y - n2.X * n1.Y);
double z = Math.Abs(n1.Y * n2.Z - n2.Y * n1.Z) < 0.000001 ? 0 : (p2.Y * n1.Z * n2.Z - p1.Y * n1.Z * n2.Z + p1.Z * n1.Y * n2.Z - p2.Z * n2.Y * n1.Z) / (n1.Y * n2.Z - n2.Y * n1.Z);
Point3d center = new Point3d(x, y, z);
double radius = point1.DistanceTo(center);
return new Circle(center, Vector3d.ZAxis, radius);
}
//判断三点是否共线
public bool IsCollinear(Point3d point1, Point3d point2, Point3d point3)
{
Vector3d vector1 = point1.GetVectorTo(point2);
Vector3d vector2 = point2.GetVectorTo(point3);
double angle = vector1.GetAngleTo(vector2);
if (Math.Abs(angle) < 0.0001 || Math.Abs(angle - Math.PI) < 0.000001) return true;
return false;
}
//求两点的中点
public Point3d MiddlePoint(Point3d point1, Point3d point2)
{
return new Point3d((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2, (point1.Z + point2.Z) / 2);
}
运行结果
角度测试
- GetAngleTo的返回值为弧度值;
- 返回值介于0-180度(0-π)之间;
- 不会有负值;
[CommandMethod("AngleTest")]
public void AngleTest()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ed.WriteMessage($"Vector3d.XAxis.GetAngleTo(Vector3d.YAxis):{Vector3d.XAxis.GetAngleTo(Vector3d.YAxis)}\n");
ed.WriteMessage($"Vector3d.XAxis.GetAngleTo(Vector3d.YAxis):{Vector3d.XAxis.GetAngleTo(Vector3d.YAxis) * 180 / Math.PI}\n");
ed.WriteMessage($"Vector3d.XAxis.GetAngleTo(-Vector3d.YAxis):{Vector3d.XAxis.GetAngleTo(-Vector3d.YAxis)}\n");
ed.WriteMessage($"Vector3d.XAxis.GetAngleTo(-Vector3d.YAxis):{Vector3d.XAxis.GetAngleTo(-Vector3d.YAxis) * 180 / Math.PI}\n");
ed.WriteMessage($"new Vector3d(1,1,0).GetAngleTo(Vector3d.XAxis):{new Vector3d(1, 1, 0).GetAngleTo(Vector3d.XAxis)}\n");
ed.WriteMessage($"new Vector3d(1,1,0).GetAngleTo(Vector3d.XAxis):{new Vector3d(1, 1, 0).GetAngleTo(Vector3d.XAxis) * 180 / Math.PI}\n");
ed.WriteMessage($"new Vector3d(1,1,0).GetAngleTo(-Vector3d.XAxis):{new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.XAxis)}\n");
ed.WriteMessage($"new Vector3d(1,1,0).GetAngleTo(-Vector3d.XAxis):{new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.XAxis) * 180 / Math.PI}\n");
ed.WriteMessage($"new Vector3d(1, 1, 0).GetAngleTo(Vector3d.YAxis):{new Vector3d(1, 1, 0).GetAngleTo(Vector3d.YAxis)}\n");
ed.WriteMessage($"new Vector3d(1, 1, 0).GetAngleTo(Vector3d.YAxis):{new Vector3d(1, 1, 0).GetAngleTo(Vector3d.YAxis) * 180 / Math.PI}\n");
ed.WriteMessage($"new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.YAxis):{new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.YAxis)}\n");
ed.WriteMessage($"new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.YAxis):{new Vector3d(1, 1, 0).GetAngleTo(-Vector3d.YAxis) * 180 / Math.PI}\n");
}
运行结果
标签:Vector3d,GetAngleTo,笔记,n1,二次开发,new,n2,Point3d,CAD 来源: https://www.cnblogs.com/zhangdezhang/p/16183266.html