Hi, Dears.
I was using a TraceBoundary method well.
However, I found a problem when using it with ellipses or splines.
The return value.Count is 0.
Do I need to do any additional settings to get it to work?
Or is there a method that is used for ellipses ?
It is searched that the same result occurred ten years ago.
I hope it will be improved now.
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Ensure that you are providing the correct input parameters to the TraceBoundary method for ellipses and splines. Verify that the coordinates and other properties are accurately defined. If you are using a third-party library or package for the TraceBoundary method, check for any updates or patches that might address this issue. Newer versions might have improvements and bug fixes.
The input parameters of
Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.TraceBoundary()
are very simple. Just Point3d and bool.
The result of TraceBoundary is the same that Point3d is located inside the ellipse, bool is true or false,
I'm not use any 3rd-party library. I'm use only Autocad .net APIs.
Is there anyone who can advise me on this matter?
it works in ARX, do you have a try catch around your code to pickup any possible errors?
import PyRx as Rx
import PyGe as Ge
import PyGi as Gi
import PyDb as Db
import PyAp as Ap
import PyEd as Ed
import PyGs as Gs
def PyRxCmd_doit():
try:
db = Db.curDb()
pntRes = Ed.Editor.getPoint("\nGet Point: ")
if(pntRes[0] != Ed.PromptStatus.eNormal):
return
ents = Ed.Editor.traceBoundary(pntRes[1],False)
print("Found = ", len(ents))
model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.ForWrite)
for ent in ents:
model.appendAcDbEntity(ent)
except Exception as err:
print(err)
Thanks for you reply.
There is no exception.
It just returns a value whose count is 0.
I use autocad .net api in autocad 2021 and vs2019.
Did you mean TraceBoundary() produces different results in arx api and .net api?
I think this is a bit odd.
If possible, I will try to test using arx api.
I have no idea how to approach to solve this problem using .net api.
Please reply, if anyone has a solution in the .net api.
Hi,
With a closed ellipse or spline TraceBoundary should generate a Region (a polyline can only be constitued of lines and arcs).
This little snippet works for me:
[CommandMethod("TEST")]
public static void Test()
{
var ed = Application.DocumentManager.MdiActiveDocument.Editor;
var pointResult = ed.GetPoint("\nPick a point: ");
var bound = ed.TraceBoundary(pointResult.Value, false);
if (0 < bound.Count)
{
Application.ShowAlertDialog(bound[0].GetType().Name);
foreach (DBObject item in bound)
{
item.Dispose();
}
}
else
{
Application.ShowAlertDialog("None boundary");
}
}
Thanks for your reply.
In my case, your code return "None Boundary" with ellipse.
As in the picture, I want to create an region when the user clicks inside the ellipse or spline.
What should I do?
Thanks for your reply.
I tried to change HPBOUND the variable.
But the result is same. (result value count is 0)
This is my code.
private DBObjectCollection GetBoundary(Point3d pnt)
{
/// object obj1 = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("HPBOUND");
/// Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("HPBOUND", 0);
/// Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("HPBOUND", 1);
/// Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("HPBOUNDRETAIN", 1);
var ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
var objs = ed. TraceBoundary(pnt, true);
/// Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("HPBOUND", obj1);
if (objs. Count > 0)
return objs;
else
return null;
}
TraceBoundary expects the point to be UCS, and probably expects the entity(s) to be aligned with the UCS.
If they’re not, you may have to do some transformations. You should post a sample DWG as a test case
Here is my test dwg file.
I'm trying to make a function like the 'BOUNDARY' command that the result object is region.
Is there any way to create a region like the BOUNDARY command?
Of course, if it is a closed area that construct an ellipse or spline, it will make a region.
Is there any additional way to try?
Hmm, yeah not sure, the code I posted works fine with your drawing
The code I posted work with your drawing as the following one.
Your issue may be due to the context you call your method or a corrupted AutoCAD installation.
What happens when you call the call the _BOUNDARY command in the test_01.dwg drawing?
[CommandMethod("TEST")]
public static void Test()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var pointResult = ed.GetPoint("\nPick a point: ");
var bound = ed.TraceBoundary(pointResult.Value, true);
if (0 < bound.Count)
{
using (var tr = db.TransactionManager.StartTransaction())
{
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (DBObject obj in bound)
{
var ent = (Entity)obj;
ent.ColorIndex = 1;
curSpace.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
Application.ShowAlertDialog($"One {obj.GetType().Name} created");
}
tr.Commit();
}
}
else
{
Application.ShowAlertDialog("None boundary");
}
}
The command '-BOUNDARY'(no UI) and 'BOUNDARY' work well.
It makes a region.
(_BOUNDARY is not found in my autocad.)
Cad 2021, 2023, 2024 had same result in my desktop.
I referenced AcCoreMgd, AcDbMgd, acdbmgdbrep, AcMgd.
Maybe, do I need additional references?
How can I fix it?
Will it fix the problem, if I reinstall Autocad?
I really have no idea what's wrong.
Repair and reinstall cad is not work for me.
But, I got something while running test.
At last time, I said that your code not work on my desktop.
I found that to be only half true.
It works well with CommandMethod.
In my case, however, my program has winform UI.
In my command, I made a form and call Application.ShowModelessDialog().
And in button handler, TraceBoundary() is not work with ellipse.
I don't know what difference between cad command and winform button handler could cause this problem.
This is my command registration code.
[CommandMethod("MyGroup", "MyCmd", "MyCmdLocal", CommandFlags.Modal)]
public void MyCmd()
{
MainForm form = new MainForm();
Application.ShowModelessDialog(null, form, false);
}
Do you have any advice?
The Editor.TraceBoundary methods works in the document context.
A modeless UI runs in application context.
As said Kean Walmsley in his blog:
"Once again there’s our important rule of thumb when it comes to implementing a modeless UI: rather than manually locking the current document, it’s safer to define a command – which will implicitly lock the current document – and call that from the UI via SendStringToExecute()."
So, you should wrap the using of TraceBoundary within a command method and call this command with SenStringToExecute from your button event handler so that AutoCAD takes care of switching in document context and locking the document.
Another way to switch to the document context is to prompt the user within the button event handler, but in this case, you're responsible to lock the document (before calling TraceBoundary).
Command side:
[CommandMethod("DLG", CommandFlags.Modal)]
public static void ShowDialog()
{
var dlg = new Dialog1();
Application.ShowModelessDialog(null, dlg, false);
}
Dialog side:
private void button1_Click(object sender, EventArgs e)
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
if (doc == null) return;
var ed = doc.Editor;
doc.Window.Focus();
var pointResult = ed.GetPoint("\nPick a point: "); // <- switch to document context
if (pointResult.Status != Autodesk.AutoCAD.EditorInput.PromptStatus.OK) return;
using (doc.LockDocument())
{
var bound = ed.TraceBoundary(pointResult.Value, true);
if (0 < bound.Count)
{
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (DBObject obj in bound)
{
var ent = (Entity)obj;
ent.ColorIndex = 1;
curSpace.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
}
tr.Commit();
}
}
}
}
Even in this case, the more robust way is not more complex and allow to recall the last command by hiting enter.
Command side:
[CommandMethod("DLG", CommandFlags.Modal)]
public static void ShowDialog()
{
var dlg = new Dialog1();
Application.ShowModelessDialog(null, dlg, false);
}
[CommandMethod("DRAWBOUND")]
public static void DrawBoundary()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
var pointResult = ed.GetPoint("\nPick a point: ");
if (pointResult.Status != PromptStatus.OK) return;
var bound = ed.TraceBoundary(pointResult.Value, true);
if (0 < bound.Count)
{
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
foreach (DBObject obj in bound)
{
var ent = (Entity)obj;
ent.ColorIndex = 1;
curSpace.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
}
tr.Commit();
}
}
}
Dialog side:
private void button2_Click(object sender, EventArgs e)
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
if (doc == null) return;
doc.Window.Focus();
doc.SendStringToExecute("DRAWBOUND\n", false, false, false); // <- switch to document context
}
Can't find what you're looking for? Ask the community or share your knowledge.