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.

How to solve the issue of adaptive family flipping when moving adaptive points during secondary development

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.

new Reference(familyInstances[i])

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
UIApplication uIApplication = commandData.Application;
Autodesk.Revit.ApplicationServices.Application application = uIApplication.Application;

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);

tran.Commit();
}
![Snipaste_2026-01-04_15-22-40.png](https://cdn.bimath.com/blog/pg/Snipaste_2026-01-04_15-22-40.png)
![Snipaste_2026-01-04_15-22-45.png](https://cdn.bimath.com/blog/pg/Snipaste_2026-01-04_15-22-45.png)