TheSwamp
Code Red => .NET => Topic started by: Kerry on January 22, 2007, 02:42:31 AM
-
Having a play ..
This is interesting !!
ent.List();
[AcRx.CommandMethod("ListIt")]
static public void ListIt()
{
AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
AcEd.PromptEntityResult resEnt = ed.GetEntity("\nSelect an Object: ");
if (resEnt.Status != AcEd.PromptStatus.OK)
{
ed.WriteMessage("\nNothing selected");
return;
}
// Something selected, so ..
// do lots of unnecessary testing stuff ..
ed.WriteMessage("\n PromptEntityResult : " + resEnt.ToString());
ed.WriteMessage("\n PickedPoint : " + resEnt.PickedPoint.ToString());
// Get the ObjectId
AcDb.ObjectId ObjId = (resEnt.ObjectId);
ed.WriteMessage("\n Object Id : " + resEnt.ObjectId.ToString());
// Get the Entity
AcDb.Entity ent = kbGetEntity(resEnt.ObjectId);
ed.WriteMessage("\n Entity : " + ent.ToString() + "\n");
ent.List();
Extents3d extents3D = ent.GeometricExtents;
ed.WriteMessage("\n extents3D : " + extents3D.ToString());
ed.WriteMessage("\n extents3D.LLPoint : " + extents3D.MinPoint.ToString());
ed.WriteMessage("\n extents3D.URPoint : " + extents3D.MaxPoint.ToString());
[color=red]/// PROBLEM : how to locate the Entity WCS location ??[/color]
}
/// <summary>
/// ---------------------------------------------------------------------------------------------
public static AcDb.TransactionManager kbGetTransMan
{
get
{
return AcadApp.DocumentManager.MdiActiveDocument.TransactionManager;
}
}
//----------------------------------------
public static AcDb.Entity kbGetEntity(AcDb.ObjectId id)
{
AcDb.Entity ent;
AcDb.TransactionManager tm = kbGetTransMan;
using (AcDb.Transaction tr = tm.StartTransaction())
{
ent = (AcDb.Entity)tm.GetObject(id, AcDb.OpenMode.ForRead, true);
}
return ent;
}
Here's the tough Part : How to determine the WCS location of the selected entity.
Seems a pain, but I may have to pass the type to a case function and get the 'location' property depending on the type of object .. Any ideas ??
-
Perhaps it can be done getting the entity ECS and performing a translation ... but thats a W.A.G. and I'm brain dead tonight ...
-
I have not used the Extents3d.
But in the implementations I have seen they use GeomExtents or GetBoundingBox
using Autodesk.AutoCAD.Interop;
As far as I know...
Remember that this respond of mine, will be destroy in 24hrs.... [11:03 AM 1/22/2007 counting started...]
-
I wonder if it is possible to get the correct GeometricExtents or boundingBox of a 3Dobject no matter its orientation, with .NET. I tried so many times to do this with lisp but failed. My goal was to find the width, length, height of a 3D object based off its bounding box.
Using Kerry’s code
using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;
[assembly: CommandClass(typeof(aClassLibrary.CRPClass))]
namespace aClassLibrary
{
public class CRPClass
{
public CRPClass()
{
}
[CommandMethod("test")]
static public void test()
{
Extents3d extents3D;
TypedValue[] values = new TypedValue[]
{
new TypedValue((short)DxfCode.Start, "3DSOLID") ,
};
SelectionFilter filter = new SelectionFilter(values);
PromptSelectionOptions selopts = new PromptSelectionOptions();
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
selopts.MessageForAdding = "Select";
selopts.AllowDuplicates = false;
PromptSelectionResult result = ed.GetSelection(selopts, filter);
if (result.Status == PromptStatus.OK)
{
ObjectId[] idarray = result.Value.GetObjectIds();
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager;
Transaction tr = tm.StartTransaction();
try
{
foreach (ObjectId id1 in idarray)
{
Entity entity1 = (Entity)tm.GetObject(id1, OpenMode.ForRead, true);
extents3D = entity1.GeometricExtents;
ed.WriteMessage("\n extents3D.LLPoint : " + extents3D.MinPoint.ToString());
ed.WriteMessage("\n extents3D.URPoint : " + extents3D.MaxPoint.ToString());
}
}
finally
{
tr.Dispose();
}
}
}
}
}
-
Daniel, the easiest way to achieve this is by attaching 'worldpoint' xdata at creation time that indicates the extrusion direction and say an x/y axis which can be used to form a ucs to transform the object to world to get the bbox dimensions, invert the matrix and send it back. Rob Kish had some very serious vba code a few years ago that was very close and if I new then what I know now it probably wouldn't take much to get it to work without the xdata but those thoughts/code are long dissolved in memory somewhere :)
-
Thanks Mick,
Interesting, I never thought of using worldpoint, What I do now is draw my parts in the correct orientation and assign the width, height and depth in xdata at extrusion. I did get pretty far with lisp and decoding the ACIS, but I gave up. I’ll have to take another shot at it one of these days. I do know it is possible, and I know it would be a cool tool to have
Dan
-
no prob's, the simplest way is to store the normal of the region you need to create the 3dSolid as the worldpoint (z axis), it is automatically updated with modifications such as rotating/mirroring etc. This is pretty simple as you at most times know the width and depth of your 'section' to extrude, I just use the worldpoint as a vector and create an arbitory matrix to rotate to world and back using the min/max z coord's for the length, easy peasy ;)
-
Here's something to get your britches in a knot.
The GeometricExtents is incorrect for text based types.
It reports 0,0,0 as the LL irrespective ... bummer.
compare it's output with/against this :
(defun c:test_bb (/ ll ur)
(vla-getboundingbox (vlax-ename->vla-object (car (nentsel))) 'll 'ur)
(princ (vlax-safearray->list ll))
(princ (vlax-safearray->list ur))
(princ)
)
I'll report it, they may get it fixed in the next month [ in time for AC2008 ]
edit: fixed local variables. duh!
-
...
I'll report it, they may get it fixed in the next month [ in time for AC2008 ]
Change Request 862345 - GEOMETRICEXTENTS RETURNING INCORRECT VALUES FOR TEXT AND MTEXT.
Already fixed for AC2008.
-
I have not used the Extents3d.
But in the implementations I have seen they use GeomExtents or GetBoundingBox
using Autodesk.AutoCAD.Interop;
Thanks Luis, I didn't want to use COM if possible
-
Here's something to get your britches in a knot.
The GeometricExtents is incorrect for text based types.
It reports 0,0,0 as the LL irrespective ... bummer.
compare it's output with/against this :
(defun c:test_bb (/ ll ur)
(vla-getboundingbox (vlax-ename->vla-object (car (nentsel))) 'll 'ur)
(princ (vlax-safearray->list ll))
(princ (vlax-safearray->list ur))
(princ)
)
I'll report it, they may get it fixed in the next month [ in time for AC2008 ]
edit: fixed local variables. duh!
Yes, I read about that bug yesterday... anyway on the mean time maybe we can use or do something like:
For the text objects
[CommandMethod("EXTENTSTEXT")]
public void extentstext()
{
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
PromptEntityResult res = ed.GetEntity("\nSelect a text object: ");
if (res.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
DBText en = tr.GetObject(res.ObjectId, OpenMode.ForWrite, false) as DBText;
if (en != null)
{
Point3dCollection points = new Point3dCollection();
en.IntersectWith(en, Intersect.OnBothOperands, points, 0, 0);
Point3d min = points[0];
Extents3d ext = en.GeometricExtents;
Point3d max = ext.MaxPoint;
ed.WriteMessage("\nMin: " + min.ToString());
ed.WriteMessage("\nMax: " + max.ToString());
}
tr.Commit();
}
}
I did some tests and appears to work... HTH
-
And also, I noticed that when a circle, polyline with curve segments or arcs... it returns a Z value...
Command:
EXTENTS
Select an object:
Min: (5.45881777898967,3.1380655194173,-1E-08)
Max: (8.53598919405592,4.86608891299586,1E-08)
Command:
EXTENTS
Select an object:
Min: (9.51955997849185,3.76989079268639,0)
Max: (12.0768439959734,6.1427457033589,0)
Command: EXTENTS
Select an object:
Min: (26.5840584617689,-3.19303918509976,-1E-08)
Max: (33.0463436581694,1.62667942692176,1E-08)
Using this, and similar as Kerry original code post.
Extents3d ext = en.GeometricExtents;
Point3d min = ext.MinPoint;
Point3d max = ext.MaxPoint;
ed.WriteMessage("\nMin: " + min.ToString());
ed.WriteMessage("\nMax: " + max.ToString());
-
.............. Yes, I read about that bug yesterday...
Where did you read that information Luis ?
-
Interesting piece of code Luis ..
Any particular reason why you open the selected object ForWrite and Commit the transaction at the end ?
using (Transaction tr = db.TransactionManager.StartTransaction())
{
DBText en = tr.GetObject(res.ObjectId, OpenMode.ForWrite, false) as DBText;
if (en != null)
{
Point3dCollection points = new Point3dCollection();
en.IntersectWith(en, Intersect.OnBothOperands, points, 0, 0);
Point3d min = points[0];
Extents3d ext = en.GeometricExtents;
Point3d max = ext.MaxPoint;
ed.WriteMessage("\nMin: " + min.ToString());
ed.WriteMessage("\nMax: " + max.ToString());
}
tr.Commit();
}
-
Any particular reason why you open the selected object ForWrite and Commit the transaction at the end ?
Oops... I was doing some other stuff, previous to this code and forgot to remove it.... thanks.
-
.............. Yes, I read about that bug yesterday...
Where did you read that information Luis ?
Here:
http://www.codeproject.com/dotnet/dotnetarxsample.asp
GetBoundingBox()
In the .NET API, the GeomExtents property of an entity can get the corner points of a box that encloses the 3D extents of the entity. But for DBText and MText, the GeomExtents property always returns the point (0,0,0) for the min-point of the box. So, DOTNETARX provides the GetBoundingBox() function to let you get the correct corner points of an entity including the DBText and the MText objects. The return value of GetBoundingBox() is a Point3d array, - is the minimum point of the object's bounding box, [1] is the maximum point of the object's bounding box. The following example shows you how to use GetBoundingBox():
I was doing a search about geometry extents on the net, and found that info....
-
Thanks Luis.
Just had a look at the DOTNETARX.dll :
Declaring Type: DOTNETARX.Tools :- public static Point3d[] GetBoundingBox(Entity ent);
They use a different solution. Would be interesting to see the results when objects are not in WCS ..
-
Thanks Luis.
Just had a look at the DOTNETARX.dll :
Declaring Type: DOTNETARX.Tools :- public static Point3d[] GetBoundingBox(Entity ent);
They use a different solution. Would be interesting to see the results when objects are not in WCS ..
There is a an usage of a an Utils available in acmgdinternal.dll (I think) on the MgdDbg by Jim Awe - and it have are included some functions about geometry extents...... and mentioned by Tony Tanzillo in some of the C# posts I have read - to bad I was not able to compile those samples...
-
Luis, I think :
acmgdinternal.dll is standard AutoCAD
Jim hasn't released the AC2007 of MgdDbg yet, so it would AC2006 which I believe is different ..
.. .. but I'll have a look, and try to find any posts by Tony on the AD Newsgroup that refer to the issue.
-
Luis,
From Jim
QueryEntTests.cs
$DateTime: 2005/06/10 17:13:15
public void
Extents()
{
Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = m_db.TransactionManager;
while (true) {
PromptEntityResult prEntRes = ed.GetEntity("\nSelect entity to show extents");
if (prEntRes.Status != PromptStatus.OK)
break;
using (Autodesk.AutoCAD.DatabaseServices.Transaction tr = tm.StartTransaction()) {
AcDb.Entity ent = (AcDb.Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
Extents3d ext = ent.GeometricExtents;
Point3d centerPt = Utils.Ge.Midpoint(ext.MinPoint, ext.MaxPoint);
Utils.AcadUi.PrintToCmdLine(string.Format("\nEXTMIN: {0}", Utils.AcadUi.PtToStr(ext.MinPoint)));
Utils.AcadUi.PrintToCmdLine(string.Format("\nEXTMAX: {0}", Utils.AcadUi.PtToStr(ext.MaxPoint)));
Utils.AcadUi.PrintToCmdLine(string.Format("\nCENTER PT: {0}", Utils.AcadUi.PtToStr(centerPt)));
tr.Commit();
MakeExtentsBlock(ext);
}
}
}
Which appears to be essentially similar to mine
Note that his version with $DateTime: 2004/11/24 uses ent.GeomExtents not ent.GeometricExtents.
-
Luis, I think :
acmgdinternal.dll is standard AutoCAD
Jim hasn't released the AC2007 of MgdDbg yet, so it would AC2006 which I believe is different ..
.. .. but I'll have a look, and try to find any posts by Tony on the AD Newsgroup that refer to the issue.
Thanks.
This is the post:
http://discussion.autodesk.com/thread.jspa?messageID=5106861
-
Resurrected :
After a couple of years I have to admit some of my code was pretty primitive and unnecessarily complicated looking back then.
...