TheSwamp

Code Red => .NET => Topic started by: johnpolob on December 08, 2018, 08:14:17 PM

Title: How to align ucs with solid in C#
Post by: johnpolob on December 08, 2018, 08:14:17 PM
Hello everyone, I have to calculate in C # the width and the length of many solids in my drawing. But some of them are not in the same plane, for example a solid inclined relative to the z axis and therefore the dimension is wrong. I would have liked to change some ucs and calculate the width of this entity to be correct.
Any help would be welcome.
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 08, 2018, 10:48:15 PM
this thread should be of some help, cheers.

https://www.theswamp.org/index.php?topic=51518.0

<added>
If you need to process existing 3dsolids then you will need the user to pick 3 points to define at least 2 axis vectors (say the base point of a face then a point along an edge for the Z axis for extrusion length then the third point anywhere else on the face to produce the width axis), the third axis is a simple normal calc to produce it.
Title: Re: How to align ucs with solid in C#
Post by: gile on December 09, 2018, 02:43:39 AM
Hello everyone, I have to calculate in C # the width and the length of many solids in my drawing. [...]

You should clarify this because "the width and the length" of an entity does not depend on a coordinate system (e.g. the length of a line remains the same whatever the coodinate system).
So, you should describe with more details how you measure these solids.
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 09, 2018, 08:56:56 AM
Hi Gile,

Thank you for this fast reply.

To measure my solids (entity), I use the code below and It's working well with the standard solids that are not oblique:

public double EntityWidth(Entity ent)
            {
            double Width;
            Extents3d ext = ent.GeometricExtents;
            Width = ext.MaxPoint.X - ext.MinPoint.X;

            return Width;
            }

My problem is that I don't want to calculate myself the hypotenuse to have my solid length. It's the reason why I was believe that I can only change the ucs then calculate the length of oblique solid basing on this one.

If you have another way the get out this problem, I will be very happy to know It...

Thank you in advance for anyone who can help me.
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 09, 2018, 09:09:28 AM
Hi MickD,

I will check this solution tomorrow and let you know if It's working...

Thank you...
Title: Re: How to align ucs with solid in C#
Post by: gile on December 09, 2018, 11:12:39 AM
Entity.GeometricExtents always creates the bounding box of the entity about WCS axes.

You can get the bounding box about the current UCS axes by transforming the entity (Solid3d or whatever else) from WCS to UCS, getting the GeometricExtents of the transformed solid and transform it back to WCS.

Here's a little example:
Code - C#: [Select]
  1.         static Extents3d GetExtentsAboutUCS(Entity entity)
  2.         {
  3.             var ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
  4.             var ucs2wcs = ed.CurrentUserCoordinateSystem;
  5.             var wcs2ucs = ucs2wcs.Inverse();
  6.             Extents3d extents;
  7.             if (!entity.IsWriteEnabled)
  8.                 entity.UpgradeOpen();
  9.             entity.TransformBy(wcs2ucs);
  10.             try { extents = entity.GeometricExtents; }
  11.             finally { entity.TransformBy(ucs2wcs); }
  12.             return extents;
  13.         }
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 09, 2018, 12:02:01 PM
Hi Gile,

Thank you for this example.

I will try It tomorrow and let you know.

Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 10, 2018, 06:01:43 AM
Hi Gile,

First of all, I would like to thank you for your help.

I try to use your function and it works well.

Now, I have another problem with the automatic detection of ucs of my entity.

Please, could you show me a way to do it?
Title: Re: How to align ucs with solid in C#
Post by: ribarm on December 10, 2018, 06:34:44 AM
3D SOLIDS don't have UCS property bounded to entity they represent... You could only try to align UCS to one of it's faces if it has them and then orient axis of UCS you want to some reference edge of face or its vertex... Sorry but I think you are stuck here IMHO...
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 10, 2018, 07:25:14 AM
Hi ribarm,

Thank you for your contribution.

I will try to define some conditions to determine the ucs of my entity (solid).
Title: Re: How to align ucs with solid in C#
Post by: dgorsman on December 10, 2018, 09:58:45 AM
Hi ribarm,

Thank you for your contribution.

I will try to define some conditions to determine the ucs of my entity (solid).

One way to handle that would be controlled creation of the 3D solids, such that they include a proper set of XDATA.  There's a handful of data types which represent vectors that are automatically modified as the host entity is moved, rotated, and/or scaled.

But otherwise yeah - getting face data for arbitrary solids is not pretty at best.
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 10, 2018, 02:28:27 PM
Hi All,

