Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

problem about Getting OutermostIntersectionPoints of line and dynamic block reference

22951050
Participant

problem about Getting OutermostIntersectionPoints of line and dynamic block reference

22951050
Participant
Participant

Hi! I'm new to here and i'm learning a lot from this forum. really thanks.

 

I have found some code of Gile that getting OuterMost Intersection Points of Line and Block Reference

first, it explodes the block reference and getting all intersection points of line and new objects(by explode)

then, find shortest distance from startpoint and endpoint of the line.

 

I wanted to use it to trim(break) with that OuterMostpoints (with GetSplitCurves Method),

and as long as if the block reference is a static block reference, it works perfectly,

but dynamic block reference, it doesn't.

 

here is my code

 

 

 

public static void TrimLinesByBlockReferences()
{
    var adoc = CadApp.DocumentManager.MdiActiveDocument;
    var db = adoc.Database;
    var ed = adoc.Editor;

    using (var tx = db.TransactionManager.StartTransaction())
    {
        var bt = (BlockTable)tx.GetObject(db.BlockTableId, OpenMode.ForRead);
        var ms = (BlockTableRecord)tx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

        var op = new PromptSelectionOptions();
        op.MessageForAdding = "\nSelect Entities:";
        var filter = new SelectionFilter(new TypedValue[]
        {
                new TypedValue((int)DxfCode.Start, "INSERT,LINE"),
        });
        var rs = ed.GetSelection(op, filter);

        if (rs.Status != PromptStatus.OK) return;
        
        var lines = (from id in rs.Value.GetObjectIds()
                        let ent = tx.GetObject(id, OpenMode.ForRead)
                        where ent is Line
                        select ent as Curve).ToList();
        var brs = (from id in rs.Value.GetObjectIds()
                    let ent = tx.GetObject(id, OpenMode.ForRead)
                    where ent is BlockReference
                    select ent as BlockReference).ToList();

        foreach (var br in brs)
        {
            lines = TrimLinesByBlockReference(br, lines);
        }

        tx.Commit();
    }
}

 

 

 

 

 

 

    private static List<Curve> TrimLinesByBlockReference(
BlockReference br, List<Curve> lines)
    {
        var newCurveList = new List<Curve>();
        foreach (var line in lines)
        {
            if (Modules.FindOutmostIntersectingPoints(line as Line, br, out Point3d pt1, out Point3d pt2))
            {
                var result = Modules.BreakLineOrPolyline(line.ObjectId, pt1, pt2);
                if (result != null && result.Count > 0)
                {
                    newCurveList.AddRange(result.OfType<Curve>());
                }
                else newCurveList.Add(line);
            }
            else
            {
                newCurveList.Add(line);
            }
        }
        return newCurveList;
    }

 

 

 

below 3 methods are in 'Modules' Class

 

 

    public static List<Point3d> GetAllIntersectingPoints(
Line line, BlockReference br)
    {
        var points = new List<Point3d>();

        using (var ents = new DBObjectCollection())
        {
            if (br.IsDynamicBlock) br.ConvertToStaticBlock();
            br.Explode(ents);
            foreach (Entity ent in ents)
            {
                var pts = new Point3dCollection();
                line.IntersectWith(
                    ent, Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);
                foreach (Point3d p in pts)
                {
                    points.Add(p);
                }
                ent.Dispose();
            }
        }

        return points;
    }

 

 

 

 

 

 

    public static bool FindOutmostIntersectingPoints(
Line line, BlockReference br, out Point3d pt1, out Point3d pt2)
    {
        pt1 = Point3d.Origin;
        pt2 = Point3d.Origin;

        var points = GetAllIntersectingPoints(line, br);
        
        // Check for the Points
        //var adoc = CadApp.DocumentManager.MdiActiveDocument;
        //var db = adoc.Database;
        //using (Transaction tx = db.TransactionManager.StartTransaction()){

        //    var bt = (BlockTable)tx.GetObject(db.BlockTableId, OpenMode.ForRead);
        //    var ms = (BlockTableRecord)tx.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

        //    db.Pdmode = 34;
        //    DBPoint dbpt;
        //    foreach (var point in points)
        //    {
        //        dbpt = new DBPoint(point);
        //        ms.AppendEntity(dbpt);
        //        tx.AddNewlyCreatedDBObject(dbpt, true);
        //    }
        //    tx.Commit();   
        //}

        if (points.Count > 0)
        {
            pt1 = (from p in points
                   orderby p.DistanceTo(line.StartPoint)
                   select p).First();

            pt2 = (from p in points
                   orderby p.DistanceTo(line.EndPoint)
                   select p).First();

            return true;
        }
        else
        {
            return false;
        }
    }

 

 

 

 

 

 

public static DBObjectCollection BreakLineOrPolyline(ObjectId curveId, Point3d pt1, Point3d pt2)
{

    var doc = CadApp.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    using (var tr = db.TransactionManager.StartTransaction())
    {
        Curve curve;
        try
        {
            curve = (Curve)tr.GetObject(curveId, OpenMode.ForWrite);
        }
        catch (Exception e)
        {
            return null;
        }
        if (!(curve is Line || curve is Polyline)) return null;
        
        double param1 = curve.GetParameterAtPoint(curve.GetClosestPointTo(pt1, false));
        double param2 = curve.GetParameterAtPoint(curve.GetClosestPointTo(pt2, false));
        var parameters = new DoubleCollection
            (new[] { param1, param2 }
            .Distinct()
            .OrderBy(x => x)
            .ToArray());
        var curves = curve.GetSplitCurves(parameters);
        var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
        switch (curves.Count)
        {
            case 3:
                curSpace.AppendEntity((Entity)curves[0]);
                tr.AddNewlyCreatedDBObject(curves[0], true);
                curSpace.AppendEntity((Entity)curves[2]);
                tr.AddNewlyCreatedDBObject(curves[2], true);
                curves[1].Dispose();
                curves.RemoveAt(1);
                curve.Erase();
                break;
            case 2:
                curSpace.AppendEntity((Entity)curves[0]);
                tr.AddNewlyCreatedDBObject(curves[0], true);
                curSpace.AppendEntity((Entity)curves[1]);
                tr.AddNewlyCreatedDBObject(curves[1], true);
                curve.Erase();
                break;
            default:
                break;
        }
        tr.Commit();

        return curves;
    }
}

 

 

 

 

by uncomment 'Check for the points' in 'FindOutMostIntersectingPoints' method,

it creates point objects to all the intersected points.

 

thanks!

outermost.png

 

 

0 Likes
Reply
Accepted solutions (1)
319 Views
2 Replies
Replies (2)

22951050
Participant
Participant

it seems all the visibility entities are created when using .Explode() method.

is there a way to get entities in current visibility only?

0 Likes

22951050
Participant
Participant
Accepted solution

Self Answer

I have found a solution in this link

the entities created by explode method are following their visibility of dynamic block reference,

so before check the intersection, just check if the Visible property is true.

 

br.Explode(ents);
foreach (Entity ent in ents)
{
    // check if the entity is visible
    if (ent.Visible == true)
    {
        var pts = new Point3dCollection();
        line.IntersectWith(
            ent, Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);
        foreach (Point3d p in pts)
        {
            points.Add(p);
        }
    }
    ent.Dispose();
}

 

0 Likes