The previous method works well for straight, continuous rigid frame bridges. However, it falls short when applied to continuous rigid frame bridges with both horizontal and vertical curves. This limitation arises because each segment of such a bridge can be considered an irregular structure. Attempting to manually create a separate family for each segment is both time-consuming and inefficient. To address this, secondary development techniques are required.
First, it is essential to clarify the modeling goals and identify the necessary mathematical principles.
The desired outcomes are as follows:
1) The beam segment’s cross-section must be perpendicular to the horizontal curve of the route. This is crucial because many users model the bridge using spatial curves and adaptive component families, which often results in the cross-section being perpendicular to the spatial curve rather than strictly the horizontal curve.
2) To accommodate vertical curves, the cross-section must be adjusted vertically along the z-axis to the correct elevation.
3) To achieve these effects, the process begins by generating lines through the adaptive component family’s reference points, where each point represents the center of a beam section. The section family is then placed at each corresponding point and rotated so that it is perpendicular to the tangent vector at that point. Finally, the section is moved to the correct 3D position, and a Form structure is generated.
The following class demonstrates the specific implementation:
class CreatJM
{
/// <summary>
/// Creates the beam section family.
/// </summary>
/// <param name="familyDoc">The family document.</param>
/// <param name="revitDoc">The Revit project document.</param>
/// <param name="revitApp">The Revit application.</param>
/// <param name="i">Index of the segment.</param>
/// <param name="filePath1">File path for outer section family.</param>
/// <param name="filePath2">File path for inner section family.</param>
/// <returns>The loaded family instance.</returns>
public Family CreatFamiliesItem(Document familyDoc, Document revitDoc, Application revitApp, int i, string filePath1, string filePath2)
{
FamilyInstance famIns1;
FamilyInstance famIns2;
FamilyInstance famIns3;
FamilyInstance famIns4;
Plane plane1 = new Plane();
Plane plane2 = new Plane();
using (Transaction transaction1 = new Transaction(familyDoc))
{
transaction1.Start("Create Reference Curves");
#region Horizontal Curve
ReferencePointArray refPointArray = new ReferencePointArray();
for (int j = 0; j < ListData.ListXYZ_X.Count; j++)
{
ReferencePoint referencePoint = familyDoc.FamilyCreate.NewReferencePoint(new XYZ(ListData.ListXYZ_X[j], ListData.ListXYZ_Y[j], 0));
refPointArray.Append(referencePoint);
}
CurveByPoints curve = familyDoc.FamilyCreate.NewCurveByPoints(refPointArray);
#endregion
#region Vertical Curve
ReferencePointArray refPointArray2 = new ReferencePointArray();
for (int j = 0; j < ListData.ListXYZ_X.Count; j++)
{
ReferencePoint referencePoint2 = familyDoc.FamilyCreate.NewReferencePoint(new XYZ(ListData.ListXYZ_X[j], ListData.ListXYZ_Y[j], ListData.ListXYZ_Z[j]));
refPointArray2.Append(referencePoint2);
}
CurveByPoints curve2 = familyDoc.FamilyCreate.NewCurveByPoints(refPointArray2);
#endregion
famIns1 = LocationFamilyInstance(familyDoc, filePath1, curve2.GetPoints().get_Item(i).Position, (curve.GeometryCurve as HermiteSpline).Tangents[i], i);
famIns2 = LocationFamilyInstance(familyDoc, filePath1, curve2.GetPoints().get_Item(i + 1).Position, (curve.GeometryCurve as HermiteSpline).Tangents[i + 1], i + 1);
famIns3 = LocationFamilyInstance2(familyDoc, filePath2, curve2.GetPoints().get_Item(i).Position, (curve.GeometryCurve as HermiteSpline).Tangents[i], i);
famIns4 = LocationFamilyInstance2(familyDoc, filePath2, curve2.GetPoints().get_Item(i + 1).Position, (curve.GeometryCurve as HermiteSpline).Tangents[i + 1], i + 1);
plane1 = new Plane((curve.GeometryCurve as HermiteSpline).Tangents[i], curve.GetPoints().get_Item(i).Position);
plane2 = new Plane((curve.GeometryCurve as HermiteSpline).Tangents[i + 1], curve.GetPoints().get_Item(i + 1).Position);
familyDoc.Delete(curve.Id);
familyDoc.Delete(curve2.Id);
refPointArray.Clear();
refPointArray2.Clear();
transaction1.Commit();
}
using (Transaction transaction2 = new Transaction(familyDoc))
{
transaction2.Start("Generate Beam Form");
ReferenceArray profiles0 = GetReferenceArrayFromFamilyInstance(familyDoc, famIns1, plane1);
ReferenceArray profiles1 = GetReferenceArrayFromFamilyInstance(familyDoc, famIns2, plane2);
ReferenceArray profiles2 = GetReferenceArrayFromFamilyInstance(familyDoc, famIns3, plane1);
ReferenceArray profiles3 = GetReferenceArrayFromFamilyInstance(familyDoc, famIns4, plane2);
ReferenceArrayArray profilesArray = new ReferenceArrayArray();
profilesArray.Append(profiles0);
profilesArray.Append(profiles1);
Form form = familyDoc.FamilyCreate.NewLoftForm(true, profilesArray);
ReferenceArrayArray profilesArray2 = new ReferenceArrayArray();
profilesArray2.Append(profiles2);
profilesArray2.Append(profiles3);
Form form2 = familyDoc.FamilyCreate.NewLoftForm(false, profilesArray2);
string paramName = "Material";
familyDoc.FamilyManager.AddParameter(paramName, BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, true);
transaction2.Commit();
Family loadedFamily = familyDoc.LoadFamily(revitDoc, new ProjiectFamLoadOption());
return loadedFamily;
}
}
/// <summary>
/// Retrieves the reference array for the beam section.
/// </summary>
/// <param name="familyDoc">Family document.</param>
/// <param name="famIns">Family instance.</param>
/// <param name="plane">Reference plane.</param>
/// <returns>Reference array of the section curves.</returns>
private ReferenceArray GetReferenceArrayFromFamilyInstance(Document familyDoc, FamilyInstance famIns, Plane plane)
{
ReferenceArray profilesArray = new ReferenceArray();
Options opt = new Options();
IList<Curve> curves1 = new List<Curve>();
GeometryElement e = famIns.get_Geometry(opt);
foreach (GeometryObject obj in e)
{
GeometryInstance geoInstance = obj as GeometryInstance;
GeometryElement geoElement = geoInstance.GetInstanceGeometry();
foreach (GeometryObject obj2 in geoElement)
{
if (obj2 is Line || obj2 is Arc)
{
Curve curve = obj2 as Curve;
ModelCurve modelcurve = familyDoc.FamilyCreate.NewModelCurve(curve, SketchPlane.Create(familyDoc, plane));
profilesArray.Append(modelcurve.GeometryCurve.Reference);
}
}
}
return profilesArray;
}
/// <summary>
/// Places the outer section family at the specified location with correct orientation.
/// </summary>
/// <param name="familyDoc">Family document.</param>
/// <param name="filePath">File path of the family.</param>
/// <param name="location">Location point in 3D space.</param>
/// <param name="normal">Normal vector for orientation.</param>
/// <param name="i">Segment index.</param>
/// <returns>Placed family instance.</returns>
private FamilyInstance LocationFamilyInstance(Document familyDoc, string filePath, XYZ location, XYZ normal, int i)
{
FamilySymbol familySymbol = null;
bool loaded = familyDoc.LoadFamilySymbol(filePath, System.IO.Path.GetFileNameWithoutExtension(filePath), out familySymbol);
familySymbol.Activate();
List<Autodesk.Revit.Creation.FamilyInstanceCreationData> list = new List<Autodesk.Revit.Creation.FamilyInstanceCreationData>();
list.Add(new Autodesk.Revit.Creation.FamilyInstanceCreationData(location, familySymbol, StructuralType.NonStructural));
var familyInstancesIds = familyDoc.FamilyCreate.NewFamilyInstances2(list);
FamilyInstance familyInstance = familyDoc.GetElement(familyInstancesIds.ElementAt(0)) as FamilyInstance;
LocationPoint point = familyInstance.Location as LocationPoint;
Line axis = Line.CreateBound(location, new XYZ(location.X, location.Y, location.Z + 1));
double angle = normal.AngleTo(new XYZ(1, 0, 0));
if (normal.CrossProduct(new XYZ(1, 0, 0)).Z < 0)
{
point.Rotate(axis, angle);
}
else
{
point.Rotate(axis, -angle);
}
IList<Parameter> heightParams = familyInstance.GetParameters("H");
heightParams[0].Set(ListData.List_height[i]);
return familyInstance;
}
/// <summary>
/// Places the inner section family at the specified location with correct orientation.
/// </summary>
/// <param name="familyDoc">Family document.</param>
/// <param name="filePath">File path of the family.</param>
/// <param name="location">Location point in 3D space.</param>
/// <param name="normal">Normal vector for orientation.</param>
/// <param name="i">Segment index.</param>
/// <returns>Placed family instance.</returns>
private FamilyInstance LocationFamilyInstance2(Document familyDoc, string filePath, XYZ location, XYZ normal, int i)
{
FamilySymbol familySymbol = null;
bool loaded = familyDoc.LoadFamilySymbol(filePath, System.IO.Path.GetFileNameWithoutExtension(filePath), out familySymbol);
familySymbol.Activate();
List<Autodesk.Revit.Creation.FamilyInstanceCreationData> list = new List<Autodesk.Revit.Creation.FamilyInstanceCreationData>();
list.Add(new Autodesk.Revit.Creation.FamilyInstanceCreationData(location, familySymbol, StructuralType.NonStructural));
var familyInstancesIds = familyDoc.FamilyCreate.NewFamilyInstances2(list);
FamilyInstance familyInstance = familyDoc.GetElement(familyInstancesIds.ElementAt(0)) as FamilyInstance;
LocationPoint point = familyInstance.Location as LocationPoint;
Line axis = Line.CreateBound(location, new XYZ(location.X, location.Y, location.Z + 1));
double angle = normal.AngleTo(new XYZ(1, 0, 0));
if (normal.CrossProduct(new XYZ(1, 0, 0)).Z < 0)
{
point.Rotate(axis, angle);
}
else
{
point.Rotate(axis, -angle);
}
IList<Parameter> paramHi1 = familyInstance.GetParameters("Hi1");
paramHi1[0].Set(ListData.List_Hi1[i]);
IList<Parameter> paramHi5 = familyInstance.GetParameters("Hi5");
paramHi5[0].Set(ListData.List_Hi5[i]);
IList<Parameter> paramT = familyInstance.GetParameters("T");
paramT[0].Set(ListData.List_t[i]);
IList<Parameter> paramH = familyInstance.GetParameters("H");
paramH[0].Set(ListData.List_height[i]);
return familyInstance;
}
}
You can see the specific result in the following video:
http://v.youku.com/v_show/id_XMjgwMjcwMjY3Ng==.html













Must log in before commenting!
Sign Up