I gave up the idea of ​​automatically detecting the ucs of my solid entities
But to calculate the length of the oblique entities, I try to calculate the hypotenuse knowing here that it is an isosceles triangle. So, according to Pythagoras' theorem, C² = A² + B²; but I know that A = B  then C = √2A².
The height on the Z axis that I consider is slightly larger than expected.
Here is the function that I use to have the height in Z
public double EntityHeight (Entity ent)
            {
            double Height;
            Extents3d ext = ent.GeometricExtents;
            Height = ext.MaxPoint.Z - ext.MinPoint.Z;
            return Height;
            }
My problem is that the result is always 14 mm higher than expected.
For example the hypotenuse should be 1178 and the height in Z 833 but my results are 1192 for the hypotenuse and 843 for Z.

Could somebody helps me to fix this issue or an another  way to calculate this.
Title: Re: How to align ucs with solid in C#
Post by: kdub_nz on December 10, 2018, 05:37:05 PM
johnpolob,

It may help anyone who has time to look at this issue if you were to attach a basic simple drawing model showing the solid you have problems with.

Regards,
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 11, 2018, 02:37:30 AM
Hi kdub,

Thank you very much for this good idea.

Please find in attached my DWG with a solid.

Let me know if you can fix this issue.

Thank you...
Title: Re: How to align ucs with solid in C#
Post by: SEANT on December 11, 2018, 04:03:17 AM
That files gives the impression that your 3d modeling is more concerned with processed sheet stock rather than lengths of extrusions.  If that were the case then I'd recommend using the BoundaryRepresentation namespace functions to analyze the faces to find the two largest, see if they have Normals that are parallel, though not codirectional.  Once found, the solid can be transformed to have that vector aligned to the World Z. 

Subsequent analysis of the edges to find the longest (though, finding 2 edges that are perpendicular to themselves as well as the Z axis may be more accurate) and set that parallel to the X axis, perhaps.
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 11, 2018, 04:32:38 AM
There really is no easy way to do this by 'inspection'. Even if you pick the longest edge for length say, you may have grain/pattern direction of the finished surface to deal with. There are many other edge cases as well. MillLister/SmartLister (cabinet making material lister) came the closest but then you still needed to check the length/width/height directions and edit them if not quite right for purpose.

Storing world point xdata upon creation is the easiest solution even if you have to add it manually for old models. The beauty is if you move, edit or copy the object the data goes and gets updated with it. I spent many hours on this in the past (even inspecting BREP in C++ before C# came along) and apart from creating a 'custom object' this is the easiest solution IMO.
Title: Re: How to align ucs with solid in C#
Post by: SEANT on December 11, 2018, 06:05:28 AM
This ‘Solid Dimensions’ conundrum has been debated numerous times before.  As a matter of fact, it seems to crop up every other year like clockwork. 

And, as has been mentioned before, some of the programming options will be based on the level of control a programmer has over the workflow used during the ‘digital mass’ creation.

If the ‘non- workflowed’ files containing old models are of sufficient mass, the “. . . . Storing world point xdata upon creation is the easiest solution even if you have to add it manually for old models . . . .”  could be rather daunting. 

What might help is a routine that could pre-process the mass to find a most likely orientation. 8-)
Title: Re: How to align ucs with solid in C#
Post by: It's Alive! on December 11, 2018, 07:48:11 AM
SmartLister (cabinet making material lister)

Hey, I remember them, Dave right?  They did good work  8-)
Title: Re: How to align ucs with solid in C#
Post by: It's Alive! on December 11, 2018, 08:10:55 AM
This ‘Solid Dimensions’ conundrum has been debated numerous times before...

like this thread?
https://www.theswamp.org/index.php?topic=24045.0
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 11, 2018, 03:27:36 PM
SmartLister (cabinet making material lister)

Hey, I remember them, Dave right?  They did good work  8-)

Yep, that's the one :)
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 11, 2018, 03:38:36 PM
This ‘Solid Dimensions’ conundrum has been debated numerous times before.  As a matter of fact, it seems to crop up every other year like clockwork. 

And, as has been mentioned before, some of the programming options will be based on the level of control a programmer has over the workflow used during the ‘digital mass’ creation.

If the ‘non- workflowed’ files containing old models are of sufficient mass, the “. . . . Storing world point xdata upon creation is the easiest solution even if you have to add it manually for old models . . . .”  could be rather daunting

