Create Solid from CAD polylines

Create Solid from CAD polylines

miguel.gutierrezD74CZ
Advocate Advocate
677 Views
6 Replies
Message 1 of 7

Create Solid from CAD polylines

miguel.gutierrezD74CZ
Advocate
Advocate

I've been working on a macros that creates a solid from a CAD file:

UIDocument uidoc = this.ActiveUIDocument;
			Document doc = uidoc.Document;
			StringBuilder stb = new StringBuilder();
			
			Element dwg=doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element));
			
			Options opt= new Options();
			opt.ComputeReferences = true;
			opt.IncludeNonVisibleObjects=false;
			opt.View = doc.ActiveView;
			GeometryElement geo = dwg.get_Geometry(opt);

			//Tuple<int,List<XYZ>> myTuple = new Tuple<int, List<XYZ>()>() ;
			List<Tuple<int,IList<XYZ>>> myTuple = new List<Tuple<int, IList<XYZ>>>();
			
			foreach (GeometryObject g in geo) {
				if (g as GeometryInstance != null) {
					GeometryInstance geoInst=g as GeometryInstance;
					foreach (GeometryObject obj in geoInst.GetInstanceGeometry()) {
						if (obj as PolyLine != null) {
							PolyLine pln=obj as PolyLine;
							IList<XYZ> coordinates= pln.GetCoordinates();
							myTuple.Add(new Tuple<int,IList<XYZ>> ( pln.Id,coordinates) );
						}
					} 
				}
			}
			myTuple= myTuple.OrderBy(X=>X.Item1).ToList();
			
			SolidOptions solidOpt = new SolidOptions(ElementId.InvalidElementId,ElementId.InvalidElementId);
			Transaction tr = new Transaction(doc,"solid");
			tr.Start();	
			
//			for (int i = 0; i < myTuple.Count -1 ; i++) {
//				
//				if (HermiteSpline.Create(myTuple[i].Item2,false).IsClosed == true && HermiteSpline.Create(myTuple[i+1].Item2,false).IsClosed == true) {
////					stb.AppendLine("closed");
////					CurveLoop cl1 = new CurveLoop();
////					cl1.Append(HermiteSpline.Create(myTuple[i].Item2,false));
////					
////					CurveLoop cl2 = new CurveLoop();
////					cl2.Append(HermiteSpline.Create(myTuple[i+1].Item2,false));
////					
////					Solid loft = GeometryCreationUtilities.CreateBlendGeometry(cl1,cl2,null); 
//					
//					
//				}
//				CurveLoop cl1 = new CurveLoop();
//				cl1.Append(HermiteSpline.Create(myTuple[i].Item2,false));
//				
//				CurveLoop cl2 = new CurveLoop();
//				cl2.Append(HermiteSpline.Create(myTuple[i+1].Item2,false));
//				
//				Solid loft = GeometryCreationUtilities.CreateBlendGeometry(cl1,cl2,null); 
//			}
			
			for (int i = 0; i < myTuple.Count -1; i++) {
				List<CurveLoop> profile = new List<CurveLoop>();
				CurveLoop cl1=new CurveLoop();
				CurveLoop cl2=new CurveLoop();
				cl1.Append(HermiteSpline.Create(myTuple[i].Item2,false));
				cl2.Append(HermiteSpline.Create(myTuple[i+1].Item2,false));
				profile.Add(cl1);
				profile.Add(cl2);
				Solid loft = GeometryCreationUtilities.CreateLoftGeometry(profile,solidOpt);
				
			}

Sometimes it Keeps telling me there are opened curves which in turns is not true as when I picked the bend top and bottom face, I see a closed boundary. 

miguelgutierrezD74CZ_1-1655252811363.jpeg

Other times it just fails. I've been struggling using createBlendSolid and Loft solid. Even direct shape form:

