/// <summary> /// Improved implementation by Alexander Ignatovich /// supporting curved wall with curved window, /// second attempt, published April 10, 2015: /// </summary> public Result Execute3( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Creator creator = new Creator(doc); Wall wall = e as Wall; if (wall == null) { return(Result.Cancelled); } using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile // a little bit simpler than in the last realization Reference sideFaceReference = HostObjectUtils.GetSideFaces( wall, ShellLayerType.Exterior) .First(); Face face = wall.GetGeometryObjectFromReference( sideFaceReference) as Face; // The normal of the wall external face. XYZ normal = wall.Orientation; // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation( 5 * normal); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); foreach (var curveLoop in curveLoops) { CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop) { curves.Append(curve.CreateTransformed( offset)); } var isCounterClockwize = curveLoop .IsCounterclockwise(normal); // Create model lines for an curve loop if it is made if (((LocationCurve)wall.Location).Curve is Line) { //Plane plane = creapp.NewPlane( curves ); // 2016 Plane plane = CurveLoop.CreateViaOffset( curveLoop, 5 * normal.GetLength(), normal.Normalize()).GetPlane(); // 2017 SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc .NewModelCurveArray(curves, sketchPlane); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } else { foreach (var curve in curves.Cast <Curve>()) { var curveElements = creator.CreateModelCurves(curve); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } } } tx.Commit(); } return(Result.Succeeded); }
/// <summary> /// Improved implementation by Alexander Ignatovich /// supporting curved wall with curved window, /// second attempt, published April 10, 2015: /// </summary> public Result Execute3( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Creator creator = new Creator(doc); Wall wall = e as Wall; if (wall == null) { return(Result.Cancelled); } using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile // a little bit simpler than in the last // implementation in Execute2. Reference sideFaceReference = HostObjectUtils.GetSideFaces( wall, ShellLayerType.Exterior) .First(); Face face = wall.GetGeometryObjectFromReference( sideFaceReference) as Face; // The plane and normal of the wall external face. XYZ normal = wall.Orientation.Normalize(); Transform ftx = face.ComputeDerivatives(UV.Zero); XYZ forigin = ftx.Origin; XYZ fnormal = ftx.BasisZ; Debug.Print( "wall orientation {0}, face origin {1}, face normal {2}", Util.PointString(normal), Util.PointString(forigin), Util.PointString(fnormal)); // Offset distance. double d = 5; // Offset curve copies for visibility. XYZ voffset = d * normal; Transform offset = Transform.CreateTranslation( voffset); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); foreach (var curveLoop in curveLoops) { //CurveLoop curveLoopOffset = CurveLoop.CreateViaOffset( // curveLoop, d, normal ); CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop) { curves.Append(curve.CreateTransformed( offset)); } var isCounterClockwize = curveLoop .IsCounterclockwise(normal); // Create model lines for an curve loop if it is made Curve wallCurve = ((LocationCurve)wall.Location).Curve; if (wallCurve is Line) { //Plane plane = creapp.NewPlane( curves ); // 2016 //Plane plane = curveLoopOffset.GetPlane(); // 2017 Plane plane = Plane.CreateByNormalAndOrigin( // 2019 normal, forigin + voffset); Debug.Print( "plane origin {0}, plane normal {1}", Util.PointString(plane.Origin), Util.PointString(plane.Normal)); SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc .NewModelCurveArray(curves, sketchPlane); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } else { foreach (var curve in curves.Cast <Curve>()) { var curveElements = creator.CreateModelCurves(curve); if (isCounterClockwize) { SetModelCurvesColor(curveElements, view, colorRed); } } } } tx.Commit(); } return(Result.Succeeded); }
/// <summary> /// Alternative implementation published January 23, 2015: /// http://thebuildingcoder.typepad.com/blog/2015/01/getting-the-wall-elevation-profile.html /// </summary> public Result Execute2( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Wall wall = e as Wall; using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile IList <Reference> sideFaces = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior); Element e2 = doc.GetElement(sideFaces[0]); Face face = e2.GetGeometryObjectFromReference( sideFaces[0]) as Face; // The normal of the wall external face. XYZ normal = face.ComputeNormal(new UV(0, 0)); // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation( 5 * normal); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops( curveLoops); foreach (IList <CurveLoop> curveLoops2 in curveLoopLoop) { foreach (CurveLoop curveLoop2 in curveLoops2) { // Check if curve loop is counter-clockwise. bool isCCW = curveLoop2.IsCounterclockwise( normal); CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop2) { curves.Append(curve.CreateTransformed(offset)); } // Create model lines for an curve loop. //Plane plane = creapp.NewPlane( curves ); // 2016 Plane plane = curveLoop2.GetPlane(); // 2017 SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc.NewModelCurveArray(curves, sketchPlane); if (isCCW) { foreach (ModelCurve mcurve in curveElements) { OverrideGraphicSettings overrides = view.GetElementOverrides( mcurve.Id); overrides.SetProjectionLineColor( colorRed); view.SetElementOverrides( mcurve.Id, overrides); } } } } tx.Commit(); } return(Result.Succeeded); }
/// <summary> /// Create other lines, including Ellipse, HermiteSpline and NurbSpline /// </summary> /// <param name="sketchId">the id of the sketch plane</param> /// <param name="elementId">the element id which copy the curve from</param> /// <param name="offsetPoint">the offset direction from the copied line</param> public void CreateOthers(ElementId sketchId, ElementId elementId, Autodesk.Revit.DB.XYZ offsetPoint) { // First get the sketch plane by the giving element id. SketchPlane workPlane = GetSketchPlaneById(sketchId); // Because the geometry of these lines can't be created by API, // use an existing geometry to create ModelEllipse, ModelHermiteSpline, ModelNurbSpline // and then move a bit to make the user see the creation distinctly // This method use NewModelCurveArray() method to create model lines CurveArray curves = m_createApp.NewCurveArray();// create a geometry curve array // Get the Autodesk.Revit.DB.ElementId which used to get the corresponding element ModelCurve selected = GetElementById(elementId) as ModelCurve; if (null == selected) { throw new Exception("Don't have the element you select"); } // add the geometry curve of the element curves.Append(selected.GeometryCurve); // add the geometry ellipse // Create the model line ModelCurveArray modelCurves = m_createDoc.NewModelCurveArray(curves, workPlane); if (null == modelCurves || 1 != modelCurves.Size) // assert the creation is successful { throw new Exception("Create the ModelCurveArray failed."); } // Offset the create model lines in order to differentiate the existing model lines foreach (ModelCurve m in modelCurves) { ElementTransformUtils.MoveElement(m.Document, m.Id, offsetPoint); // move the lines } // Add the created model lines into corresponding array foreach (ModelCurve m in modelCurves) { switch (m.GetType().Name) { case "ModelEllipse": // If the line is Ellipse m_ellipseArray.Append(m); // Add to Ellipse array break; case "ModelHermiteSpline": // If the line is HermiteSpline m_hermiteArray.Append(m); // Add to HermiteSpline array break; case "ModelNurbSpline": // If the line is NurbSpline m_nurbArray.Append(m); // Add to NurbSpline break; default: break; } } // Finally refresh information map. RefreshInformationMap(); }