Hello,
I am sweeping along a closed path, consisting of two arcs connected at each of their ends with straight lines.
When I only sweep along the straight lines and one arc between them, it works. I can exchange arcs, and it also works.
But in the closed loop configuration, i.e. both arcs and the connecting straight lines, it fails with the following message:
exc = {"createSweptSolid failed when creating the Swept solid."}
Below the code for the arcs and the methods used.
What am I doing wrong?
Regards, DIrk
var segment = "HT_STL_G_COMPONENT BORED TUNNEL STANDARD TYPE 1"; double OUTER_SEAL_RADIUS = Length.MetersToFeet(5.500 / 2.0) - Length.MetersToFeet(0.04); double startAngle = -Angle.DegreeToRadiant(11.25); double endAngle = Angle.DegreeToRadiant(56.25); Arc arc_top = Arc.Create(planeTop, OUTER_SEAL_RADIUS, startAngle, endAngle); ModelArc upperArc = CreateModelCurve(doc, planeTop, arc_top); Arc arc_bottom = Arc.Create(planeBottom, OUTER_SEAL_RADIUS, startAngle, endAngle); ModelArc lowerArc = CreateModelCurve(doc, planeBottom, arc_bottom); var lowerArcReversed = lowerArc.GeometryCurve.CreateReversed(); //vertical connectors var upperStart = upperArc.GeometryCurve.GetEndPoint(0); var lowerFin = lowerArcReversed.GetEndPoint(1); var startLine = Creator.CreateModelLine(doc, lowerFin, upperStart); var upperFin = upperArc.GeometryCurve.GetEndPoint(1); var lowerStart = lowerArcReversed.GetEndPoint(0); var finLine = Creator.CreateModelLine(doc, upperFin, lowerStart); Debug.WriteLine("startLine: {0};{1}", startLine.GetCurve().GetEndPoint(0), startLine.GetCurve().GetEndPoint(1)); Debug.WriteLine("upperArc: {0};{1}", upperArc.GetCurve().GetEndPoint(0), upperArc.GetCurve().GetEndPoint(1)); Debug.WriteLine("finLine: {0};{1}", finLine.GetCurve().GetEndPoint(0), finLine.GetCurve().GetEndPoint(1)); Debug.WriteLine("lowerArcReversed: {0};{1}", lowerArcReversed.GetEndPoint(0), lowerArcReversed.GetEndPoint(1)); CurveLoop sweepes = new CurveLoop(); sweepes.Append(startLine.GeometryCurve); sweepes.Append(upperArc.GeometryCurve); sweepes.Append(finLine.GeometryCurve); sweepes.Append(lowerArcReversed); Solid seal = sealProfile(doc, segment, pnt, width, sweepes);
Solid sealProfile(Document doc, string segment, XYZ center, double width, CurveLoop sweeps) { CurveLoop profileLoop = null; Solid solid = null; Line initV = null; ElementId categoryId = new ElementId(BuiltInCategory.OST_GenericModel); DirectShape ds = null; List<GeometryObject> solids = null; XYZ vt = new XYZ(0, 0, width); XYZ origin_top = center - vt; XYZ origin_bottom = center + vt; try { //get the sweep, get plane per to first sweep vector, //then you instantiate the cross-section in that plane to get it normal to the first sweep vector double param = sweeps.First().GetEndParameter(0); Curve firstCurve = sweeps.First(); XYZ xyz = firstCurve.GetEndPoint(0); Transform tr = firstCurve.ComputeDerivatives(0, true); var v = XYZ.BasisZ; var v_normaltostartofarc = tr.OfVector(v); //tilt this profile into the sweep path XYZ endPoint1 = (sweeps.First() as Curve).Tessellate().ElementAt(0); XYZ endPoint2 = (sweeps.First() as Curve).Tessellate().ElementAt(1); initV = Line.CreateBound(endPoint1, endPoint2); var tangent = initV.Direction.CrossProduct(XYZ.BasisZ); //Plane LoopPlane = new Plane(initV.Direction, endPoint1); Plane LoopPlane = new Plane(tr.BasisX.Normalize(), tr.Origin); var _profilepoints = new List<XYZ>() { FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-10,0)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-11.36,-7.7)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-14.15,-10.49)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-13,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-11,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-10.27,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-9.41,-12.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-7.95,-12)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-6.49,-12.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-5.63,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-4.91,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-2.91,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-2.18,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-1.4,-12.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(0,-12)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(1.4,-12.5 )), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(2.18,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(2.91,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(4.91,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(5.63,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(6.49,-12.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(7.95,-12)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(9.41,-12.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(10.27,-13.78)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(11,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(13,-16.5)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(14.15,-10.49)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(11.36,-7.7)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(10,0)), FAIR_Space.Extensions.MmToFootPlanePoint(LoopPlane,new UV(-10,0)) }; profileLoop = new CurveLoop(); for (int i = 0; i < (_profilepoints.Count - 1); i++) { Line line = Line.CreateBound(_profilepoints[i], _profilepoints[i + 1]); profileLoop.Append(line); } //rotate profileLoop on plane into position //ray from centroid to point of insertion var ray = origin_bottom - endPoint1; var angle = ray.AngleOnPlaneTo(XYZ.BasisX, LoopPlane.Normal); Debug.WriteLine("Segment [{0}]: {1}°", segment, Angle.RadiantToDegree(angle)); //var angle = Math.PI / 2 + Angle.DegreeToRadiant(33.75); var transform = Transform.CreateRotationAtPoint(LoopPlane.Normal, angle, endPoint1); profileLoop.Transform(transform); IList<CurveLoop> profileLoops = new List<CurveLoop>(); profileLoops.Add(profileLoop); SolidOptions solOptions = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId); solid = GeometryCreationUtilities.CreateSweptGeometry(sweeps /*sweepPath*/, 0, param, profileLoops, solOptions); categoryId = new ElementId(BuiltInCategory.OST_GenericModel); ds = DirectShape.CreateElement(doc, categoryId, Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); solids = new List<GeometryObject>() { solid }; ds.SetShape(solids); ds.Name = "ExtrusionTest3"; //SolidSolidCutUtils } catch (Exception exc) { Debug.WriteLine(exc); } return solid; } public static XYZ MmToFootPlanePoint(Plane plane, UV pt) { return plane.Origin + plane.XVec.Multiply(pt.U / 304.8) + plane.YVec.Multiply(pt.V / 304.8); }
Solved! Go to Solution.
Solved by FAIR59. Go to Solution.
You're not doing anything wrong. I'm afraid this is a Revit "thing" , too much going on in the corner, start face and end face.
A closed path (rectangular) in a plane works fine!!
Solution :
split your first Curve/Line in 2 halves. That way the direction at the start of the path is the same as the direction at the end.
pathLoop.Append( end halve); // line 1 in picture
pathLoop.Append( curve); // line 2 in picture
...
pathLoop.Append( start halve); // line 5 in picture
Thanks, I tried your suggestion. I split the left vertical line.
When I add the upper part of the left vertical line, the two Arcs and the right vertical line to the
CurveLoop Array, CreateSweptGeometry works fine, see pic. However, when I add the last line Segment (the lower half of the left vertical line), in order to close the path, the method call cracks with:
+ exc {"createSweptSolid failed when creating the Swept solid."} System.Exception {Autodesk.Revit.Exceptions.InternalException}
I think I found a reason why this does not work, even though it should work anyway, since the start and finish coincide.
The upper and lower arcs are drawn on planes which are slightly offset to each other. The reason being that the tunnel lining ring, composed of the segments, as a slightly conical shape if seen from the side. This is done so that rings can be turned in the axial direction so that the Tunnel Boring Machine can change direction.
If the lower plane is slightly offset w.r.t. the upper plane, then the lower arc will be slightly shorter compared to the upper one, if projected into the same plane as the upper arc. Is it possible to draw the lower arc in the same plane as the upper one, and then transform it into the offset plane, so that it automatically becomes longer?
- planeTop {Autodesk.Revit.DB.Plane} Autodesk.Revit.DB.Plane + base {Autodesk.Revit.DB.Plane} Autodesk.Revit.DB.Surface {Autodesk.Revit.DB.Plane} + Normal {(0.000000000, 0.000000000, 1.000000000)} Autodesk.Revit.DB.XYZ + Origin {(0.000000000, 0.000000000, -7.536093855)} Autodesk.Revit.DB.XYZ + XVec {(1.000000000, 0.000000000, 0.000000000)} Autodesk.Revit.DB.XYZ + YVec {(0.000000000, 1.000000000, 0.000000000)} Autodesk.Revit.DB.XYZ - planeBottom {Autodesk.Revit.DB.Plane} Autodesk.Revit.DB.Plane + base {Autodesk.Revit.DB.Plane} Autodesk.Revit.DB.Surface {Autodesk.Revit.DB.Plane} + Normal {(0.000000000, 0.008181544, 0.999966531)} Autodesk.Revit.DB.XYZ + Origin {(0.000000000, 0.000000000, -12.148945515)} Autodesk.Revit.DB.XYZ + XVec {(1.000000000, 0.000000000, 0.000000000)} Autodesk.Revit.DB.XYZ + YVec {(0.000000000, 0.999966531, -0.008181544)} Autodesk.Revit.DB.XYZ
When you say slight offset, do you mean a different position of the centerpoint?, or a different Radius?
Also I notice that the planeBottom is not vertical. Is that intentional?
If nothing else works you could combine 2 U shaped solids in the DirectShape.
No I mean the planes are not exactly parallel to each other. The upper plane is horizontal, and the lower one tilts slightly downwards. I solved that part by projecting 3 vertical rays down from the upper Arc, at each end and in the middle.
Then I used the method below to determine the intersection Points on the plane below, which is at a slight angle to the horizontal.
Those 3 Points I then use to construct a new Arc, which is a projection of the upper arc on the lower plane.
I checked the x and y values of each projected Point, and they are exactly the same, as one would expect from a proper projection. So that part is OK.
However, when I then try to Close the path with the last remaining line Segment, the method again Fails.
So I am going to embark on another solution:
It seems there is no other solution, is that correct?
The curve in the tilted plane isn't an Arc anymore, but an Ellipse.
If the seal is in the outer curved plane, I would find the method used so far to be good enough,
The alternative method of creating corners will probably give you the same problems with regards to direction/placement of profile.
Hello FAIR59,
thanks for answering. Of course you're right about the ellipse, I only noticed now. Generally the solution is good. However,
the Problem at the edges is that the Profile does not properly turn the corner, resulting in the profile being imprintend on the longitudinal section:
Regards, DIrk
Hello FAIR59,
can any of this be avoided by running the corresponding sweep command in a Family Document, and then doing a FamilyInstance in the project document?
Regards, Dirk
Hello FAIR59,
I have 2 more questions:
Regards, Dirk
I think you have the same kind of creation methods in the Family Editor, so the same kind of problems.
We're trying to connect the square with the curved lines (see picture), so Revit has to make some adjustments.
In modelling I sometimes first make something bigger and then cut it back with a Void
Regards Frank
Hello FAIR59,
thanks for the advice. I am accepting this as a solution, but I have 3 questions:
1. How can I transform a Solid? I tried applying the transform (below) to the solid which I obtain from the sweep, but the solid does not react to it.
Transform.CreateRotationAtPoint or Transform.CreateTranslation
2. Is there a way to convert a Solid into an Element?
3. Is there an Extrusion/Sweep method which yields an Element?
Regards, Dirk
Hello Dirk
Maybe you'd have to go to the FamilyEditor afterall, then the result is an FamilyInstance
answer to ealier question, (maybe you've already found the answer):
material for the solid:
SolidOptions solOptions = new SolidOptions(_material.Id, ElementId.InvalidElementId);
Regards Frank
Hello Frank,
thanks for the pointers.
I figured having to do transformations beforehand. I got partial results, but conisidering the effort, I am reconsidering FamilyDocument. Transforming a FamilyInstance would be easier than doing it for each plane seperately on which a seal is swept.
If I sweep the seals in a FamilyDocument, and then instantiate that via FamilyInstance, will they react to a Transformation as a unit?
Regards, Dirk
Btw: where do I obtain material?
Regards, DIrk