miguelgutierrezD74CZ_2-1655252822886.png

			UIDocument uidoc = this.ActiveUIDocument;
			Document doc = uidoc.Document;
			StringBuilder stb = new StringBuilder();
			
			Element dwg=doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element));
			Options opt= new Options();
			opt.ComputeReferences = true;
			opt.IncludeNonVisibleObjects=false;
			opt.View = doc.ActiveView;
			GeometryElement geo = dwg.get_Geometry(opt);
			int count=0;
			Dictionary<int,IList<XYZ>> dictionary = new Dictionary<int, IList<XYZ>>();
			
			foreach (GeometryObject g in geo) {
				if (g as GeometryInstance != null) {
					
					GeometryInstance geoInst=g as GeometryInstance;
					foreach (GeometryObject obj in geoInst.GetInstanceGeometry()) {
						if (obj as PolyLine != null) {
							PolyLine pln=obj as PolyLine;
							IList<XYZ> coordinates= pln.GetCoordinates();
							dictionary.Add(count, coordinates);
							count += 1;

						}
						
					} 
					
				}
				
			}

			
			Transaction tr = new Transaction(doc,"solid - afry");
			tr.Start();
			IList<Element> materials = new FilteredElementCollector(doc).OfClass(typeof(Material)).ToElements().ToList();
			Material mat = null;
			foreach (Material mate in materials) {
				if (mate.Name == "Concrete, Cast In Situ") {
					mat=mate;
				}
			}
			TessellatedShapeBuilder builder= new TessellatedShapeBuilder();
			builder.OpenConnectedFaceSet(true);
			
			foreach (KeyValuePair<int,IList<XYZ>> pair in dictionary) {
				//stb.AppendLine(pair.Key.ToString());
				IList<XYZ> outerLoopVertices = new List<XYZ>();
				for (int i = 0; i < pair.Value.Count - 2; i++) {
					outerLoopVertices.Add(pair.Value[i]);
					outerLoopVertices.Add(pair.Value[i+1]);
					outerLoopVertices.Add(pair.Value[i+2]);
				}
//				TessellatedFace tesseFace= new TessellatedFace(pair.Value,mat.Id);
//				if (builder.DoesFaceHaveEnoughLoopsAndVertices(tesseFace)) {
//					builder.AddFace(tesseFace);
//					//stb.AppendLine(tesseFace.ToString());
//					//stb.AppendLine(tesseFace.GetBoundaryLoops().ToString());
//				}
				TessellatedFace tesseFace= new TessellatedFace(outerLoopVertices,mat.Id);
				if (builder.DoesFaceHaveEnoughLoopsAndVertices(tesseFace)) {
					builder.AddFace(tesseFace);
				}
			}
			
			builder.CloseConnectedFaceSet();
			
			builder.Target = TessellatedShapeBuilderTarget.Solid;
			builder.Fallback=TessellatedShapeBuilderFallback.Abort;
			
			builder.Build();
			
			TessellatedShapeBuilderResult result = builder.GetBuildResult();
			
			ElementId categoryId= new ElementId(BuiltInCategory.OST_GenericModel);
			DirectShape ds=DirectShape.CreateElement(doc,categoryId);
			ds.SetShape(result.GetGeometricalObjects());
			ds.Name="Presa";

			tr.Commit();

 

 

 

 

 

What we expect:

 

miguelgutierrezD74CZ_0-1655251889613.png

We have a bunch of DWG data and it takes a lot to manually creating blend components. Any suggestions on how to improve my code or find the issue of this matter?

miguelgutierrezD74CZ_3-1655252948847.png

 

Best regards, Miguel G

 

 

Accepted solutions (1)
678 Views
6 Replies
Replies (6)
Message 2 of 7

jeremy_tammik
Alumni
Alumni

Yes, two suggestions. Whenever you run into an issue trying to create a solid via the API like this, it may help to test the solid creation manually in the end user interface using the same underlying geometry data, as described in:

 

https://thebuildingcoder.typepad.com/blog/2009/07/debug-geometric-form-creation.html

 

The UI will often provide much more useful information on why a specific solid generation fails.

 

It may even help to implement your own little curve loop visualisation:

 

https://thebuildingcoder.typepad.com/blog/2013/04/geosnoop-net-boundary-curve-loop-visualisation.htm...

 

You can also mix the two a bit: generate model curves to represent your curve loops and the extrusion paths, so that you can see better exactly what is being calculated, in case the solid generation fails.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 7

RPTHOMAS108
Mentor
Mentor

You will virtually never be able to close a Hermite spline from a set of polyline points, the end tangents of the spline need to be compatible. What you'll end up with also wouldn't be representative of the polyline i.e. the acute changes of direction would be significantly smoothed out. If you try to close it by making the first point the last then it may even become self intersecting.

 

You should break your polyline profile into a number of splines within your CurveLoop. Perhaps considering the significance of angle formed between n and n-1 against n and n+1 in terms of deciding if the polyline should be split at that point.

 

I can't understand what you are doing with the shape builder.

 

Do you have an example to share of the DWG you are inputting?

 

Message 4 of 7

miguel.gutierrezD74CZ
Advocate
Advocate

That's right, UI seems to blend the solid from the dwg polylines. Fair enough, I'll represent my curve loops one at the time to have more insights. Stay bless Jeremy!

Message 5 of 7

miguel.gutierrezD74CZ
Advocate
Advocate

I've not bear in mind that small detail. I'll follow your recommendations , thanks Thomas for the insights! Regarding the direct shape, My goal was to input the polylines points and make a solid out of them. Is there any changes I might need to do to the direct shape code I provided above?

I'm attaching the DWG file too:

Message 6 of 7

RPTHOMAS108
Mentor
Mentor
Accepted solution

Hello @miguel.gutierrezD74CZ 

 

Having looked at the dwg I can make the following comments:

There are a lot of overlapping lines that need to be resolved into single lines. Generally the Polylines will be formed from connected lines of the same layer/colour. It is not obvious how this will be treated if you have two lines overlapping i.e. will a flat closed loop of two lines be created.

When you import the dwg you should use the option that doesn't correct the out of axis lines. This option straightens lines and could make certain loops open, there is a loop on layer 'E2990500' that suffers from this.

 

220619a.PNG

In any case you can exclude these loops by reviewing CurveLoop.IsOpen after you form them.

 

For the below I used NurbSpline and Lines to create the loft, each set of lines was resolved into a loop and each loop was coloured in a sequence of Red/Green/Blue (open loops where coloured magenta).

 

Plotting and colouring the loops in this way allows you to see any errors i.e. if a loop at a certain level was formed from two open loops (instead of one closed loop) then the colour sequence would be discontinuous.

 

220619b.PNG

Resulting loft with omitted open loop for loft coloured magenta

 

 

Message 7 of 7

miguel.gutierrezD74CZ
Advocate
Advocate

Thanks for replying Thomas and for the recommendations you've provide as well. So you made it by drawing lines as well, gonna give it shoot following your steps then.

 

Cheers dear colleague!

0 Likes