What might help is a routine that could pre-process the mass to find a most likely orientation. 8-)

IDK, the pre-processing solids sounds more daunting to me :)
I'll see if I can dig out my old code to add the xdata at creation and for retro fit, be back a bit later :)
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 11, 2018, 05:05:34 PM
Here's some snippets of the types of data I add to the 3d solid at creation time, this is part of a much larger class that holds a 3dSolid (_solid) as a private property and the x, y, z values etc as class properties, these can be calculated and set from the polyline plane and normal or however you want to calculate your ECS. I use the extrusion direction and/or normal of the polyline I'm about to extrude.
Just remember to normalise the vectors to make it easier later.

Hopefully it's a good starting point for someone :)

Code - C#: [Select]
  1.                 public void SetXData()
  2.                 {
  3.      // check for xdata app name
  4.                         if(Utils.CheckForAppName())
  5.                         {
  6.                                 ResultBuffer resbuf = new ResultBuffer();
  7.                                 Point3d pntL = new Point3d(_start.X,_start.Y,_start.Z);
  8.                                 Point3d pntR = new Point3d(_end.X,_end.Y,_end.Z);
  9.                                 Point3d pntX = new Point3d(_vecX.X,_vecX.Y,_vecX.Z);
  10.                                 Point3d pntY = new Point3d(_vecY.X,_vecY.Y,_vecY.Z);
  11.                                 Point3d pntZ = new Point3d(_vecZ.X,_vecZ.Y,_vecZ.Z);
  12.                                 resbuf.Add(new TypedValue(1001, "MY_APPNAME"));
  13.                                 resbuf.Add(new TypedValue(1011,pntL));
  14.                                 resbuf.Add(new TypedValue(1011,pntR));
  15.                                 resbuf.Add(new TypedValue(1013,pntX)); // world 3D point data types
  16.                                 resbuf.Add(new TypedValue(1013,pntY)); // these get updated
  17.                                 resbuf.Add(new TypedValue(1013,pntZ)); // with modifications
  18.                                 _solid.XData = resbuf;
  19.                         }
  20.  
  21.                         else
  22.                         {
  23.                                 Utils.PrintMessage("\nFailed to add xdata!..");
  24.                         }
  25.                
  26.                 }
  27.  

And a bit of a hack to get the data back into a hash table to make it easier to consume, once you have this you can transform the solid to get the bounding box and length (code below)

Code - C#: [Select]
  1.                 private void GetXdata()
  2.                 {
  3.                         ResultBuffer rb = new ResultBuffer();
  4.                         rb = (ResultBuffer)_solid.GetXDataForApplication("MY__APPNAME");
  5.                         if(rb != null)
  6.                         {
  7.                                 Hashtable ht = new Hashtable();
  8.                                 IEnumerator iter = rb.GetEnumerator();
  9.                                 int i = 0; //count for ht
  10.                                 while (iter.MoveNext())
  11.                                 {
  12.                                         TypedValue tv = (TypedValue)iter.Current;
  13.                                         ht.Add(i,tv.Value);
  14.                                         i++;           
  15.                                 }
  16.                                 //set the property values
  17.                                 Point3d x = new Point3d();
  18.                                 Point3d y = new Point3d();
  19.                                 Point3d z = new Point3d();
  20.                                 Point3d L = new Point3d();
  21.                                 Point3d R = new Point3d();
  22.                                 L = (Point3d)ht[1]; // left end
  23.                                 R = (Point3d)ht[2]; // right end
  24.                                 x = (Point3d)ht[3];
  25.                                 y = (Point3d)ht[4];
  26.                                 z = (Point3d)ht[5];
  27.                                 _start = L; // class properties...
  28.                                 _end = R;
  29.                                 _vecX = new Vector3d(x.X,x.Y,x.Z);
  30.                                 _vecY = new Vector3d(y.X,y.Y,y.Z);
  31.                                 _vecZ = new Vector3d(z.X,z.Y,z.Z);
  32.                         }
  33.                
  34.                 }
  35.  

The _solid is a property of my 3dSolid class and the vectors are set using the code above:
Code - C#: [Select]
  1.                 private double GetLength()
  2.                 {
  3.                         Matrix3d mat = new Matrix3d();
  4.                         Plane plane = new Plane(new Point3d(0,0,0), _vecZ);
  5.                         mat = Matrix3d.WorldToPlane(plane); // transform solid from current position to WCS
  6.                         _solid.TransformBy(mat);
  7.                         double length = _solid.GeometricExtents.MaxPoint.Z - _solid.GeometricExtents.MinPoint.Z;
  8.                         _solid.TransformBy(mat.Inverse()); // transform it back
  9.                         return length;
  10.                 }
  11.  

