Exemplo n.º 1
0
        // 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();
            }
        }
Exemplo n.º 2
0
        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();
            }
        }
Exemplo n.º 3
0
        // 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));
        }
Exemplo n.º 4
0
        // 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);
        }