曲线处理专贴----我们的[原创]
先发几个简单的例子,抛砖引玉,希望大家也贴上自己的得意之作:)直线打断,模拟Break命令
public static void MyBreakLine()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
//选择直线
PromptEntityOptions opt1 = new PromptEntityOptions("\nselect a line:");
opt1.SetRejectMessage("\nerror!");
opt1.AddAllowedClass(typeof(Line), true);
PromptEntityResult res1 = ed.GetEntity(opt1);
if (res1.Status == PromptStatus.OK)
{
//选择第二打断点
PromptPointOptions opt2 = new PromptPointOptions("\nselect second point:");
opt2.AllowNone = true;
PromptPointResult res2 = ed.GetPoint(opt2);
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Line oldline = (Line)tr.GetObject(res1.ObjectId, OpenMode.ForRead);
List pars = new List();
Point3d pt1 = oldline.GetClosestPointTo(res1.PickedPoint, false);
Point3d pt2 = new Point3d();
pars.Add(oldline.GetParameterAtPoint(pt1));
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
DBObjectCollection objs;
//两种情况
if (res2.Status == PromptStatus.OK)
{
//如果选择了第二点,获取直线上两点的param值,并排序
pt2 = oldline.GetClosestPointTo(res2.Value, false);
pars.Add(oldline.GetParameterAtPoint(pt2));
pars.Sort();
//按param值打断曲线
objs = oldline.GetSplitCurves(new DoubleCollection(pars.ToArray()));
foreach (Line newline in objs)
{
//如果生成的直线起点或终点不是选择的打断点,把它加入数据库
if ((newline.StartPoint != pt1 && newline.StartPoint != pt2) ^ (newline.EndPoint != pt1 && newline.EndPoint != pt2))
{
btr.AppendEntity(newline);
tr.AddNewlyCreatedDBObject(newline, true);
}
}
}
else
{
//如果没有选择第二点,就按第一点打断
objs = oldline.GetSplitCurves(new DoubleCollection(pars.ToArray()));
foreach (Line newline in objs)
{
btr.AppendEntity(newline);
tr.AddNewlyCreatedDBObject(newline, true);
}
}
oldline.UpgradeOpen();
oldline.Erase();
tr.Commit();
}
}
}
所有曲线打断于点
public static void BreakAllCurve()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
//选择曲线
PromptSelectionResult res = ed.GetSelection(new PromptSelectionOptions(), new SelectionFilter(new TypedValue[] { new TypedValue(0, "*Line,Arc,Circle,Ellipse") }));
ObjectId[] ids = res.Value.GetObjectIds();
ObjectIdCollection oldids = new ObjectIdCollection();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
//遍历选择集
foreach (ObjectId i in ids)
{
List pars = new List();
Curve iCurve = (Curve)tr.GetObject(i, OpenMode.ForRead);
//获取曲线与其他曲线的交点处的param值集合,按该集合打断曲线
foreach (ObjectId j in ids)
{
if (i != j)
{
Curve jCurve = (Curve)tr.GetObject(j, OpenMode.ForRead);
Point3dCollection iwpnts = new Point3dCollection();
iCurve.IntersectWith(jCurve, Intersect.OnBothOperands, iwpnts, 0, 0);
foreach (Point3d p in iwpnts)
{
pars.Add(iCurve.GetParameterAtPoint(p));
}
}
}
//如果有交点,按param值排序并打断
if (pars.Count > 0)
{
pars.Sort();
try
{
//将子曲线加入数据库,原曲线加入oldids集合
foreach (Curve c in iCurve.GetSplitCurves(new DoubleCollection(pars.ToArray())))
{
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
oldids.Add(i);
}
catch
{ }
}
}
foreach (ObjectId id in oldids)
{
tr.GetObject(id, OpenMode.ForWrite).Erase();
}
tr.Commit();
}
}简单的直线倒角
public void daojiao()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptDoubleResult resgetdist = ed.GetDistance("\n请输入倒角距离");
if (resgetdist.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
double dist = resgetdist.Value;
PromptEntityOptions optgetent = new PromptEntityOptions("\n请选择第一条直线:");
optgetent.SetRejectMessage("\n错误的选择");
optgetent.AddAllowedClass(typeof(Line), true);
PromptEntityResult resgetent = ed.GetEntity(optgetent);
if (resgetent.Status == PromptStatus.OK)
{
ObjectId id1 = resgetent.ObjectId;
Line line1 = (Line)tr.GetObject(id1, OpenMode.ForWrite);
line1.Highlight();
Point3d pt1 = resgetent.PickedPoint;
optgetent.Message = "\n请选择第二条直线:";
resgetent = ed.GetEntity(optgetent);
if (resgetent.Status == PromptStatus.OK)
{
ObjectId id2 = resgetent.ObjectId;
Point3d pt2 = resgetent.PickedPoint;
Line line2 = (Line)tr.GetObject(id2, OpenMode.ForWrite);
pt1 = line1.GetClosestPointTo(pt1, false);
pt2 = line2.GetClosestPointTo(pt2, false);
//获取两直线交点
Point3dCollection pts = new Point3dCollection();
line1.IntersectWith(line2, Intersect.ExtendBoth, pts, 0, 0);
//如果有交点
if (pts.Count == 1)
{
Point3d pt = pts;
Plane plane = new Plane();
//判断点选在直线的哪一侧(是否靠近起点)
Vector3d v1,v2;
v1 = line1.StartPoint - pt;
v2 = line1.EndPoint - pt;
bool atstart1 = false;
if (v1.Length != 0)
{
atstart1 = Tolerance.Equals(v1.AngleOnPlane(plane), (pt1 - pt).AngleOnPlane(plane));
if (Tolerance.Equals(v1.AngleOnPlane(plane), v2.AngleOnPlane(plane)))
{
atstart1 = v1.Length > v2.Length;
}
}
v1 = line2.StartPoint - pt;
v2 = line2.EndPoint - pt;
bool atstart2 = false;
if (v1.Length != 0)
{
atstart2 = Tolerance.Equals(v1.AngleOnPlane(plane), (pt2 - pt).AngleOnPlane(plane));
if (Tolerance.Equals(v1.AngleOnPlane(plane), v2.AngleOnPlane(plane)))
{
atstart2 = v1.Length > v2.Length;
}
}
// 判断被选择段是否可以倒角
Point3d pt3 = atstart1 ? line1.StartPoint : line1.EndPoint;
Point3d pt4 = atstart2 ? line2.StartPoint : line2.EndPoint;
Vector3d vec1 = pt3 - pt;
Vector3d vec2 = pt4 - pt;
if (vec1.Length >= dist && vec2.Length >= dist)
{
//计算倒角点
vec1 = vec1.GetNormal() * dist;
vec2 = vec2.GetNormal() * dist;
pt3 = pt + vec1;
pt4 = pt + vec2;
//按点选的位置改变原直线
if (atstart1)
{
line1.EndPoint = pt3;
}
else
{
line1.StartPoint = pt3;
}
if (line1.Length == 0)
{
line1.Erase();
}
if (atstart2)
{
line2.EndPoint = pt4;
}
else
{
line2.StartPoint = pt4;
}
if (line2.Length == 0)
{
line2.Erase();
}
//生成倒角线
Line line = new Line(pt3, pt4);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
}
else
{
ed.WriteMessage("\n距离太大\n*无效");
}
}
else
{
ed.WriteMessage("\n直线平行\n*无效");
}
}
}
tr.Commit();
}
}
}找回hatch的边界,
填充边界是一组Ge曲线,所以需要转换为Db曲线
圆弧和椭圆的处理不太好,Ge库实体的方法有点晕哈,期待高人操刀
public static void HatchLoop()
{
PromptSelectionResult res = CadHelper.Editor.GetSelection(
new PromptSelectionOptions(),
new SelectionFilter(new TypedValue[] { new TypedValue(0, "Hatch") }));
if (res.Status != PromptStatus.OK)
return;
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
foreach (ObjectId id in res.Value.GetObjectIds())
{
//获取Hatch对象的Ocs
Hatch h = (Hatch)tr.GetObject(id, OpenMode.ForRead);
Matrix3d mat = Matrix3d.PlaneToWorld(h.GetPlane());
//遍历边界集合,通常边界有两种形式:多义线 或 曲线集合
for (int i = 0; ipars = new List();
Curve iCurve = (Curve)tr.GetObject(i, OpenMode.ForRead);
//获取曲线与其他曲线的交点处的param值集合,按该集合打断曲线
foreach (ObjectId j in ids)
{
if (i != j)
{
Curve jCurve = (Curve)tr.GetObject(j, OpenMode.ForRead);
Point3dCollection iwpnts = new Point3dCollection();
iCurve.IntersectWith(jCurve, Intersect.OnBothOperands, iwpnts, 0, 0);
foreach (Point3d p in iwpnts)
{
pars.Add(iCurve.GetParameterAtPoint(p));
}
}
}
//如果有交点,按param值排序并打断
if (pars.Count > 0)
{
pars.Sort();
try
{
//将子曲线加入数据库,原曲线加入oldids集合
foreach (Line newline in iCurve.GetSplitCurves(new DoubleCollection(pars.ToArray())))
{
btr.AppendEntity(newline);
tr.AddNewlyCreatedDBObject(newline, true);
}
oldids.Add(i);
}
catch
{ }
}
}
foreach (ObjectId id in oldids)
{
tr.GetObject(id, OpenMode.ForWrite).Erase();
}
tr.Commit();
}
}
找回hatch的边界,
填充边界是一组Ge曲线,所以需要转换为Db曲线
圆弧和椭圆的处理不太好,Ge库实体的方法有点晕哈,期待高人操刀
public static void HatchLoop()
{
PromptSelectionResult res = CadHelper.Editor.GetSelection(
new PromptSelectionOptions(),
new SelectionFilter(new TypedValue[] { new TypedValue(0, "Hatch") }));
if (res.Status != PromptStatus.OK)
return;
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
foreach (ObjectId id in res.Value.GetObjectIds())
{
//获取Hatch对象的Ocs
Hatch h = (Hatch)tr.GetObject(id, OpenMode.ForRead);
Matrix3d mat = Matrix3d.PlaneToWorld(h.GetPlane());
//遍历边界集合,通常边界有两种形式:多义线 或 曲线集合
for (int i = 0; iv2.Length;
}
}
v1 = line2.StartPoint - pt;
v2 = line2.EndPoint - pt;
bool atstart2 = false;
if (v1.Length != 0)
{
atstart2 = Tolerance.Equals(v1.AngleOnPlane(plane), (pt2 - pt).AngleOnPlane(plane));
if (Tolerance.Equals(v1.AngleOnPlane(plane), v2.AngleOnPlane(plane)))
{
atstart2 = v1.Length > v2.Length;
}
}
// 判断被选择段是否可以倒角
Point3d pt3 = atstart1 ? line1.StartPoint : line1.EndPoint;
Point3d pt4 = atstart2 ? line2.StartPoint : line2.EndPoint;
Vector3d vec1 = pt3 - pt;
Vector3d vec2 = pt4 - pt;
if (vec1.Length >= dist && vec2.Length >= dist)
{
//计算倒角点
vec1 = vec1.GetNormal() * dist;
vec2 = vec2.GetNormal() * dist;
pt3 = pt + vec1;
pt4 = pt + vec2;
//按点选的位置改变原直线
if (atstart1)
{
line1.EndPoint = pt3;
}
else
{
line1.StartPoint = pt3;
}
if (line1.Length == 0)
{
line1.Erase();
}
if (atstart2)
{
line2.EndPoint = pt4;
}
else
{
line2.StartPoint = pt4;
}
if (line2.Length == 0)
{
line2.Erase();
}
//生成倒角线
Line line = new Line(pt3, pt4);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId,
OpenMode.ForWrite,
false);
btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
}
else
{
ed.WriteMessage("\n距离太大\n*无效");
}
}
else
{
ed.WriteMessage("\n直线平行\n*无效");
}
}
}
tr.Commit();
}
}
} 仅以此表示对新任版主的支持!复制代码提示:pi可以直接调用System.Math.PI获取,:)
连接两条相连的Spline,Ge曲线还是强大些:)
简单的示例
public static Spline ConvertNurbCurve3d(NurbCurve3d nc3d)
{
DoubleCollection knots = new DoubleCollection();
foreach (double knot in nc3d.Knots)
{
knots.Add(knot);
}
NurbCurve3dData ncdata = nc3d.DefinitionData;
return
new Spline(
ncdata.Degree,
ncdata.Rational,
nc3d.IsClosed(),
ncdata.Periodic,
ncdata.ControlPoints,
knots,
ncdata.Weights,
0,
nc3d.Knots.Tolerance);
}
public static NurbCurve3d ConvertNurbCurve3d(Spline spl)
{
KnotCollection knots = new KnotCollection();
foreach (double knot in spl.NurbsData.GetKnots())
{
knots.Add(knot);
}
NurbsData ndata = spl.NurbsData;
return
new NurbCurve3d(
ndata.Degree,
knots,
ndata.GetControlPoints(),
ndata.Periodic);
}
public static void Test4()
{
PromptSelectionResult res = CadHelper.Editor.GetSelection();
using (DBTransaction tr = new DBTransaction())
{
Spline c1 = (Spline)tr.GetObject(res.Value.ObjectId, OpenMode.ForRead);
Spline c2 = (Spline)tr.GetObject(res.Value.ObjectId, OpenMode.ForRead);
NurbCurve3d nc3d = ConvertNurbCurve3d(c1);
nc3d.JoinWith(ConvertNurbCurve3d(c2));
Spline spl = ConvertNurbCurve3d(nc3d);
tr.OpenCurrentSpace();
tr.AddEntity(spl);
}
}打断自相交曲线,以前写过一个巨复杂的:),一百多行代码
使用Ge CurveCurveIntersector3d对象要简单有效的多:)
暂时只有Spline的
public static void Test7()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult res1 = ed.GetEntity("选择图元1");
using (DBTransaction tr = new DBTransaction())
{
Spline spl1 = (Spline)tr.GetObject(res1.ObjectId, OpenMode.ForRead);
NurbCurve3d nc1 = ConvertDbCurve.ToNurbCurve3d(spl1);
CurveCurveIntersector3d cci = new CurveCurveIntersector3d(nc1, nc1, Vector3d.ZAxis);
List pars = new List();
for (int i = 0; i0)
{
pars.Sort();
tr.OpenCurrentSpace();
tr.AddEntity(spl1.GetSplitCurves(new DoubleCollection(pars.ToArray())));
spl1.UpgradeOpen();
spl1.Erase(true);
}
}
}曲线的不等比缩放
注意,不是所有的曲线都支持,可以直接转换的只有椭圆,样条曲线
圆可以先转换为椭圆
其余的曲线可能需要先转换为Ge样条曲线,再变换矩阵,或取Spline属性
public static Matrix3d ScaleMatrix(Point3d point, double x, double y, double z)
{
double[] matdata = new double;
matdata = x;
matdata = point.X * (1 - x);
matdata = y;
matdata = point.Y * (1 - y);
matdata = z;
matdata = point.Z * (1 - z);
matdata = 1;
return new Matrix3d(matdata);
}
public static void Test9()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult res1 = ed.GetEntity("选择图元1");
using (DBTransaction tr = new DBTransaction())
{
Curve curve = (Curve)tr.GetObject(res1.ObjectId, OpenMode.ForWrite);
curve.TransformBy(ScaleMatrix(new Point3d(10, 10, 0), 2, 1, 1));
}
} 打断自相交曲线,以前写过一个巨复杂的:),一百多行代码
使用Ge CurveCurveIntersector3d对象要简单有效的多:)
public static void Test7()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult res1 = ed.GetEntity("选择图元1");
using (DBTransaction tr = new DBTransaction())
{
Spline spl1 = (Spline)tr.GetObject(res1.ObjectId, OpenMode.ForRead);
NurbCurve3d nc1 = ConvertDbCurve.ToNurbCurve3d(spl1);
CurveCurveIntersector3d cci = new CurveCurveIntersector3d(nc1, nc1, Vector3d.ZAxis);
List pars = new List();
for (int i = 0; i0)
{
pars.Sort();
tr.OpenCurrentSpace();
tr.AddEntity(spl1.GetSplitCurves(new DoubleCollection(pars.ToArray())));
spl1.UpgradeOpen();
spl1.Erase(true);
}
}
}
曲线的不等比缩放
注意,不是所有的曲线都支持,可以直接转换的只有椭圆,样条曲线
圆可以先转换为椭圆
其余的曲线可能需要先转换为Ge样条曲线,再变换矩阵,或取Spline属性
public static Matrix3d ScaleMatrix(Point3d point, double x, double y, double z)
{
double[] matdata = new double;
matdata = x;
matdata = point.X * (1 - x);
matdata = y;
matdata = point.Y * (1 - y);
matdata = z;
matdata = point.Z * (1 - z);
matdata = 1;
return new Matrix3d(matdata);
}
public static void Test9()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult res1 = ed.GetEntity("选择图元1");
using (DBTransaction tr = new DBTransaction())
{
Curve curve = (Curve)tr.GetObject(res1.ObjectId, OpenMode.ForWrite);
curve.TransformBy(ScaleMatrix(new Point3d(10, 10, 0), 2, 1, 1));
}
}复制代码 “所有曲线打断于点”的程序只是针对line对象有用?我试了cad2008、2010多段线都没打断。 如果有自交点,这个简化版本不支持:)
在自交点打断曲线可以看下三楼的代码
页:
[1]