Here's some code to add xdata to existing solids.

Code - C#: [Select]
  1.                 public static ResultBuffer SetCustomData()
  2.                 {
  3.                         Database db = HostApplicationServices.WorkingDatabase;
  4.                         Editor ed = Bricscad.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
  5.  
  6.                         PromptPointResult pntOri = ed.GetPoint("\nPick 3 points of primary face/view:\nPick origin point(bottom left):");
  7.                         if(pntOri.Status != PromptStatus.OK || pntOri.Status == PromptStatus.Cancel)
  8.                                 return null;
  9.  
  10.                         PromptPointResult pnt2 = ed.GetPoint("\nPick point in 'X' direction of face/view:");
  11.                         if(pnt2.Status != PromptStatus.OK || pnt2.Status == PromptStatus.Cancel)
  12.                                 return null;
  13.  
  14.                         PromptPointResult pnt3 = ed.GetPoint("\nPick point in 'Y' direction of face/view:");
  15.                         if(pnt3.Status != PromptStatus.OK || pnt3.Status == PromptStatus.Cancel)
  16.                                 return null;
  17.  
  18.                         Point3d or = new Point3d();
  19.                         Point3d X = new Point3d();
  20.                         Point3d Y = new Point3d();
  21.                         or = Utils.UcsToWcs(pntOri.Value);
  22.                         X = Utils.UcsToWcs(pnt2.Value);
  23.                         Y = Utils.UcsToWcs(pnt3.Value);
  24.  
  25.                         Vector3d vecx = new Vector3d();
  26.                         Vector3d vecy = new Vector3d();
  27.                         Vector3d vecz = new Vector3d();
  28.  
  29.                         vecz = or.GetVectorTo(X).GetNormal(Tolerance.Global);
  30.                         vecy = or.GetVectorTo(Y);
  31.                         vecx = vecz.CrossProduct(vecy).GetNormal(Tolerance.Global);
  32.                         vecy = vecx.CrossProduct(vecz).GetNormal(Tolerance.Global);
  33.  
  34.                         if(Utils.CheckForAppName())
  35.                         {
  36.                                 ResultBuffer resbuf = new ResultBuffer();
  37.                         {
  38.                                 Point3d pntL = new Point3d(or.X,or.Y,or.Z);
  39.                                 Point3d pntR = new Point3d(X.X,X.Y,X.Z);
  40.                                 Point3d pntX = new Point3d(vecx.X,vecx.Y,vecx.Z);
  41.                                 Point3d pntY = new Point3d(vecy.X,vecy.Y,vecy.Z);
  42.                                 Point3d pntZ = new Point3d(vecz.X,vecz.Y,vecz.Z);
  43.                                 resbuf.Add(new TypedValue(1001,Utils.AppName));
  44.                                 resbuf.Add(new TypedValue(1011,pntL));
  45.                                 resbuf.Add(new TypedValue(1011,pntR));
  46.                                 resbuf.Add(new TypedValue(1013,pntX));
  47.                                 resbuf.Add(new TypedValue(1013,pntY));
  48.                                 resbuf.Add(new TypedValue(1013,pntZ));
  49.                         }
  50.                                
  51.                                 return resbuf;
  52.                         }
  53.                         else
  54.                         {
  55.                                 Utils.PrintMessage("\nFailed to add xdata!..");
  56.                                 return null;
  57.                         }
  58.                
  59.                 }
  60.  

Title: Re: How to align ucs with solid in C#
Post by: kdub_nz on December 11, 2018, 11:14:00 PM
Hi Mick,

I can sort of visualise how that fitted into your work process.

I assume you'd add component description/catalog at the same time.

It would make material take-off a little simpler.

Stay well.
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 11, 2018, 11:30:45 PM
Hi Mick,

I can sort of visualise how that fitted into your work process.

I assume you'd add component description/catalog at the same time.

It would make material take-off a little simpler.

Stay well.

Yes, you got it Kerry, I quickly stripped out the extraneous stuff like section and item numbers etc. I used an Access DB for section profile data and created solids from 2 points, lines or from profiles from plates. I'd use the code above along with the line/2 points picked and current UCS to build my ECS data and add it to the solid.
I haven't used this code for quite a while now but might dig it out for an update, I think I've held back as I wanted to convert the DB to an SQLite setup as the Access drivers are well dated now.

