/// <summary> /// Get the hook orient of the top rebar /// </summary> /// <param name="geomInfo">the rebar geometry support information</param> /// <param name="location">the location of top rebar</param> /// <returns>the hook orient of the top hook</returns> private RebarHookOrientation GetTopHookOrient(RebarGeometry geomInfo, TopRebarLocation location) { // Top center rebar doesn't need hook. if (TopRebarLocation.Center == location) { throw new Exception("Center top rebar doesn't have any hook."); } // Get the hook direction, rebar normal and rebar line Autodesk.Revit.DB.XYZ hookVec = m_geometry.GetDownDirection(); Autodesk.Revit.DB.XYZ normal = geomInfo.Normal; Line rebarLine = geomInfo.Curves[0] as Line; // get the top start hook orient if (TopRebarLocation.Start == location) { Autodesk.Revit.DB.XYZ curveVec = GeomUtil.SubXYZ(rebarLine.GetEndPoint(1), rebarLine.GetEndPoint(0)); return(GeomUtil.GetHookOrient(curveVec, normal, hookVec)); } else // get the top end hook orient { Autodesk.Revit.DB.XYZ curveVec = GeomUtil.SubXYZ(rebarLine.GetEndPoint(0), rebarLine.GetEndPoint(1)); return(GeomUtil.GetHookOrient(curveVec, normal, hookVec)); } }
/// <summary> /// Get two vectors, which indicate some edge direction which contain given point, /// set the given point as the start point, the other end point of the edge as end /// </summary> /// <param name="point">a point of the swept profile</param> /// <returns>two vectors indicate edge direction</returns> protected List <Autodesk.Revit.DB.XYZ> GetRelatedVectors(Autodesk.Revit.DB.XYZ point) { // Initialize the return vector list. List <Autodesk.Revit.DB.XYZ> vectors = new List <Autodesk.Revit.DB.XYZ>(); // Get all the edge which contain this point. // And get the vector from this point to another point foreach (Line line in m_edges) { if (GeomUtil.IsEqual(point, line.GetEndPoint(0))) { Autodesk.Revit.DB.XYZ vector = GeomUtil.SubXYZ(line.GetEndPoint(1), line.GetEndPoint(0)); vectors.Add(vector); } if (GeomUtil.IsEqual(point, line.GetEndPoint(1))) { Autodesk.Revit.DB.XYZ vector = GeomUtil.SubXYZ(line.GetEndPoint(0), line.GetEndPoint(1)); vectors.Add(vector); } } // only two vector(direction) should be found if (2 != vectors.Count) { throw new Exception("a point on swept profile should have only two direction."); } return(vectors); }
/// <summary> /// Create the transverse rebars, according to the location of transverse rebars /// </summary> /// <param name="location">location of rebar which need to be created</param> /// <returns>the created rebar, return null if the creation is unsuccessful</returns> public Rebar FillTransverseBar(TransverseRebarLocation location) { // Get the geometry information which support rebar creation RebarGeometry geomInfo = new RebarGeometry(); switch (location) { case TransverseRebarLocation.Start: // start transverse rebar case TransverseRebarLocation.End: // end transverse rebar geomInfo = m_geometry.GetTransverseRebar(location, m_transverseEndSpacing); break; case TransverseRebarLocation.Center:// center transverse rebar geomInfo = m_geometry.GetTransverseRebar(location, m_transverseCenterSpacing); break; } RebarHookOrientation startHook = RebarHookOrientation.Right; RebarHookOrientation endHook = RebarHookOrientation.Left; if (!GeomUtil.IsInRightDir(geomInfo.Normal)) { startHook = RebarHookOrientation.Left; endHook = RebarHookOrientation.Right; } // create the rebar return(PlaceRebars(m_transverseType, m_transverseHookType, m_transverseHookType, geomInfo, startHook, endHook)); }
/// <summary> /// Get the geometry information of bottom rebar /// </summary> /// <returns>the gotten geometry information</returns> public RebarGeometry GetBottomRebar() { // sort the points of the swept profile XYZHeightComparer comparer = new XYZHeightComparer(); m_points.Sort(comparer); // Get the normal parameter for bottom rebar creation List <Autodesk.Revit.DB.XYZ> directions = GetRelatedVectors(m_points[0]); directions.Sort(comparer); Autodesk.Revit.DB.XYZ normal = directions[0]; double offset = BeamRebarData.BottomOffset; //offset value of the rebar int rebarNumber = BeamRebarData.BottomRebarNumber; //the number of the rebar // the spacing of the rebar double spacing = (m_beamWidth - 2 * offset) / (rebarNumber - 1); // Get the curve which define the shape of the bottom rebar curve List <Autodesk.Revit.DB.XYZ> movedPoints = OffsetPoints(offset); Autodesk.Revit.DB.XYZ startPoint = movedPoints[0]; //get the coordinate of startpoint //get the coordinate of endpoint Autodesk.Revit.DB.XYZ endPoint = GeomUtil.OffsetPoint(startPoint, m_drivingVector, m_beamLength); IList <Curve> curves = new List <Curve>(); //the profile of the bottom rebar curves.Add(Line.CreateBound(startPoint, endPoint)); // return the rebar geometry information return(new RebarGeometry(normal, curves, rebarNumber, spacing)); }
/// <summary> /// Get the geometry information for top rebar /// </summary> /// <param name="location">indicate where top rebar is placed</param> /// <returns>the gotten geometry information</returns> public RebarGeometry GetTopRebar(TopRebarLocation location) { // sort the points of the swept profile XYZHeightComparer comparer = new XYZHeightComparer(); m_points.Sort(comparer); // Get the normal parameter for rebar creation List <Autodesk.Revit.DB.XYZ> directions = GetRelatedVectors(m_points[3]); directions.Sort(comparer); Autodesk.Revit.DB.XYZ normal = directions[1]; double offset = 0; //the offset from the beam surface to the rebar double startPointOffset = 0; // the offset of start point from swept profile double rebarLength = m_beamLength / 3; //the length of the rebar int rebarNumber = BeamRebarData.TopRebarNumber; //the number of the rebar // set offset and startPointOffset according to the location of rebar switch (location) { case TopRebarLocation.Start: // top start rebar offset = BeamRebarData.TopEndOffset; break; case TopRebarLocation.Center: // top center rebar offset = BeamRebarData.TopCenterOffset; startPointOffset = m_beamLength / 3 - 0.5; rebarLength = m_beamLength / 3 + 1; break; case TopRebarLocation.End: // top end rebar offset = BeamRebarData.TopEndOffset; startPointOffset = m_beamLength * 2 / 3; break; default: throw new Exception("The program should never go here."); } // Get the curve which define the shape of the top rebar curve List <Autodesk.Revit.DB.XYZ> movedPoints = OffsetPoints(offset); Autodesk.Revit.DB.XYZ startPoint = movedPoints[movedPoints.Count - 1]; // offset the start point according startPointOffset startPoint = GeomUtil.OffsetPoint(startPoint, m_drivingVector, startPointOffset); // get the coordinate of endpoint Autodesk.Revit.DB.XYZ endPoint = GeomUtil.OffsetPoint(startPoint, m_drivingVector, rebarLength); IList <Curve> curves = new List <Curve>(); //the profile of the top rebar curves.Add(Line.CreateBound(startPoint, endPoint)); // the spacing of the rebar double spacing = spacing = (m_beamWidth - 2 * offset) / (rebarNumber - 1); // return the rebar geometry information return(new RebarGeometry(normal, curves, rebarNumber, spacing)); }
/// <summary> /// Get the swept profile(face) of the host object(family instance) /// </summary> /// <param name="solid">the solid reference</param> /// <returns>the swept profile</returns> private Face GetSweptProfileFace(Solid solid) { // Get a point on the swept profile from all points in solid Autodesk.Revit.DB.XYZ refPoint = new Autodesk.Revit.DB.XYZ(); // the point on swept profile foreach (Edge edge in solid.Edges) { List <XYZ> points = edge.Tessellate() as List <XYZ>; //get end points of the edge if (2 != points.Count) // make sure all edges are lines { throw new Exception("All edge should be line."); } // get two points of the edge. All points in solid should be transform first Autodesk.Revit.DB.XYZ first = Transform(points[0]); // start point of edge Autodesk.Revit.DB.XYZ second = Transform(points[1]); // end point of edge // some edges should be parallelled with the driving line, // and the start point of that edge should be the wanted point Autodesk.Revit.DB.XYZ edgeVector = GeomUtil.SubXYZ(second, first); if (GeomUtil.IsSameDirection(edgeVector, m_drivingVector)) { refPoint = first; break; } if (GeomUtil.IsOppositeDirection(edgeVector, m_drivingVector)) { refPoint = second; break; } } // Find swept profile(face) Face sweptFace = null; // define the swept face foreach (Face face in solid.Faces) { if (null != sweptFace) { break; } // the swept face should be perpendicular with the driving line if (!GeomUtil.IsVertical(face, m_drivingLine, m_transform, null)) { continue; } // use the gotted point to get the swept face foreach (Autodesk.Revit.DB.XYZ point in face.Triangulate().Vertices) { Autodesk.Revit.DB.XYZ pnt = Transform(point); // all points in solid should be transform if (GeomUtil.IsEqual(refPoint, pnt)) { sweptFace = face; break; } } } return(sweptFace); }
/// <summary> /// Get the width of the column /// </summary> /// <returns>the width data</returns> private double GetColumnWidth() { XYZHeightComparer comparer = new XYZHeightComparer(); m_points.Sort(comparer); Autodesk.Revit.DB.XYZ refPoint = m_points[0]; List <Autodesk.Revit.DB.XYZ> directions = GetRelatedVectors(refPoint); directions.Sort(comparer); return(GeomUtil.GetLength(directions[1])); }
int IComparer <Autodesk.Revit.DB.XYZ> .Compare(Autodesk.Revit.DB.XYZ first, Autodesk.Revit.DB.XYZ second) { // first compare z coordinate, then y coordinate, at last x coordinate if (GeomUtil.IsEqual(first.Z, second.Z)) { if (GeomUtil.IsEqual(first.Y, second.Y)) { if (GeomUtil.IsEqual(first.X, second.X)) { return(0); } return((first.X > second.X) ? 1 : -1); } return((first.Y > second.Y) ? 1 : -1); } return((first.Z > second.Z) ? 1 : -1); }
/// <summary> /// get the orient of hook accroding to curve direction, rebar normal and hook direction /// </summary> /// <param name="curveVec">the curve direction</param> /// <param name="normal">rebar normal direction</param> /// <param name="hookVec">the hook direction</param> /// <returns>the orient of the hook</returns> public static RebarHookOrientation GetHookOrient(Autodesk.Revit.DB.XYZ curveVec, Autodesk.Revit.DB.XYZ normal, Autodesk.Revit.DB.XYZ hookVec) { Autodesk.Revit.DB.XYZ tempVec = normal; for (int i = 0; i < 4; i++) { tempVec = GeomUtil.CrossMatrix(tempVec, curveVec); if (GeomUtil.IsSameDirection(tempVec, hookVec)) { if (i == 0) { return(RebarHookOrientation.Right); } else if (i == 2) { return(RebarHookOrientation.Left); } } } throw new Exception("Can't find the hook orient according to hook direction."); }
/// <summary> /// Offset the points of the swept profile to make the points inside swept profile /// </summary> /// <param name="offset">indicate how long to offset on two directions</param> /// <returns>the offset points</returns> protected List <Autodesk.Revit.DB.XYZ> OffsetPoints(double offset) { // Initialize the offset point list. List <Autodesk.Revit.DB.XYZ> points = new List <Autodesk.Revit.DB.XYZ>(); // Get all points of the swept profile, and offset it in two related direction foreach (Autodesk.Revit.DB.XYZ point in m_points) { // Get two related directions List <Autodesk.Revit.DB.XYZ> directions = GetRelatedVectors(point); Autodesk.Revit.DB.XYZ firstDir = directions[0]; Autodesk.Revit.DB.XYZ secondDir = directions[1]; // offset the point in two direction Autodesk.Revit.DB.XYZ movedPoint = GeomUtil.OffsetPoint(point, firstDir, offset); movedPoint = GeomUtil.OffsetPoint(movedPoint, secondDir, offset); // add the offset point into the array points.Add(movedPoint); } return(points); }
/// <summary> /// Get the geometry information of the transverse rebar /// </summary> /// <param name="location">the location of transverse rebar</param> /// <param name="spacing">the spacing value of the rebar</param> /// <returns>the gotted geometry information</returns> public RebarGeometry GetTransverseRebar(TransverseRebarLocation location, double spacing) { // sort the points of the swept profile XYZHeightComparer comparer = new XYZHeightComparer(); m_points.Sort(comparer); // the offset from the column surface to the rebar double offset = ColumnRebarData.TransverseOffset; //the length of the transverse rebar double rebarLength = 0; // get the origin and normal parameter for rebar creation Autodesk.Revit.DB.XYZ normal = m_drivingVector; double curveOffset = 0; //set rebar length and origin according to the location of rebar switch (location) { case TransverseRebarLocation.Start: // start transverse rebar rebarLength = m_columnHeight / 4; break; case TransverseRebarLocation.Center: // center transverse rebar rebarLength = m_columnHeight / 2; curveOffset = m_columnHeight / 4 + (rebarLength % spacing) / 2; break; case TransverseRebarLocation.End: // end transverse rebar rebarLength = m_columnHeight / 4; curveOffset = m_columnHeight - rebarLength + (rebarLength % spacing); break; default: throw new Exception("The program should never go here."); } // the number of the transverse rebar int rebarNumber = (int)(rebarLength / spacing) + 1; // get the profile of the transverse rebar List <Autodesk.Revit.DB.XYZ> movedPoints = OffsetPoints(offset); List <Autodesk.Revit.DB.XYZ> translatedPoints = new List <Autodesk.Revit.DB.XYZ>(); foreach (Autodesk.Revit.DB.XYZ point in movedPoints) { translatedPoints.Add(GeomUtil.OffsetPoint(point, m_drivingVector, curveOffset)); } IList <Curve> curves = new List <Curve>(); //the profile of the transverse rebar Autodesk.Revit.DB.XYZ first = translatedPoints[0]; Autodesk.Revit.DB.XYZ second = translatedPoints[1]; Autodesk.Revit.DB.XYZ third = translatedPoints[2]; Autodesk.Revit.DB.XYZ fourth = translatedPoints[3]; curves.Add(Line.CreateBound(first, second)); curves.Add(Line.CreateBound(second, fourth)); curves.Add(Line.CreateBound(fourth, third)); curves.Add(Line.CreateBound(third, first)); // return the rebar geometry information return(new RebarGeometry(normal, curves, rebarNumber, spacing)); }
/// <summary> /// Get the geometry information of vertical rebar /// </summary> /// <param name="location">the location of vertical rebar</param> /// <param name="rebarNumber">the spacing value of the rebar</param> /// <returns>the gotted geometry information</returns> public RebarGeometry GetVerticalRebar(VerticalRebarLocation location, int rebarNumber) { // sort the points of the swept profile XYZHeightComparer comparer = new XYZHeightComparer(); m_points.Sort(comparer); // Get the offset and rebar length of rebar double offset = ColumnRebarData.VerticalOffset; double rebarLength = m_columnHeight + 3; //the length of rebar // Get the start point of the vertical rebar curve Autodesk.Revit.DB.XYZ startPoint = m_drivingLine.GetEndPoint(0); List <Autodesk.Revit.DB.XYZ> movedPoints = OffsetPoints(offset); movedPoints.Sort(comparer); Autodesk.Revit.DB.XYZ normal = new Autodesk.Revit.DB.XYZ(); // the normal parameter double rebarOffset = 0; // rebar offset, equal to rebarNumber* spacing // get the normal, start point and rebar offset of vertical rebar switch (location) { case VerticalRebarLocation.East: //vertical rebar in east normal = new Autodesk.Revit.DB.XYZ(0, 1, 0); rebarOffset = m_columnWidth - 2 * offset; startPoint = movedPoints[1]; break; case VerticalRebarLocation.North: //vertical rebar in north normal = new Autodesk.Revit.DB.XYZ(-1, 0, 0); rebarOffset = m_columnLength - 2 * offset; startPoint = movedPoints[3]; break; case VerticalRebarLocation.West: //vertical rebar in west normal = new Autodesk.Revit.DB.XYZ(0, -1, 0); rebarOffset = m_columnWidth - 2 * offset; startPoint = movedPoints[2]; break; case VerticalRebarLocation.South: //vertical rebar in south normal = new Autodesk.Revit.DB.XYZ(1, 0, 0); rebarOffset = m_columnLength - 2 * offset; startPoint = movedPoints[0]; break; default: break; } double spacing = rebarOffset / rebarNumber; //spacing value of the rebar Autodesk.Revit.DB.XYZ endPoint = GeomUtil.OffsetPoint(startPoint, m_drivingVector, rebarLength); IList <Curve> curves = new List <Curve>(); //profile of the rebar curves.Add(Line.CreateBound(startPoint, endPoint)); // return the rebar geometry information return(new RebarGeometry(normal, curves, rebarNumber, spacing)); }
/// <summary> /// constructor /// </summary> /// <param name="element">the host object, must be family instance</param> /// <param name="geoOptions">the geometry option</param> public GeometrySupport(FamilyInstance element, Options geoOptions) { // get the geometry element of the selected element Autodesk.Revit.DB.GeometryElement geoElement = element.get_Geometry(new Options()); IEnumerator <GeometryObject> Objects = geoElement.GetEnumerator(); if (null == geoElement || !Objects.MoveNext()) { throw new Exception("Can't get the geometry of selected element."); } SweptProfile swProfile = element.GetSweptProfile(); if (swProfile == null || !(swProfile.GetDrivingCurve() is Line)) { throw new Exception("The selected element driving curve is not a line."); } // get the driving path and vector of the beam or column Line line = swProfile.GetDrivingCurve() as Line; if (null != line) { m_drivingLine = line; // driving path m_drivingVector = GeomUtil.SubXYZ(line.GetEndPoint(1), line.GetEndPoint(0)); } //get the geometry object Objects.Reset(); //foreach (GeometryObject geoObject in geoElement.Objects) while (Objects.MoveNext()) { GeometryObject geoObject = Objects.Current; //get the geometry instance which contain the geometry information GeoInstance instance = geoObject as GeoInstance; if (null != instance) { //foreach (GeometryObject o in instance.SymbolGeometry.Objects) IEnumerator <GeometryObject> Objects1 = instance.SymbolGeometry.GetEnumerator(); while (Objects1.MoveNext()) { GeometryObject o = Objects1.Current; // get the solid of beam of column Solid solid = o as Solid; // do some checks. if (null == solid) { continue; } if (0 == solid.Faces.Size || 0 == solid.Edges.Size) { continue; } m_solid = solid; //get the transform value of instance m_transform = instance.Transform; // Get the swept profile curves information if (!GetSweptProfile(solid)) { throw new Exception("Can't get the swept profile curves."); } break; } } } // do some checks about profile curves information if (null == m_edges) { throw new Exception("Can't get the geometry edge information."); } if (4 != m_points.Count) { throw new Exception("The sample only work for rectangular beams or columns."); } }
/// <summary> /// Get the length of driving line /// </summary> /// <returns>the length of the driving line</returns> protected double GetDrivingLineLength() { return(GeomUtil.GetLength(m_drivingVector)); }
/// <summary> /// transform the point to new coordinates /// </summary> /// <param name="point">the point need to transform</param> /// <returns>the changed point</returns> protected Autodesk.Revit.DB.XYZ Transform(Autodesk.Revit.DB.XYZ point) { // only invoke the TransformPoint() method. return(GeomUtil.TransformPoint(point, m_transform)); }