.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Identify Solid3d Object as Box or Cylinder

13 REPLIES 13
SOLVED
Reply
Message 1 of 14
wein3967
2718 Views, 13 Replies

Identify Solid3d Object as Box or Cylinder

I am trying to determine, via VB.NET, what a particular solid is in a selection set. I already separate out the solid3d objects from everything else (e.g., lines, circles). I was just wondering if there is a "simple" way to figure out if each solid is a box or cylinder. It seems like AutoCAD doesn't really make that distinction internally and just considers them solids. I've done some complicated slicing and such in the past, but I am hoping I may have missed something simpler and perhaps more elegant. Thanks for any ideas.

13 REPLIES 13
Message 2 of 14
hgasty1001
in reply to: wein3967

Hi,

 

If you only need to filter cubes and cylinders, you can check the bounding box of each shape, and compare its volume  to the volume of the solid (from the mass properties), if they are the same (may be using some tolerance) then it's a cube or a rectangular prism. I don't know of another way to identify geometric shapes than to get geometric properties and try to match them with known shapes.

 

Gaston Nunez

Message 3 of 14
wein3967
in reply to: hgasty1001

Gaston,

 

Thanks for the suggestion. I was/am actually currently just looking at trying out an approach like that. As far as I've worked it out, it may serve the purpose for my "ideal cases" (boxes and cylinders aligned orthographically). However, I'll need to think about how to assess boxes and cylinders that may be rotated along one or more axes. Thanks again. 

Message 4 of 14
dgorsman
in reply to: wein3967

Is this for any solid, or just for the ones you create?  If the latter, then you could simply flag them with extra information at the time of creation.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 5 of 14
_gile
in reply to: dgorsman

Hi,

 

For solid analysis, you can use the Boundary Representation, Brep class (have to reference the acdbmgdbrep.dll).

For example a cylinder Brep must have  a single Complex, 3 faces and 2 circular edges of the same radius.

 

Here's a little snippet which evaluates if a solid is a non truncated cylinder (both faces are circular and parallel)

 

        private bool IsCylinder(Solid3d solid)
        {
            using (Brep brep = new Brep(solid))
            {
                if (brep.Complexes.Count() != 1)
                    return false;
                if (brep.Faces.Count() != 3)
                    return false;
                BrepEdgeCollection edges = brep.Edges;
                if (edges.Count() != 2)
                    return false;
                CircularArc3d[] circles = brep.Edges
                    .Select(edge => ((ExternalCurve3d)edge.Curve).NativeCurve as CircularArc3d)
                    .Where(circle => circle != null)
                    .ToArray();
                if (circles.Length != 2)
                    return false;
                return 
                    circles[0].Radius == circles[1].Radius && 
                    circles[0].Normal.IsParallelTo(circles[1].Normal);
            }
        }

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 14
wein3967
in reply to: dgorsman

dgorsman,

 

The majority of the time it is for solids (boxes and cylinder othogonally aligned to an axis) that we draw. Occasionally, we get files from other people and we run it through our VB.NET code to see what comes through and what needs to be redrawn/removed. Flagging items as they are created sounds like a good idea, however, I am not familiar enough with that to know what the would entail coding-wise (for me) and drawing-wise (for the CAD guys).

Message 7 of 14
wein3967
in reply to: _gile

_gile,

 

The Boundary Representation class is a good idea. I have actually used it before, but it didn't occur to me that I might be able to implement it here. Once I get the Volume Comparision version working, I will try a Brep version as well. At the end of the day, the fastest one would be preferred (typically have a solids count up to 200,000). But there is something to be said for flexibility (potentailly correcting mal-aligned solids programatically) and a code path that others can follow. Thanks.

Message 8 of 14
dgorsman
in reply to: wein3967

Compared to BREP, solid analysis, and even creating your own solids, adding Dictionaries and Xrecords is dirt simple.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 9 of 14
wein3967
in reply to: dgorsman

dgorsman,

 

