A case study on creating an adaptive family essentially using a plane and model lines. This is a summary of an answer I posted on the Autodesk forum, now organized and published on CSDN.
If you directly use a profile family and read the profile family’s lines to creating geometry, you might encounter an issue where the shape mirrors after the path deflects. This happens because the normal vector changes when the reference attachment plane changes, causing the adaptive family to regenerate the shape with a different orientation during path offset.
If you need to lock the profile family to the path position, you only need to directly acquire the profile family’s reference. This way, like manual creation, the new correct shape will be effectively created automatically as the path offsets.
UIDocument uidoc = commandData.Application.ActiveUIDocument; Document familydoc1 = uidoc.Document; ReferencePointArray referencePointArray = new ReferencePointArray(); string filepath = @"D:\BeamSlabSection.rfa"; CurveByPoints curveByPoints = null;// Use adaptive points to create model line Curve curve = null;// Geometry curve from model line using (Transaction ts1 = new Transaction(familydoc1)) { ts1.Start("Create Adaptive Points"); for (int i = 0; i < 3; i++) { ReferencePoint referencePoint = familydoc1.FamilyCreate.NewReferencePoint(new XYZ(i, 0, 0)); AdaptiveComponentFamilyUtils.MakeAdaptivePoint(familydoc1, referencePoint.Id, AdaptivePointType.PlacementPoint); AdaptiveComponentFamilyUtils.SetPlacementNumber(familydoc1, referencePoint.Id, i + 1); referencePointArray.Append(referencePoint); } curveByPoints = familydoc1.FamilyCreate.NewCurveByPoints(referencePointArray); curve = curveByPoints.GeometryCurve; ts1.Commit(); } ReferenceArray pathReference = new ReferenceArray(); pathReference.Append(curve.Reference); IList<XYZ> tangents = (curve as HermiteSpline).Tangents;// Tangent collection at adaptive points of model line // Load CAD drawing instance
ReferenceArrayArray referenceArrayArray = new ReferenceArrayArray(); FilteredElementCollector collector1 = new FilteredElementCollector(familydoc1); FamilySymbol familySymbol = collector1.OfClass(typeof(FamilySymbol)).ToElements().FirstOrDefault(x => x.Name == "BeamSlab") as FamilySymbol; using (Transaction ts = new Transaction(familydoc1)) { ts.Start("Load CAD Instance"); for (int i = 0; i < 3; i++) { if (i == 1) { continue; } FamilyInstance instance = AdaptiveComponentInstanceUtils.CreateAdaptiveComponentInstance(familydoc1, familySymbol); IList<ElementId> placePointIds = AdaptiveComponentInstanceUtils.GetInstancePlacementPointElementRefIds(instance); ReferencePoint point = familydoc1.GetElement(placePointIds[0]) as ReferencePoint; // Bind loaded instance to model line if (i == 0) {
point.Position = curve.GetEndPoint(i); PointLocationOnCurve pointLocationOnCurve = new PointLocationOnCurve(PointOnCurveMeasurementType.NormalizedCurveParameter, 0, PointOnCurveMeasureFrom.Beginning); PointOnEdge pointOnEdge = application.Create.NewPointOnEdge(curve.Reference, pointLocationOnCurve); point.SetPointElementReference(pointOnEdge as PointElementReference); } else { point.Position = curve.GetEndPoint(i - 1); PointLocationOnCurve pointLocationOnCurve = new PointLocationOnCurve(PointOnCurveMeasurementType.NormalizedCurveParameter, 1, PointOnCurveMeasureFrom.Beginning); PointOnEdge pointOnEdge = application.Create.NewPointOnEdge(curve.Reference, pointLocationOnCurve); point.SetPointElementReference(pointOnEdge as PointElementReference); } } // Make loaded CAD drawing instance tangent to model line FilteredElementCollector collector2 = new FilteredElementCollector(familydoc1); List<Element> elements1 = collector2.OfClass(typeof(FamilyInstance)).ToList(); for (int i = 0; i < 3; i++) { if (i == 2) { continue; } if (elements1[i] is FamilyInstance familyInstance) { XYZ location = (familyInstance.Location as LocationPoint).Point; Transform transform = familyInstance.GetTotalTransform(); Line line = Line.CreateBound(location, new XYZ(location.X + 1, location.Y, location.Z)); double angle = tangents[i].AngleTo(transform.BasisX); bool flag = tangents[i].CrossProduct(transform.BasisX).Z < 0; if (flag) {
familyInstance.Location.Rotate(line, angle); } else { familyInstance.Location.Rotate(line, -angle); } } } FilteredElementCollector elements2 = new FilteredElementCollector(familydoc1); List<FamilyInstance> familyInstances = elements2.OfClass(typeof(FamilyInstance)).Cast<FamilyInstance>().ToList(); TaskDialog.Show("Revit",familyInstances.Count.ToString()); for (int i = 0; i < 2; i++) { ReferenceArray referenceArray = new ReferenceArray(); GeometryElement geometryElement = familyInstances[i].get_Geometry(new Options()); //if (i == 1) //{ // i++; //} //double u1 = curve.Project(new XYZ(i, 0, 0)).Parameter; //Transform transform1 = curve.ComputeDerivatives(u1, false); //XYZ normal =XYZ.BasisY; //Plane plane = Plane.CreateByNormalAndOrigin(normal, new XYZ(i, 0, 0)); //SketchPlane sketchPlane = SketchPlane.Create(familydoc1, plane); //foreach (var item in geometryElement) //{ // if (item is GeometryInstance geometryInstance) // { // GeometryElement geometryElement1 = geometryInstance.GetInstanceGeometry(); // foreach (var item1 in geometryElement1) // { // if (item1 is Curve curve1) // { // ModelCurve modelCurve = familydoc1.FamilyCreate.NewModelCurve(curve1, sketchPlane); // Reference referenceInstnce = modelCurve.GeometryCurve.Reference; // referenceArray.Append(referenceInstnce); // } // } // } //} referenceArray.Append(new Reference(familyInstances[i])); referenceArrayArray.Append(referenceArray); } ts.Commit(); }
using (Transaction tran = new Transaction(familydoc1)) { tran.Start("Create"); Form form = familydoc1.FamilyCreate.NewSweptBlendForm(true, pathReference, referenceArrayArray);