I also used the ECS data with the 2D engine I built to automatically create drawings and matlists, it worked pretty well for stock solid modelling. Bricscad has come a long way since then and I don't think it's needed anymore :)
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 12, 2018, 04:57:00 AM
Hi everybody,
Thank you all for your ideas and solutions.
I still gave up my last idea and I'm stuck here.
I have another idea but I do not know if I can implement it.
The idea is to make sure that all my solids are in the same plane and then I can measure them.
Could someone have an example for this kind of case?
Need your help.
Title: Re: How to align ucs with solid in C#
Post by: SEANT on December 12, 2018, 05:51:47 AM
Hi everybody,
Thank you all for your ideas and solutions.
I still gave up my last idea and I'm stuck here.
I have another idea but I do not know if I can implement it.
The idea is to make sure that all my solids are in the same plane and then I can measure them.
Could someone have an example for this kind of case?
Need your help.

Did the link in nullptr's post (#18) contain anything you can use?
Title: Re: How to align ucs with solid in C#
Post by: SEANT on December 12, 2018, 05:57:12 AM
Here's some snippets of the types of data I add to the 3d solid at creation time, this is part of a much larger class that holds a 3dSolid (_solid) as a private property and the x, y, z values etc as class properties, these can be calculated and set from the polyline plane and normal or however you want to calculate your ECS. I use the extrusion direction and/or normal of the polyline I'm about to extrude.
Just remember to normalise the vectors to make it easier later.

Hopefully it's a good starting point for someone :)


That looks like some highly effective and terse code.  Thank you for sharing.  That is an incredible leg up on the pre-model process methodology.

I’ve got some code prepped for post-model.  Still quite a work in progress – and, certainly, not nearly as terse.  I’ll look it over again in the next few weeks and post the project in whatever state it is in at that point.

I mostly focused on extruded profiles.  The hope was to not only get the lengths, but also some post modeling profile recognition.  So If I knew someone was modeling with the aid of “Al’s Steel Mill”, a type and quantity takeoff could be made by comparing Profile Area, Perimeter, and Moments of Inertia. 

I’m referring to the methodology as POCS (Preponderance of Coordinated Systems).  It’s reasonably effective at recovering extrusion direction.  As can be seen in the screencast, though,  the profile recognition still needs some work.

https://autode.sk/2Bmfkjp
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 12, 2018, 06:02:19 AM
Hi SEANT,

Thank you for the link.

I never saw It when I wrote down my last idea.

At first, It could help me.

I will try to test It and let you know.

Thank you very much...
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 12, 2018, 06:16:29 AM
Hi MickD,

Thank you very much for your contribution.

I am working on It.
Title: Re: How to align ucs with solid in C#
Post by: MickD on December 13, 2018, 12:34:19 AM

I mostly focused on extruded profiles.  The hope was to not only get the lengths, but also some post modeling profile recognition.  So If I knew someone was modeling with the aid of “Al’s Steel Mill”, a type and quantity takeoff could be made by comparing Profile Area, Perimeter, and Moments of Inertia. 


Yep, my code is focused more on the pre-modelling as you say and I only work with extrusions of steel profiles and plates. Not shown in the code is the extra data I add such as section profile data, weight calculations (which takes cuts and holes into consideration), surface area etc. The standard section data is added at creation and lengths and weights are added/updated during processing for material lists etc.

The reason I gave up on trying to get LWH from existing solids is I knew that practically all my new work would be created using my tools which made things a lot easier. What would have made my tools really good was to make an 'auto-numbering' tool, this was the weak link in my workflow otherwise I could model a steel job just as quick as a more professional detailing package.
Auto dimensions would also have been nice and  I had plans for that too...just not enough free time to do it :)
Title: Re: How to align ucs with solid in C#
Post by: SEANT on December 13, 2018, 02:42:25 AM
. . . . more professional detailing package.

. . . .

Sounds like you're very close to requiring the rephrase ". . . . the other professional detailing packages." 

Free time is elusive. Hope you can hunt some down to bring it all together. 
Title: Re: How to align ucs with solid in C#
Post by: johnpolob on December 13, 2018, 07:35:44 AM
Hi All,

Thank you all for your ideas and solutions.

My problem is now solved.

I have made a small adaptation for the code of the link :

https://www.theswamp.org/index.php?topic=24045.0

Thank you so much to nullptr who wrote this.

And many thanks to all the participants of this topic.