// Main transaction public static void Execute(Application app, Document doc, List <Curve> columnLines, string nameRectColumn, string nameRoundColumn, Level level, bool IsSilent) { // Sort out column boundary // Consider using CurveArray to store the data List <List <Curve> > columnRect = new List <List <Curve> >(); List <Arc> columnRound = new List <Arc>(); List <List <Curve> > columnSpecialShaped = new List <List <Curve> >(); List <int> delIndex = new List <int>(); List <Curve> sortedLines = new List <Curve>(); foreach (Curve columnLine in columnLines) { if (columnLine.GetType().ToString() == "Autodesk.Revit.DB.Arc") { columnRound.Add(columnLine as Arc); delIndex.Add(columnLines.IndexOf(columnLine)); } else { sortedLines.Add(columnLine); } } // this is the temperal method List <List <Curve> > columnGroups = Algorithm.ClusterByIntersect(sortedLines); Debug.Print("Baselines are sorted well"); foreach (List <Curve> columnGroup in columnGroups) { if (Algorithm.GetPtsOfCrvs(columnGroup).Count == columnGroup.Count) { if (Algorithm.IsRectangle(columnGroup)) { columnRect.Add(columnGroup); } else { columnSpecialShaped.Add(columnGroup); } } } Debug.Print("Got rectangle {0}, round {1}, and unique shape {2}", columnRect.Count, columnRound.Count, columnSpecialShaped.Count); // Grab the columntype FilteredElementCollector colColumns = new FilteredElementCollector(doc) .OfClass(typeof(FamilySymbol)); // .OfCategory(BuiltInCategory.OST_Columns); // OST handles the internal family types, maybe? FamilySymbol rectangularColumn = colColumns.FirstElement() as FamilySymbol; // Use default setting to avoid error handling, which is a lack of the line below //FamilySymbol column_demo = columnTypes.Find((FamilySymbol fs) => { return fs.Name == "Column_demo"}); foreach (FamilySymbol columnType in colColumns) { if (columnType.Name == nameRectColumn) { rectangularColumn = columnType as FamilySymbol; break; } } // I don't know if there's a better way to split this... // Column generation if (IsSilent == true) { using (Transaction tx = new Transaction(doc, "Generate rectangular columns")) { FailureHandlingOptions options = tx.GetFailureHandlingOptions(); options.SetFailuresPreprocessor(new Util.FailureSwallower(false, false)); tx.SetFailureHandlingOptions(options); tx.Start(); foreach (List <Curve> baselines in columnRect) { double width = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item1; double depth = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item2; double angle = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item3; FamilySymbol fs = NewRectColumnType(doc, nameRectColumn, width, depth); if (!fs.IsActive) { fs.Activate(); } XYZ columnCenterPt = Algorithm.GetCenterPt(baselines); Line columnCenterAxis = Line.CreateBound(columnCenterPt, columnCenterPt.Add(-XYZ.BasisZ)); // z pointing down to apply a clockwise rotation FamilyInstance fi = doc.Create.NewFamilyInstance(columnCenterPt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); ElementTransformUtils.RotateElement(doc, fi.Id, columnCenterAxis, angle); //Autodesk.Revit.DB.Structure.StructuralType.Column } tx.Commit(); } // To generate the special shaped column you have to do it transaction by transaction // due to the family document reload operation must be out of one. foreach (List <Curve> baselines in columnSpecialShaped) { var boundary = Algorithm.RectifyPolygon(Misc.CrvsToLines(baselines)); FamilySymbol fs = NewSpecialShapedColumnType(app, doc, boundary); if (null == fs) { Debug.Print("Generic Model Family returns no symbol"); continue; } using (Transaction tx = new Transaction(doc, "Generate a special shaped column")) { tx.Start(); if (!fs.IsActive) { fs.Activate(); } XYZ basePt = XYZ.Zero; Line columnBaseAxis = Line.CreateBound(basePt, basePt.Add(-XYZ.BasisZ)); FamilyInstance fi = doc.Create.NewFamilyInstance(basePt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); // DANGEROUS! the coordination transformation should be added here tx.Commit(); } } } else { string caption = "Extrude columns"; string task = "Creating rectangular columns..."; Views.ProgressBar pb1 = new Views.ProgressBar(caption, task, columnRect.Count); foreach (List <Curve> baselines in columnRect) { using (Transaction tx = new Transaction(doc, "Generate a rectangular column")) { tx.Start(); double width = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item1; double depth = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item2; double angle = Algorithm.GetSizeOfRectangle(Misc.CrvsToLines(baselines)).Item3; FamilySymbol fs = NewRectColumnType(doc, nameRectColumn, width, depth); if (!fs.IsActive) { fs.Activate(); } XYZ columnCenterPt = Algorithm.GetCenterPt(baselines); Line columnCenterAxis = Line.CreateBound(columnCenterPt, columnCenterPt.Add(-XYZ.BasisZ)); // z pointing down to apply a clockwise rotation FamilyInstance fi = doc.Create.NewFamilyInstance(columnCenterPt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); ElementTransformUtils.RotateElement(doc, fi.Id, columnCenterAxis, angle); //Autodesk.Revit.DB.Structure.StructuralType.Column tx.Commit(); } pb1.Increment(); if (pb1.ProcessCancelled) { break; } } pb1.Close(); task = "Creating round columns..."; Views.ProgressBar pb2 = new Views.ProgressBar(caption, task, columnRound.Count); foreach (Arc baseline in columnRound) { using (Transaction tx = new Transaction(doc, "Generate a rounded column")) { tx.Start(); XYZ basePt = baseline.Center; double diameter = Misc.FootToMm(Math.Round(2 * baseline.Radius, 2)); FamilySymbol fs = NewRoundColumnType(doc, nameRoundColumn, diameter); if (!fs.IsActive) { fs.Activate(); } Line columnCenterAxis = Line.CreateBound(basePt, basePt.Add(-XYZ.BasisZ)); // z pointing down to apply a clockwise rotation FamilyInstance fi = doc.Create.NewFamilyInstance(basePt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); tx.Commit(); } pb2.Increment(); if (pb2.ProcessCancelled) { break; } } pb2.Close(); task = "Creating special shaped columns..."; Views.ProgressBar pb3 = new Views.ProgressBar(caption, task, columnSpecialShaped.Count); foreach (List <Curve> baselines in columnSpecialShaped) { var boundary = Algorithm.RectifyPolygon(Misc.CrvsToLines(baselines)); FamilySymbol fs = NewSpecialShapedColumnType(app, doc, boundary); if (null == fs) { Debug.Print("Generic Model Family returns no symbol"); continue; } using (Transaction tx = new Transaction(doc, "Generate a special shaped column")) { tx.Start(); if (!fs.IsActive) { fs.Activate(); } XYZ basePt = XYZ.Zero; Line columnBaseAxis = Line.CreateBound(basePt, basePt.Add(-XYZ.BasisZ)); FamilyInstance fi = doc.Create.NewFamilyInstance(basePt, fs, level, Autodesk.Revit.DB.Structure.StructuralType.NonStructural); // DANGEROUS! the coordination transformation should be added here tx.Commit(); } pb3.Increment(); if (pb3.ProcessCancelled) { break; } } pb3.JobCompleted(); } }
public static void Execute(UIApplication uiapp, List <Curve> wallCrvs, Level level, bool IsSilent) { UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; // Bundle double lines and generate their axes List <Curve> axes = new List <Curve>(); double bias = Misc.MmToFoot(20); var doubleLines = Misc.CrvsToLines(wallCrvs); for (int i = 0; i < doubleLines.Count; i++) { for (int j = 0; j < doubleLines.Count - i; j++) { if (Algorithm.IsParallel(doubleLines[i], doubleLines[i + j]) && !Algorithm.IsIntersected(doubleLines[i], doubleLines[i + j])) { // Imperical Units within Revit API if (Algorithm.LineSpacing(doubleLines[i], doubleLines[i + j]) < Misc.MmToFoot(200) + bias && Algorithm.LineSpacing(doubleLines[i], doubleLines[i + j]) > Misc.MmToFoot(200) - bias && Algorithm.IsShadowing(doubleLines[i], doubleLines[i + j])) { if (Algorithm.GenerateAxis(doubleLines[i], doubleLines[i + j]) != null) { axes.Add(Algorithm.GenerateAxis(doubleLines[i], doubleLines[i + j])); } Debug.Print(doubleLines[i].Length.ToString() + " | " + doubleLines[i + j].Length.ToString()); } } } } // Axis merge / List <Curve> mergedAxes = Algorithm.MergeAxes(axes); Debug.Print("The merged axes number " + mergedAxes.Count.ToString()); string task = "Creating Walls..."; string caption = "Extrude Walls"; int n = mergedAxes.Count; /*using (Transaction tx = new Transaction(doc, "Generate walls")) * { * tx.Start(); * * // Wall generation * foreach (Curve axis in mergedAxes) * { * Wall.Create(doc, axis, level.Id, true); * } * * tx.Commit(); * }*/ if (IsSilent == true) { using (Transaction tx = new Transaction(doc, "Generate a wall")) { FailureHandlingOptions options = tx.GetFailureHandlingOptions(); options.SetFailuresPreprocessor(new Util.FailureSwallower(false, false)); tx.SetFailureHandlingOptions(options); tx.Start(); foreach (Curve axis in mergedAxes) { Wall.Create(doc, axis, level.Id, true); } tx.Commit(); } } else { Views.ProgressBar pb = new Views.ProgressBar(caption, task, n); foreach (Curve axis in mergedAxes) { using (Transaction tx = new Transaction(doc, "Generate a wall")) { tx.Start(); Wall.Create(doc, axis, level.Id, true); tx.Commit(); } pb.Increment(); if (pb.ProcessCancelled) { break; } } pb.JobCompleted(); } }
// Main thread public static CurveArray Execute(Document doc, List <Curve> wallCrvs, List <Curve> columnCrvs, List <Curve> windowCrvs, List <Curve> doorCrvs) { View view = doc.ActiveView; List <Line> columnLines = Misc.CrvsToLines(columnCrvs); // Merge the overlapped wall boundaries // Seal the wall boundary by column block // INPUT List<Line> wallLines, List<Line> columnLines #region PATCH wallLines List <Line> patchLines = new List <Line>(); List <XYZ> sectPts = new List <XYZ>(); // Seal the wall when encountered with column foreach (Curve columnCrv in columnCrvs) { sectPts.Clear(); foreach (Line wallCrv in wallCrvs) { if (!Algorithm.IsParallel(columnCrv, wallCrv)) { SetComparisonResult result = wallCrv.Intersect(columnCrv, out IntersectionResultArray results); if (result != SetComparisonResult.Disjoint) { XYZ sectPt = results.get_Item(0).XYZPoint; sectPts.Add(sectPt); } } else { continue; } } if (sectPts.Count() == 2) { patchLines.Add(Line.CreateBound(sectPts[0], sectPts[1])); } if (sectPts.Count() > 2) // not sure how to solve this { Line minPatch = Line.CreateBound(XYZ.Zero, 10000 * XYZ.BasisX); for (int i = 0; i < sectPts.Count(); i++) { for (int j = i + 1; j < sectPts.Count(); j++) { if (sectPts[i].DistanceTo(sectPts[j]) > 0.001) { Line testPatch = Line.CreateBound(sectPts[i], sectPts[j]); if (testPatch.Length < minPatch.Length) { minPatch = testPatch; } } } } patchLines.Add(minPatch); } } // Patch for the wall lines wallCrvs.AddRange(patchLines); // Merge lines when they are parallel and almost intersected (knob) List <Curve> mergeLines = CmdPatchBoundary.CloseGapAtBreakpoint(wallCrvs); // List <Curve> fixedLines = CmdPatchBoundary.CloseGapAtCorner(mergeLines); #endregion // OUTPUT List<Line> fixedLines // INPUT List<Line> fixedLines #region Cluster the wallLines by hierarchy var wallClusters = Algorithm.ClusterByIntersect(fixedLines); Debug.Print("{0} clustered wall blocks in total", wallClusters.Count); // Generate boundingbox marker for the wall cluster List <List <Curve> > wallBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in wallClusters) { List <Curve> clusterCrv = cluster; if (null != Algorithm.CreateBoundingBox2D(clusterCrv)) { wallBlocks.Add(Algorithm.CreateBoundingBox2D(clusterCrv)); } } Debug.Print("{0} clustered wall bounding boxes in total", wallBlocks.Count); #endregion // INPUT List<List< Curve >> wallClusters Debug.Print("WALL LINES PATCH & CLUSTERING COMPLETE!"); // INPUT List<List<Curve>> wallClusters #region Iterate the generaion of axis // Wall axes List <Curve> axes = new List <Curve>(); double bias = Misc.MmToFoot(20); foreach (List <Curve> wallCluster in wallClusters) { List <Line> lines = Misc.CrvsToLines(wallCluster); for (int i = 0; i < lines.Count; i++) { for (int j = 0; j < lines.Count - i; j++) { if (Algorithm.IsParallel(lines[i], lines[i + j]) && !Algorithm.IsIntersected(lines[i], lines[i + j])) { if (Algorithm.LineSpacing(lines[i], lines[i + j]) < Misc.MmToFoot(200) + bias && Algorithm.LineSpacing(lines[i], lines[i + j]) > Misc.MmToFoot(200) - bias && Algorithm.IsShadowing(lines[i], lines[i + j])) { if (Algorithm.GenerateAxis(lines[i], lines[i + j]) != null) { axes.Add(Algorithm.GenerateAxis(lines[i], lines[i + j])); Debug.Print("got it!"); } } } } } } #endregion // OUTPUT List<Line> axes Debug.Print("WALL AXIS ITERATION COMPLETE!"); // INPUT List<Curve> doorCrvs // INPUT List<Curve> windowCrvs // INPUT List<Line> axes #region Merge axis joined/overlapped // Door axes var doorClusters = Algorithm.ClusterByIntersect(doorCrvs); List <List <Curve> > doorBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in doorClusters) { if (null != Algorithm.CreateBoundingBox2D(cluster)) { doorBlocks.Add(Algorithm.CreateBoundingBox2D(cluster)); } } List <Curve> doorAxes = new List <Curve> { }; foreach (List <Curve> doorBlock in doorBlocks) { List <Curve> doorFrame = new List <Curve> { }; for (int i = 0; i < doorBlock.Count; i++) { int sectCount = 0; List <Line> fenses = new List <Line>(); foreach (Line line in fixedLines) { Curve testCrv = doorBlock[i].Clone(); SetComparisonResult result = RegionDetect.ExtendCrv(testCrv, 0.01).Intersect(line, out IntersectionResultArray results); if (result == SetComparisonResult.Overlap) { sectCount += 1; fenses.Add(line); } } if (sectCount == 2) { XYZ projecting = fenses[0].Evaluate(0.5, true); XYZ projected = fenses[1].Project(projecting).XYZPoint; if (fenses[0].Length > fenses[1].Length) { projecting = fenses[1].Evaluate(0.5, true); projected = fenses[0].Project(projecting).XYZPoint; } Line doorAxis = Line.CreateBound(projecting, projected); doorAxes.Add(doorAxis); //doorAxes.Add(doorBlock[i]); } } } // Window axes var windowClusters = Algorithm.ClusterByIntersect(windowCrvs); List <List <Curve> > windowBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in windowClusters) { if (null != Algorithm.CreateBoundingBox2D(cluster)) { windowBlocks.Add(Algorithm.CreateBoundingBox2D(cluster)); } } List <Curve> windowAxes = new List <Curve> { }; foreach (List <Curve> windowBlock in windowBlocks) { Line axis1 = Line.CreateBound((windowBlock[0].GetEndPoint(0) + windowBlock[0].GetEndPoint(1)).Divide(2), (windowBlock[2].GetEndPoint(0) + windowBlock[2].GetEndPoint(1)).Divide(2)); Line axis2 = Line.CreateBound((windowBlock[1].GetEndPoint(0) + windowBlock[1].GetEndPoint(1)).Divide(2), (windowBlock[3].GetEndPoint(0) + windowBlock[3].GetEndPoint(1)).Divide(2)); if (axis1.Length > axis2.Length) { windowAxes.Add(axis1); } else { windowAxes.Add(axis2); } } axes.AddRange(windowAxes); axes.AddRange(doorAxes); Debug.Print("Checklist for axes: Door-{0}, Window-{1}, All-{2}", doorAxes.Count, windowAxes.Count, axes.Count); List <Curve> axesExtended = new List <Curve>(); foreach (Curve axis in axes) { axesExtended.Add(Algorithm.ExtendLine(axis, 200)); } // Axis merge List <List <Curve> > axisGroups = Algorithm.ClusterByOverlap(axesExtended); List <Curve> centerLines = new List <Curve>(); foreach (List <Curve> axisGroup in axisGroups) { var merged = Algorithm.FuseLines(axisGroup); centerLines.Add(merged); } #endregion // OUTPUT List<Line> centerLines Debug.Print("WINDOW / DOOR LINES JOINED!"); // INPUT List<Curve> columnCrvs // INPUT List<Line> centerLines #region Extend and trim the axis (include column corner) List <List <Curve> > columnGroups = Algorithm.ClusterByIntersect(columnCrvs); foreach (List <Curve> columnGroup in columnGroups) { List <Curve> nestLines = new List <Curve>(); for (int i = 0; i < columnGroup.Count; i++) { foreach (Line centerLine in centerLines) { SetComparisonResult result = columnGroup[i].Intersect(centerLine, out IntersectionResultArray results); if (result == SetComparisonResult.Overlap) { for (int j = 0; j < columnGroup.Count; j++) { if (j != i) { if (null != CmdPatchBoundary.ExtendLine(centerLine, columnGroup[j])) { nestLines.Add(CmdPatchBoundary.ExtendLine(centerLine, columnGroup[j])); } } } } } } Debug.Print("Got nested lines: " + nestLines.Count.ToString()); if (nestLines.Count < 2) { continue; } else { centerLines.AddRange(nestLines); int count = 0; for (int i = 1; i < nestLines.Count; i++) { if (!Algorithm.IsParallel(nestLines[0], nestLines[i])) { count += 1; } } if (count == 0) { var patches = Algorithm.CenterLinesOfBox(columnGroup); foreach (Line patch in patches) { if (Algorithm.IsLineIntersectLines(patch, nestLines)) { centerLines.Add(patch); } } } } } #endregion // OUTPUT List<Line> centerLines Debug.Print("AXES JOINED AT COLUMN"); // INPUT List<Line> centerLines //#The region detect function has fatal bug during boolean union operation #region Call region detection // Axis merge List <List <Curve> > tempStrays = Algorithm.ClusterByOverlap(centerLines); List <Curve> strays = new List <Curve>(); foreach (List <Curve> tempStray in tempStrays) { var merged = Algorithm.FuseLines(tempStray); strays.Add(merged); } // The RegionCluster method should be applied to each cluster of the strays // It only works on a bunch of intersected line segments List <CurveArray> loops = RegionDetect.RegionCluster(strays); // The boolean union method of the loops needs to fix var perimeter = RegionDetect.GetBoundary(loops); var recPerimeter = CmdPatchBoundary.CloseGapAtBreakpoint(perimeter); #endregion // OUTPUT List<CurveArray> loops Debug.Print("REGION COMPLETE!"); return(RegionDetect.AlignCrv(recPerimeter)); }
// Main thread public Result Execute(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; Selection sel = uidoc.Selection; double tolerance = app.ShortCurveTolerance; // Pick Import Instance ImportInstance import = null; try { Reference r = uidoc.Selection.PickObject(ObjectType.Element, new Util.ElementsOfClassSelectionFilter <ImportInstance>()); import = doc.GetElement(r) as ImportInstance; } catch { return(Result.Cancelled); } if (import == null) { System.Windows.MessageBox.Show("CAD not found", "Tips"); return(Result.Cancelled); } List <Curve> columnCrvs = Util.TeighaGeometry.ShatterCADGeometry(uidoc, import, "COLUMN", tolerance); List <Curve> wallCrvs = Util.TeighaGeometry.ShatterCADGeometry(uidoc, import, "WALL", tolerance); List <Curve> doorCrvs = Util.TeighaGeometry.ShatterCADGeometry(uidoc, import, "DOOR", tolerance); List <Curve> windowCrvs = Util.TeighaGeometry.ShatterCADGeometry(uidoc, import, "WINDOW", tolerance); //List<Line> columnLines = Util.CrvsToLines(columnCrvs); //List<Line> wallLines = Util.CrvsToLines(wallCrvs); // Merge the overlapped wall boundaries // Seal the wall boundary by column block // INPUT List<Line> wallLines, List<Line> columnLines #region PATCH wallLines List <Line> patchLines = new List <Line>(); List <XYZ> sectPts = new List <XYZ>(); // Seal the wall when encountered with column foreach (Curve columnCrv in columnCrvs) { sectPts.Clear(); foreach (Line wallCrv in wallCrvs) { if (!Algorithm.IsParallel(columnCrv, wallCrv)) { SetComparisonResult result = wallCrv.Intersect(columnCrv, out IntersectionResultArray results); if (result != SetComparisonResult.Disjoint) { XYZ sectPt = results.get_Item(0).XYZPoint; sectPts.Add(sectPt); } } else { continue; } } if (sectPts.Count() == 2) { patchLines.Add(Line.CreateBound(sectPts[0], sectPts[1])); } if (sectPts.Count() > 2) // not sure how to solve this { Line minPatch = Line.CreateBound(XYZ.Zero, 10000 * XYZ.BasisX); for (int i = 0; i < sectPts.Count(); i++) { for (int j = i + 1; j < sectPts.Count(); j++) { if (sectPts[i].DistanceTo(sectPts[j]) > 0.001) { Line testPatch = Line.CreateBound(sectPts[i], sectPts[j]); if (testPatch.Length < minPatch.Length) { minPatch = testPatch; } } } } patchLines.Add(minPatch); } } // Patch for the wall lines wallCrvs.AddRange(patchLines); // Merge lines when they are parallel and almost intersected (knob) List <Curve> mergeLines = CloseGapAtBreakpoint(wallCrvs); // List <Curve> fixedLines = CloseGapAtCorner(mergeLines); #endregion // OUTPUT List<Line> fixedLines // INPUT List<Line> fixedLines #region Cluster the wallLines by hierarchy var wallClusters = Algorithm.ClusterByIntersect(fixedLines); Debug.Print("{0} clustered wall blocks in total", wallClusters.Count); // Generate boundingbox marker for the wall cluster List <List <Curve> > wallBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in wallClusters) { List <Curve> clusterCrv = cluster; if (null != Algorithm.CreateBoundingBox2D(clusterCrv)) { wallBlocks.Add(Algorithm.CreateBoundingBox2D(clusterCrv)); } } Debug.Print("{0} clustered wall bounding boxes in total", wallBlocks.Count); #endregion // INPUT List<List< Curve >> wallClusters Debug.Print("WALL LINES PATCH & CLUSTERING COMPLETE!"); // INPUT List<List<Curve>> wallClusters #region Iterate the generaion of axis // Wall axes List <Curve> axes = new List <Curve>(); double bias = Misc.MmToFoot(20); foreach (List <Curve> wallCluster in wallClusters) { List <Line> lines = Misc.CrvsToLines(wallCluster); for (int i = 0; i < lines.Count; i++) { for (int j = 0; j < lines.Count - i; j++) { if (Algorithm.IsParallel(lines[i], lines[i + j]) && !Algorithm.IsIntersected(lines[i], lines[i + j])) { if (Algorithm.LineSpacing(lines[i], lines[i + j]) < Misc.MmToFoot(200) + bias && Algorithm.LineSpacing(lines[i], lines[i + j]) > Misc.MmToFoot(200) - bias && Algorithm.IsShadowing(lines[i], lines[i + j])) { if (Algorithm.GenerateAxis(lines[i], lines[i + j]) != null) { axes.Add(Algorithm.GenerateAxis(lines[i], lines[i + j])); Debug.Print("got it!"); } } } } } } #endregion // OUTPUT List<Line> axes Debug.Print("WALL AXIS ITERATION COMPLETE!"); // INPUT List<Curve> doorCrvs // INPUT List<Curve> windowCrvs // INPUT List<Line> axes #region Merge axis joined/overlapped // Door axes var doorClusters = Algorithm.ClusterByIntersect(doorCrvs); List <List <Curve> > doorBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in doorClusters) { if (null != Algorithm.CreateBoundingBox2D(cluster)) { doorBlocks.Add(Algorithm.CreateBoundingBox2D(cluster)); } } List <Curve> doorAxes = new List <Curve> { }; foreach (List <Curve> doorBlock in doorBlocks) { List <Curve> doorFrame = new List <Curve> { }; for (int i = 0; i < doorBlock.Count; i++) { int sectCount = 0; List <Line> fenses = new List <Line>(); foreach (Line line in fixedLines) { Curve testCrv = doorBlock[i].Clone(); SetComparisonResult result = RegionDetect.ExtendCrv(testCrv, 0.01).Intersect(line, out IntersectionResultArray results); if (result == SetComparisonResult.Overlap) { sectCount += 1; fenses.Add(line); } } if (sectCount == 2) { XYZ projecting = fenses[0].Evaluate(0.5, true); XYZ projected = fenses[1].Project(projecting).XYZPoint; if (fenses[0].Length > fenses[1].Length) { projecting = fenses[1].Evaluate(0.5, true); projected = fenses[0].Project(projecting).XYZPoint; } Line doorAxis = Line.CreateBound(projecting, projected); doorAxes.Add(doorAxis); //doorAxes.Add(doorBlock[i]); } } } // Window axes var windowClusters = Algorithm.ClusterByIntersect(windowCrvs); List <List <Curve> > windowBlocks = new List <List <Curve> > { }; foreach (List <Curve> cluster in windowClusters) { if (null != Algorithm.CreateBoundingBox2D(cluster)) { windowBlocks.Add(Algorithm.CreateBoundingBox2D(cluster)); } } List <Curve> windowAxes = new List <Curve> { }; foreach (List <Curve> windowBlock in windowBlocks) { Line axis1 = Line.CreateBound((windowBlock[0].GetEndPoint(0) + windowBlock[0].GetEndPoint(1)).Divide(2), (windowBlock[2].GetEndPoint(0) + windowBlock[2].GetEndPoint(1)).Divide(2)); Line axis2 = Line.CreateBound((windowBlock[1].GetEndPoint(0) + windowBlock[1].GetEndPoint(1)).Divide(2), (windowBlock[3].GetEndPoint(0) + windowBlock[3].GetEndPoint(1)).Divide(2)); if (axis1.Length > axis2.Length) { windowAxes.Add(axis1); } else { windowAxes.Add(axis2); } } axes.AddRange(windowAxes); axes.AddRange(doorAxes); Debug.Print("Checklist for axes: Door-{0}, Window-{1}, All-{2}", doorAxes.Count, windowAxes.Count, axes.Count); List <Curve> axesExtended = new List <Curve>(); foreach (Curve axis in axes) { axesExtended.Add(Algorithm.ExtendLine(axis, 200)); } // Axis merge List <List <Curve> > axisGroups = Algorithm.ClusterByOverlap(axesExtended); List <Curve> centerLines = new List <Curve>(); foreach (List <Curve> axisGroup in axisGroups) { var merged = Algorithm.FuseLines(axisGroup); centerLines.Add(merged); } #endregion // OUTPUT List<Line> centerLines Debug.Print("WINDOW / DOOR LINES JOINED!"); // INPUT List<Curve> columnCrvs // INPUT List<Line> centerLines #region Extend and trim the axis (include column corner) List <List <Curve> > columnGroups = Algorithm.ClusterByIntersect(columnCrvs); foreach (List <Curve> columnGroup in columnGroups) { //List<Line> columnGrouplines = Util.CrvsToLines(columnGroup); List <Curve> nestLines = new List <Curve>(); for (int i = 0; i < columnGroup.Count; i++) { foreach (Line centerLine in centerLines) { SetComparisonResult result = columnGroup[i].Intersect(centerLine, out IntersectionResultArray results); if (result == SetComparisonResult.Overlap) { for (int j = 0; j < columnGroup.Count; j++) { if (j != i) { if (null != ExtendLine(centerLine, columnGroup[j])) { nestLines.Add(ExtendLine(centerLine, columnGroup[j])); } } } } } } Debug.Print("Got nested lines: " + nestLines.Count.ToString()); if (nestLines.Count < 2) { continue; } else { centerLines.AddRange(nestLines); int count = 0; for (int i = 1; i < nestLines.Count; i++) { if (!Algorithm.IsParallel(nestLines[0], nestLines[i])) { count += 1; } } if (count == 0) { var patches = Algorithm.CenterLinesOfBox(columnGroup); foreach (Line patch in patches) { if (Algorithm.IsLineIntersectLines(patch, nestLines)) { centerLines.Add(patch); } } } } } #endregion // OUTPUT List<Line> centerLines Debug.Print("AXES JOINED AT COLUMN"); // INPUT List<Line> centerLines //#The region detect function has fatal bug during boolean union operation #region Call region detection // Axis merge List <List <Curve> > tempStrays = Algorithm.ClusterByOverlap(centerLines); List <Curve> strays = new List <Curve>(); foreach (List <Curve> tempStray in tempStrays) { Curve merged = Algorithm.FuseLines(tempStray); strays.Add(merged); } //var strayClusters = Algorithm.ClusterByIntersect(Util.LinesToCrvs(strays)); //Debug.Print("Cluster of strays: " + strayClusters.Count.ToString()); //Debug.Print("Cluster of strays[0]: " + strayClusters[0].Count.ToString()); //Debug.Print("Cluster of strays[1]: " + strayClusters[1].Count.ToString()); // The RegionCluster method should be applied to each cluster of the strays // It only works on a bunch of intersected line segments List <CurveArray> loops = RegionDetect.RegionCluster(strays); // The boolean union method of the loops needs to fix var perimeter = RegionDetect.GetBoundary(loops); var recPerimeter = CloseGapAtBreakpoint(perimeter); var arrayPerimeter = RegionDetect.AlignCrv(recPerimeter); for (int i = 0; i < arrayPerimeter.Size; i++) { Debug.Print("Line-{0} {1} {2}", i, Misc.PointString(arrayPerimeter.get_Item(i).GetEndPoint(0)), Misc.PointString(arrayPerimeter.get_Item(i).GetEndPoint(1))); } #endregion // OUTPUT List<CurveArray> loops Debug.Print("REGION COMPLETE!"); // Get the linestyle of "long-dashed" FilteredElementCollector fec = new FilteredElementCollector(doc) .OfClass(typeof(LinePatternElement)); LinePatternElement linePatternElem = fec.FirstElement() as LinePatternElement; // Main visualization process using (Transaction tx = new Transaction(doc)) { tx.Start("Generate Floor"); // Draw wall patch lines /* * foreach (Curve patchLine in patchLines) * { * DetailLine axis = doc.Create.NewDetailCurve(view, patchLine) as DetailLine; * GraphicsStyle gs = axis.LineStyle as GraphicsStyle; * gs.GraphicsStyleCategory.LineColor = new Color(202, 51, 82); * gs.GraphicsStyleCategory.SetLineWeight(3, gs.GraphicsStyleType); * } */ Plane Geomplane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero); SketchPlane sketch = SketchPlane.Create(doc, Geomplane); /* * // Draw bounding boxes * foreach (List<Curve> wallBlock in wallBlocks) * { * foreach (Curve edge in wallBlock) * { * DetailLine axis = doc.Create.NewDetailCurve(view, edge) as DetailLine; * GraphicsStyle gs = axis.LineStyle as GraphicsStyle; * gs.GraphicsStyleCategory.LineColor = new Color(210, 208, 185); * gs.GraphicsStyleCategory.SetLineWeight(1, gs.GraphicsStyleType); * gs.GraphicsStyleCategory.SetLinePatternId(linePatternElem.Id, gs.GraphicsStyleType); * } * } */ /* * // Draw Axes * Debug.Print("Axes all together: " + strays.Count.ToString()); * foreach (Line centerLine in strays) * { * ModelCurve modelline = doc.Create.NewModelCurve(centerLine, sketch) as ModelCurve; * } */ // Draw Regions foreach (CurveArray loop in loops) { foreach (Curve edge in loop) { ModelCurve modelline = doc.Create.NewModelCurve(edge, sketch) as ModelCurve; } } foreach (Curve edge in arrayPerimeter) { DetailLine axis = doc.Create.NewDetailCurve(view, edge) as DetailLine; GraphicsStyle gs = axis.LineStyle as GraphicsStyle; gs.GraphicsStyleCategory.LineColor = new Color(202, 51, 82); gs.GraphicsStyleCategory.SetLineWeight(8, gs.GraphicsStyleType); } tx.Commit(); } return(Result.Succeeded); }