I am curious has to how you would generally envision that being implemented. I mean, would I need to write custom tools for making cylinders and boxes so that the Dictionaries and Xrecords were created as the solids are created? Or, would I end up putting the burden on the CAD guys by having them manually add the appropraite Xrecord to each object they make (don't think that would be terribly productive). At some point, someone or something has to determine the shape (box or cylinder) and the direction (x, y, z, for cylinders).

 

Assuming that this was implemented, it would be beneficial going forward. There are, of course, many past and current models which would not have these special records. So, some code processing will still be necessary for older stuff as well as models provided to us by 3rd parties. Thanks.

Message 10 of 14
dgorsman
in reply to: wein3967

If you already have something coded up to create your objects from a select set of data, then you are most of the way there.  Once you have the object and the inputs used to create that object, you pass them to another method which attaches the required data to the newly created object.  If you are hijacking the basic AutoCAD solid creation tools... not so easy, to the point where building your own tools makes control easier.

 

You've also identified a common problem in development: what do we do with legacy objects when something new is done?  In general, its a good idea to plan for the future before rolling something out.  You may identify areas which would better be handled now rather than trying to wrangle a square data into a round hole later on.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 11 of 14
wein3967
in reply to: dgorsman

The new system seems to be working effectively, right now. The code is essentailly a two step process and is designed to handle our older AutoCAD models as well as future models from outside our usual CAD department. The first step uses the Complex, Edge, and Face counts (via Brep) to identify if the solid is a Box or Cylinder. The second step uses the solid identification in step 1 along with a ratio of the solid's bounding box to the solid's volume. The ratio for orthogonal boxes is 1 and pi/4 for orthogonal cylinders. I implemented a tolerance to handle small rotations and small decimal deviations. However, for the future, we may try to implement our own drawing tools so we can potentially tag and specify shape data when solids are created. Thanks to all for your input.

Message 12 of 14
hericson
in reply to: _gile

Seems to work perfect for identifying cylinders. But how about to identify a ordinary box, or a wedge?

Message 13 of 14
hericson
in reply to: hericson

I answer myself. I don't know if this code is bullet proof but it works in my tests.

private static bool IsBox(Autodesk.AutoCAD.DatabaseServices.Solid3d solid)
{
	// A box have a single Complex, 6 faces (bottom, top, 4 sides) and 12 edges
	using (Brep brep = new Brep(solid))
	{
		 if (brep.Complexes.Count() != 1)
			  return false;
		 if (brep.Faces.Count() != 6)
			  return false;
		 if (brep.Edges.Count() != 12)
			  return false;
		 return
			  true;
	}
}

A wedge have 1 Complex, 5 Faces and 9 Edges.

A pyramid have 1 Complex, 5 Faces and 8 Edges.

Message 14 of 14
SEANT61
in reply to: hericson


@hericson wrote:

I answer myself. I don't know if this code is bullet proof but it works in my tests.

 

 

private static bool IsBox(Autodesk.AutoCAD.DatabaseServices.Solid3d solid)
{
	// A box have a single Complex, 6 faces (bottom, top, 4 sides) and 12 edges
	using (Brep brep = new Brep(solid))
	{
		 if (brep.Complexes.Count() != 1)
			  return false;
		 if (brep.Faces.Count() != 6)
			  return false;
		 if (brep.Edges.Count() != 12)
			  return false;
		 return
			  true;
	}
}

 

 

A wedge have 1 Complex, 5 Faces and 9 Edges.

A pyramid have 1 Complex, 5 Faces and 8 Edges.


 

Very often ‘bulletproof’ is overkill and ‘serves the purpose’ can carry the day.  The code snippet above is not bullet proof but could easily, and with great efficiency, work well with any file your workflow would need to process.

 

From my perspective, though, making code more bulletproof can be worth the effort.  It’s always better to have more robust code, and the subtleties of the APIs can be brought into focus whilst dealing with a halted debugger.

 

See the file for objects that may cause hiccups.  I’ve posted sample code that can handle much of the geometric oddities, but I wouldn’t even call that ‘bulletproof’.

 

 

 

        private static bool IsBox(Brep solidBrep)
        {
            int EdgeCount = 0;
            int FaceCount = 0;
            try
            {
                FaceCount = solidBrep.Faces.Count();
                EdgeCount = solidBrep.Edges.Count();
            }
            catch(Autodesk.AutoCAD.BoundaryRepresentation.Exception)
            {
                return false;
            }
            
            if (solidBrep.Complexes.Count() != 1) return false;
            if (FaceCount != 6) return false;
            if (EdgeCount != 12) return false;

            BrepFaceCollection Faces = solidBrep.Faces;
            bool isFirst = true;
            Vector3d TestLin;
            Vector3d FirstLin = new Vector3d();
            foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face fce in Faces)
            {
                ExternalBoundedSurface ebs = fce.Surface as ExternalBoundedSurface;
                CurveBoundary[] cb = ebs.GetContours();
                if (cb.Count() != 1) return false;
                if(cb[0].NumElements !=4) return false;

                PlanarEntity PlnEnt = ebs.BaseSurface as PlanarEntity;
                if (PlnEnt == null) return false;
                TestLin = PlnEnt.Normal;
                if (isFirst)
                {
                    FirstLin = TestLin;
                    isFirst = false;
                    continue;
                }
                if (!(FirstLin.IsParallelTo(TestLin) ^ FirstLin.IsPerpendicularTo(TestLin)))
                {
                    return false;
                }
            }
            
            return true;
        }

 

 

 


************************************************************
May your cursor always snap to the location intended.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost