using IfoxDemo;
namespace IFoxDemo;
public class Class1
{
[CommandMethod("xx")]
public static void Demo()
{
//"ifox可以了".Print();
using var tr = new DBTrans();//开事务
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Env.Editor;
var doc = Env.Document;
"请选择全部需裁剪对象:\n".Print();
var psr = ed.GetSelection();//提示框选待裁剪图元
if (psr.Status != PromptStatus.OK) return;
var pcat = ed.GetEntity("请选择裁剪框:");//提示选裁剪框
if (pcat.Status != PromptStatus.OK ) return;
var ppr = ed.GetPoint("请选择需删除的边界一侧点");//提示选点
if (ppr.Status != PromptStatus.OK ) return;
var p0 = ppr.Value;//获取点坐标
var catobj = pcat.ObjectId.GetObject();//获取裁剪框对象
Curve cat = null;//定义裁剪框曲线
if (catobj is Curve)
{
cat = catobj as Curve;
}
if (cat == null) return;
List<Curve> curs = new List<Curve>();//创建list待裁剪曲线对象
foreach (var id in psr.Value.GetObjectIds())//遍历待裁剪图元id
{
var obj = id.GetObject();//根据id获取对象
if (obj is Curve cur)
{
curs.Add(cur);//对象加入曲线列表
}
}
if (curs.Contains(cat)) curs.Remove(cat);//如果曲线列表包含裁剪框,那么移除裁剪框
if(curs.Count > 0)//如果曲线类型的待裁剪图元不为空,执行以下操作
{
var sps = 自动修剪(curs,cat, p0);//根据三个参数,修剪曲线,返回另一侧曲线列表
foreach (var c in sps)//遍历修剪后的另一侧曲线
{
if (c.IsNewObject) //如果曲线被修剪生成了新对象,那么把新对象加入当前空间
{
tr.CurrentSpace.AddEntity(c);
}
else
{
curs.Remove(c);//如果曲线未被修剪,那么从原始曲线列表中移除此对象
}
}
foreach (var item in curs)//再次遍历删除原始曲线对象(另一侧未被修剪的不用删除)
{
db.Erase(item);//李小科版删除模型空间中实体,需要using
// tr.BlockTable.Remove(item.ObjectId);//删除修剪前的曲线对象,未能删除,待完善。
}
}
}
public static List<Curve> 自动修剪(List<Curve>curs,Curve cat,Point3d ptseed)//返回另一侧曲线列表
{
List<Curve> lingyice = new List<Curve>();
var zuijindian0=cat.GetClosestPointTo(ptseed,false);//获取图框上与指定点距离最近的一个点
var vt10 = zuijindian0.GetVectorTo(ptseed);//图框点到指定点的向量
var vt20 = cat.GetFirstDerivative(zuijindian0);//图框上一点的切线向量
var vt30= vt10.CrossProduct(vt20);//图框点到指定点的向量 叉乘 图框点的切线向量,
foreach (var cur in curs)//遍历待裁剪曲线对象
{
var ptc = new Point3dCollection();//新建点集合
cat.IntersectWith(cur,Intersect.OnBothOperands,ptc,IntPtr.Zero ,IntPtr.Zero );//图框与待裁剪曲线相交,返回相交点集合
if (ptc.Count ==0)//如果不想交
{
neiwai(cur);//判断曲线并加入另一侧曲线
}
else//如果相交
{
var pts = new List<Point3d>();//新建点列表
foreach (Point3d item in ptc)
{
pts.Add(item);//点集合加入点列表
}
var vv = from p in pts orderby cur.GetParameterAtPoint(cur.GetClosestPointTo(p,false))select p;//曲线上到点列表的最近点,然后排序
ptc = new Point3dCollection(vv.ToArray());//曲线上的交点排序
var fenjies = cur.GetSplitCurves(ptc);//曲线根据排序后的交点分解曲线
foreach (Curve item in fenjies)
{
neiwai(item);//分解后的曲线,执行内部函数。当程序比较繁琐时,可采用内部函数的方法,简化主函数。
}
}
}
void neiwai(Curve cur)//内部方法,返回选点的另一侧曲线
{
var zhongdian = cur.GetPointAtParameter(cur.StartParam / 2 + cur.EndParam / 2);//待裁剪曲线,(起始点参数+终点参数)/2,即中点的参数,求出中点的坐标
var zuijindian = cat.GetClosestPointTo(zhongdian,false);//图框上到曲线中点的最近点
var vt1 = zuijindian.GetVectorTo(zhongdian);//图框上的点到曲线中点的向量
var vt2 = cat.GetFirstDerivative(zuijindian);//图框上点的切线向量
var vt3 = vt1.CrossProduct(vt2);//图框上的点到曲线中点的向量 叉乘 图框上点的切线向量
var tong = vt3.Z*vt30.Z>0; //叉乘大于0
if (!tong)
{
lingyice.Add(cur);//如果小于0,在选点的另一侧,加入另一侧曲线
}
}
return lingyice;//
}
}
封装erase
public static void Erase(this Database db, Entity entity)
{
// Database db = HostApplicationServices.WorkingDatabase;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
if (entity == null)
{
return;
}
if (entity.IsNewObject) return;
//if (!entity.IsErased)
//{
entity.ObjectId.GetObject(OpenMode.ForWrite);
entity.Erase();
trans.Commit();
// }
}
}
public static void Erase<T>(this Database db, List<T> entities) where T : Entity
{
// Database db = HostApplicationServices.WorkingDatabase;
foreach (var entity in entities)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
if (entity == null)
{
return;
}
if (entity.IsNewObject) return;
//if (!entity.IsErased)
//{
entity.ObjectId.GetObject(OpenMode.ForWrite);
entity.Erase();
trans.Commit();
// }
}
}
}