Example #1
0
        public MaterialsAMLPaletteRequest(UIApplication uiApp, String text)
        {
            RVTDocument         doc = uiApp.ActiveUIDocument.Document;
            MaterialsAMLPalette materialsPalette = BARevitTools.Application.thisApp.newMainUi.materialsAMLPalette;

            //Get the versioned symbol family
            FamilySymbol familySymbol    = null;
            string       versionedFamily = RVTOperations.GetVersionedFamilyFilePath(uiApp, Properties.Settings.Default.RevitIDAccentMatTag);

            //Try loading the family symbol
            Transaction loadSymbolTransaction = new Transaction(doc, "LoadFamilySymbol");

            loadSymbolTransaction.Start();
            try
            {
                try
                {
                    IFamilyLoadOptions loadOptions = new RVTFamilyLoadOptions();
                    doc.LoadFamilySymbol(versionedFamily, "Legend Tag (Fake)", loadOptions, out FamilySymbol symb);
                    familySymbol = symb;
                }
                catch
                {
                    MessageBox.Show(String.Format("Could not get the 'Legend Tag (Fake)' type from {0}", versionedFamily), "Family Symbol Load Error");
                }
                loadSymbolTransaction.Commit();
            }
            catch (Exception transactionException)
            { loadSymbolTransaction.RollBack(); MessageBox.Show(transactionException.ToString()); }

            //Get the line style to use, or create the default
            Element lineStyle = null;

            if (materialsPalette.paletteMaterialComboBox.Text == "Default")
            {
                try
                {
                    lineStyle = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories.get_Item("6 BA ID ACCENT").GetGraphicsStyle(GraphicsStyleType.Projection);
                }
                catch
                {
                    try
                    {
                        Category linesCategory        = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines);
                        Category newLineStyleCategory = doc.Settings.Categories.NewSubcategory(linesCategory, "6 BA ID ACCENT");
                        newLineStyleCategory.LineColor = new Color(0, 0, 0);
                        newLineStyleCategory.SetLineWeight(6, GraphicsStyleType.Projection);
                        newLineStyleCategory.SetLinePatternId(LinePatternElement.GetSolidPatternId(), GraphicsStyleType.Projection);
                        doc.Regenerate();
                        lineStyle = newLineStyleCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.ToString());
                    }
                }
            }
            else
            {
                lineStyle = doc.Settings.Categories.get_Item(BuiltInCategory.OST_Lines).SubCategories.get_Item("ID " + materialsPalette.paletteMaterialComboBox.Text).GetGraphicsStyle(GraphicsStyleType.Projection);
            }

            //Assure the view being used is a floor plan
            if (doc.ActiveView.ViewType != ViewType.FloorPlan)
            {
                MessageBox.Show("This tool should be used ina a Floor Plan or Area Plan view");
            }
            else
            {
                //Create a loop for picking points. Change the palette background color based on the number of points picked
                List <XYZ> pickedPoints = new List <XYZ>();
                bool       breakLoop    = false;
                int        pickCount    = 0;
                while (breakLoop == false)
                {
                    try
                    {
                        //Have the user begin picking points. The number of clicks to start the UI color change is 1 because the first click is usually to activate the window.
                        XYZ point = uiApp.ActiveUIDocument.Selection.PickPoint(Autodesk.Revit.UI.Selection.ObjectSnapTypes.Endpoints, "Click points for the line to follow. Then click once to the side where the lines should be drawn. Hit ESC to finish");
                        pickedPoints.Add(point);

                        if (pickCount == 1)
                        {
                            materialsPalette.BackColor = System.Drawing.Color.Firebrick;
                        }
                        else if (pickCount == 2)
                        {
                            materialsPalette.BackColor = System.Drawing.Color.Orange;
                        }
                        else if (pickCount > 2)
                        {
                            //After three clicks in the window, the user has made the minimum point selection to generate the lines from the start, end, and positive side points.
                            materialsPalette.BackColor = System.Drawing.Color.GreenYellow;
                        }
                        else
                        {
                            ;
                        }

                        pickCount++;
                    }
                    catch
                    {
                        materialsPalette.BackColor = MaterialsAMLPalette.DefaultBackColor;
                        breakLoop = true;
                    }
                }

                //Get rid of the first point from clicking into the Revit view. This point is not needed.
                pickedPoints.RemoveAt(0);

                if (pickedPoints.Count > 2)
                {
                    Transaction createLinesTransaction = new Transaction(doc, "CreateAccentLines");
                    createLinesTransaction.Start();

                    try
                    {
                        //These points will be used in determining the start, end, and room points
                        XYZ firstPoint = pickedPoints[0];
                        XYZ roomPoint  = pickedPoints[pickedPoints.Count - 1];
                        XYZ lastPoint  = pickedPoints[pickedPoints.Count - 2];

                        //Create  a list of points for the polyline that excludes the room point
                        List <XYZ> polyLinePoints = new List <XYZ>();
                        for (int i = 0; i < pickedPoints.Count - 1; i++)
                        {
                            polyLinePoints.Add(pickedPoints[i]);
                        }

                        //Create a polyline from the list of picked points and then get make lines from the points on the poly line
                        PolyLine    guidePolyLine = PolyLine.Create(polyLinePoints);
                        IList <XYZ> polyPoints    = guidePolyLine.GetCoordinates();

                        List <Line> guideLines = new List <Line>();
                        for (int i = 0; i < polyLinePoints.Count - 1; i++)
                        {
                            guideLines.Add(Line.CreateBound(polyLinePoints[i], polyLinePoints[i + 1]));
                        }

                        //Get the direction of the line offset by measuring the first offset for positive and negative values and comparing their distances with the room point
                        bool positiveZ = false;

                        List <Line> offsetLines            = new List <Line>();
                        Line        positiveOffsetLine     = guideLines.Last().CreateOffset(0.6666666667d, XYZ.BasisZ) as Line;
                        Line        negativeOffsetLine     = guideLines.Last().CreateOffset(-0.6666666667d, XYZ.BasisZ) as Line;
                        XYZ         positiveOffsetMidPoint = positiveOffsetLine.Evaluate(0.5d, true);
                        XYZ         negativeOffsetMidPoint = negativeOffsetLine.Evaluate(0.5d, true);

                        Double positiveOffsetDistance = positiveOffsetMidPoint.DistanceTo(roomPoint);
                        Double negativeOffsetDistance = negativeOffsetMidPoint.DistanceTo(roomPoint);

                        //If the positive offset side resulted in a shorter distance to the point inside the room, then the offset should have a positive Z normal.
                        if (positiveOffsetDistance < negativeOffsetDistance)
                        {
                            positiveZ = true;
                        }

                        //Knowing whether or not to use a positive or negative offset, begin creating offset lines for each guide line
                        foreach (Line guideLine in guideLines)
                        {
                            if (positiveZ)
                            {
                                offsetLines.Add(guideLine.CreateOffset(0.6666666667d, XYZ.BasisZ) as Line);
                            }
                            else
                            {
                                offsetLines.Add(guideLine.CreateOffset(-0.6666666667d, XYZ.BasisZ) as Line);
                            }
                        }

                        //Determine if the number of line segments is 1 or more
                        Line firstLine = offsetLines.First();
                        Line lastLine  = null;
                        if (offsetLines.Count > 1)
                        {
                            lastLine = offsetLines.Last();
                        }

                        //If there is only one line segment, both end operations must be performed on it
                        if (lastLine == null)
                        {
                            double lineLength       = firstLine.Length;
                            double fractionOfLength = 0.6666666667d / lineLength;

                            //Checking fractions to ensure they are not greater than 1 for the normalization
                            if (fractionOfLength > 1)
                            {
                                fractionOfLength = 0.25d;
                            }

                            //Re-evaluating where to place the start and end point of the line
                            XYZ shiftedStartPoint = firstLine.Evaluate(fractionOfLength, true);
                            XYZ shiftedEndPoint   = firstLine.Evaluate(1 - fractionOfLength, true);
                            firstLine = Line.CreateBound(shiftedStartPoint, shiftedEndPoint);

                            //Creating the angled corner lines
                            Line firstCornerLine = Line.CreateBound(firstPoint, firstLine.GetEndPoint(0));
                            Line lastCornerLine  = Line.CreateBound(lastPoint, firstLine.GetEndPoint(1));

                            //Create the detail lines from the lines
                            DetailCurve newAccentLine1 = doc.Create.NewDetailCurve(doc.ActiveView, firstCornerLine);
                            DetailCurve newAccentLine2 = doc.Create.NewDetailCurve(doc.ActiveView, firstLine);
                            DetailCurve newAccentLine3 = doc.Create.NewDetailCurve(doc.ActiveView, lastCornerLine);

                            //Assign a line style to the newly created detail lines
                            newAccentLine1.LineStyle = lineStyle;
                            newAccentLine2.LineStyle = lineStyle;
                            newAccentLine3.LineStyle = lineStyle;


                            XYZ    tagPlacementPoint = firstLine.Evaluate(0.5d, true);
                            XYZ    direction         = firstLine.Direction;
                            Line   axisLine          = Line.CreateUnbound(tagPlacementPoint, XYZ.BasisZ);
                            double rotationAngle     = direction.AngleTo(XYZ.BasisX);

                            //Get the midpoint of the line, its direction, and create the rotation and axis
                            if (familySymbol != null)
                            {
                                //Create the tag instance
                                FamilyInstance newTag = doc.Create.NewFamilyInstance(tagPlacementPoint, familySymbol, doc.ActiveView);
                                //Rotate the new tag instance
                                ElementTransformUtils.RotateElement(doc, newTag.Id, axisLine, rotationAngle);
                            }

                            createLinesTransaction.Commit();
                        }
                        //If there is more than one line segment, an operation must be performed on the start and end of the start and end lines, respectively
                        else
                        {
                            List <Line> linesToDraw = new List <Line>();
                            // Get the normalized value for 8" relative to the lengths of the start and end lines
                            double firstLineLength     = firstLine.Length;
                            double fractionOfFirstLine = 0.6666666667 / firstLineLength;
                            double lastLineLength      = lastLine.Length;
                            double fractionOfLastLine  = 0.666666667 / lastLineLength;

                            //Checking fractions to ensure they are not greater than 1 for the normalization
                            if (fractionOfFirstLine > 1)
                            {
                                fractionOfFirstLine = 0.25d;
                            }
                            if (fractionOfLastLine > 1)
                            {
                                fractionOfLastLine = 0.25d;
                            }

                            //Shift the ends of the start and end lines by finding the point along the line relative to the normalized 8" value
                            XYZ shiftedStartPoint = firstLine.Evaluate(fractionOfFirstLine, true);
                            XYZ shiftedEndPoint   = lastLine.Evaluate(1 - fractionOfLastLine, true);

                            //Reset the start and end lines with the new shifted points
                            firstLine = Line.CreateBound(shiftedStartPoint, firstLine.GetEndPoint(1));
                            lastLine  = Line.CreateBound(lastLine.GetEndPoint(0), shiftedEndPoint);
                            linesToDraw.Add(firstLine);

                            //If there are only 3 offset lines, there will be just one middle segment
                            if (offsetLines.Count == 3)
                            {
                                linesToDraw.Add(offsetLines[1]);
                            }
                            //If there are more than three offset lines, there will be more than one middle line segment
                            else
                            {
                                List <Line> middleLines = offsetLines.GetRange(1, offsetLines.Count - 2);
                                foreach (Line middleLine in middleLines)
                                {
                                    linesToDraw.Add(middleLine);
                                }
                            }
                            linesToDraw.Add(lastLine);

                            //For the lines to draw, intersect them with the next line in the list and reset their start and end points to be the intersection
                            for (int i = 0; i < linesToDraw.Count - 1; i++)
                            {
                                Line line1       = linesToDraw[i];
                                Line scaledLine1 = Line.CreateUnbound(line1.GetEndPoint(1), line1.Direction);
                                Line line2       = linesToDraw[i + 1];
                                Line scaledLine2 = Line.CreateUnbound(line2.GetEndPoint(0), line2.Direction.Negate());
                                SetComparisonResult intersectionResult = scaledLine1.Intersect(scaledLine2, out IntersectionResultArray results);
                                if (intersectionResult == SetComparisonResult.Overlap)
                                {
                                    IntersectionResult result = results.get_Item(0);
                                    Line newLine1             = Line.CreateBound(line1.GetEndPoint(0), result.XYZPoint);
                                    Line newLine2             = Line.CreateBound(result.XYZPoint, line2.GetEndPoint(1));

                                    linesToDraw[i]     = newLine1;
                                    linesToDraw[i + 1] = newLine2;
                                }
                            }

                            //Create the angled corner lines at the start and end of the line chain
                            Line firstCornerLine = Line.CreateBound(firstPoint, firstLine.GetEndPoint(0));
                            Line lastCornerLine  = Line.CreateBound(lastPoint, lastLine.GetEndPoint(1));
                            linesToDraw.Add(firstCornerLine);
                            linesToDraw.Add(lastCornerLine);

                            //Create each line as a detail line
                            foreach (Line apiLine in linesToDraw)
                            {
                                DetailCurve newAccentLine = doc.Create.NewDetailCurve(doc.ActiveView, apiLine);
                                newAccentLine.LineStyle = lineStyle;
                            }

                            //Declare some stuff for use in the symbol placement
                            Line   firstMiddleLine = linesToDraw[0];
                            Line   lastMiddleLine  = linesToDraw[linesToDraw.Count - 3];
                            XYZ    firstTagPoint   = firstMiddleLine.Evaluate(0.5d, true);
                            XYZ    lastTagPoint    = lastMiddleLine.Evaluate(0.5d, true);
                            XYZ    firstDirection  = firstMiddleLine.Direction;
                            XYZ    lastDirection   = lastMiddleLine.Direction;
                            Line   firstAxisLine   = Line.CreateUnbound(firstTagPoint, XYZ.BasisZ);
                            Line   lastAxisLine    = Line.CreateUnbound(lastTagPoint, XYZ.BasisZ);
                            double firstRotation   = firstDirection.AngleTo(XYZ.BasisX);
                            double lastRotation    = lastDirection.AngleTo(XYZ.BasisX);

                            if (familySymbol != null)
                            {
                                //Create tag at the beginning of the middle lines
                                FamilyInstance firstTag = doc.Create.NewFamilyInstance(firstTagPoint, familySymbol, doc.ActiveView);
                                ElementTransformUtils.RotateElement(doc, firstTag.Id, firstAxisLine, firstRotation);

                                //Create a tag at the end of the middle lines if there are more than 2 middle lines
                                if (linesToDraw.Count > 4)
                                {
                                    FamilyInstance lastTag = doc.Create.NewFamilyInstance(lastTagPoint, familySymbol, doc.ActiveView);
                                    ElementTransformUtils.RotateElement(doc, lastTag.Id, lastAxisLine, lastRotation);
                                }
                            }

                            createLinesTransaction.Commit();
                        }
                    }
                    catch (Exception e)
                    {
                        //Suppose the user closed the palette too soon. This will remind them to keep it open.
                        if (BARevitTools.Application.thisApp.newMainUi.materialsAMLPalette == null)
                        {
                            MessageBox.Show("AML Picker was closed prematurely. Please keep the picker open until the lines are drawn.");
                        }
                        else
                        {
                            //Otherwise, if some other error occurred, show the exception
                            MessageBox.Show(e.ToString());
                        }
                        createLinesTransaction.RollBack();
                    }
                }
                else
                {
                    ;
                }
            }
        }
Example #2
0
        public RoomsCDRTRequest(UIApplication uiApp, String text)
        {
            RVTDocument doc = uiApp.ActiveUIDocument.Document;

            Autodesk.Revit.DB.View activeView = doc.ActiveView;

            //Verify the active view is a floor plan view
            if (activeView.ViewType != ViewType.FloorPlan)
            {
                MessageBox.Show("Please run from a demo floor plan view.");
            }
            else
            {
                //Get the current phase of the active view
                Phase     currentPhase    = doc.GetElement(activeView.get_Parameter(BuiltInParameter.VIEW_PHASE).AsElementId()) as Phase;
                ElementId currentPhaseId  = currentPhase.Id;
                ElementId previousPhaseId = null;
                //Collect the phases of the document
                PhaseArray phaseArray = doc.Phases;

                //Cycle through the phases in the project to get the previous phase
                for (int i = 0; i < phaseArray.Size; i++)
                {
                    //By finding the index of the current phase, which must not be the first phase, the phase in the previous index can be obtained
                    if (phaseArray.get_Item(i).ToString() == currentPhase.ToString() && i != 0)
                    {
                        previousPhaseId = phaseArray.get_Item(i - 1).Id;
                    }
                    i++;
                }

                //Collect the rooms in the current view where their phase is equal to the active view's phase
                List <Room>   currentVisibleRooms       = new FilteredElementCollector(doc, activeView.Id).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType().ToElements().Cast <Room>().Where(r => r.get_Parameter(BuiltInParameter.ROOM_PHASE).AsElementId() == currentPhaseId).ToList();
                List <string> currentVisibleRoomNumbers = new List <string>();

                //Get the list of currently visible rooms' numbers
                foreach (Room room in currentVisibleRooms)
                {
                    currentVisibleRoomNumbers.Add(room.Number);
                }

                //Only continue if the previous phase was found
                if (previousPhaseId != null)
                {
                    List <Room> previousRoomsToTag = new List <Room>();
                    Outline     outline            = null;
                    try
                    {
                        //This portion will require a new outline from the view's bounding box
                        BoundingBoxXYZ viewBBox = activeView.get_BoundingBox(activeView);
                        //Get the active view as a plan view so the view range can be obtained for the height of the outline
                        ViewPlan      viewPlan      = activeView as ViewPlan;
                        PlanViewRange planViewRange = viewPlan.GetViewRange();
                        double        minX          = viewBBox.Min.X;
                        double        minY          = viewBBox.Min.Y;
                        //The bottom Z point of the outline will be the elevation of the view's level plus the bottom offset
                        double minZ = activeView.GenLevel.Elevation + planViewRange.GetOffset(PlanViewPlane.BottomClipPlane);
                        double maxX = viewBBox.Max.X;
                        double maxY = viewBBox.Max.Y;
                        //The top Z point of the outline will be the elevation of the view's level plust the top offset
                        double maxZ = activeView.GenLevel.Elevation + planViewRange.GetOffset(PlanViewPlane.TopClipPlane);
                        //Generate the minimum and maximum points
                        XYZ minPoint = new XYZ(minX, minY, minZ);
                        XYZ maxPoint = new XYZ(maxX, maxY, maxZ);
                        //Make a new outline from the points
                        outline = new Outline(minPoint, maxPoint);

                        //Establish a new bounding box filter using the outline
                        BoundingBoxIntersectsFilter bboxFilter = new BoundingBoxIntersectsFilter(outline);
                        //The previous rooms will be those that pass the bounding box intersects filter (their bounding boxes intersect the view bounding box) and they belong to the previous phase
                        var previousNonVisibleRooms = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms).WhereElementIsNotElementType().WherePasses(bboxFilter).ToElements().Where(r => r.get_Parameter(BuiltInParameter.ROOM_PHASE).AsElementId() == previousPhaseId);
                        foreach (Element elem in previousNonVisibleRooms)
                        {
                            //Get the rooms and their numbers
                            Room   room       = elem as Room;
                            string roomNumber = room.Number;
                            //Verify the room number is not in the current view's list of visible room numbers
                            if (!currentVisibleRoomNumbers.Contains(roomNumber))
                            {
                                previousRoomsToTag.Add(room);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        //If something went wrong in getting the demoed rooms, report an error
                        MessageBox.Show(e.ToString(), "Getting Demo Rooms Error");
                    }

                    //Start a transaction to make the new tags
                    Transaction t = new Transaction(doc, "Create Demo Room Tags");
                    t.Start();
                    FamilySymbol symbol = null;
                    //Create a new instance of the load options
                    IFamilyLoadOptions loadOptions = new RVTFamilyLoadOptions();

                    try
                    {
                        //Get the versioned symbol family to use as a "tag"
                        string roomTagSymbolPath = RVTOperations.GetVersionedFamilyFilePath(uiApp, Properties.Settings.Default.RevitRoomTagSymbol);
                        try
                        {
                            //Load only the particular type of tag
                            doc.LoadFamilySymbol(roomTagSymbolPath, Properties.Settings.Default.RevitRoomTagSymbolType, loadOptions, out FamilySymbol symb);
                            symbol = symb;
                        }
                        catch
                        {
                            //If it could not be loaded, let the user know it needs added to the family for the script to work
                            MessageBox.Show(String.Format("The family type {0} could not be found in {1}. Please add it for this tool to work.",
                                                          Properties.Settings.Default.RevitRoomTagSymbolType,
                                                          Properties.Settings.Default.RevitRoomTagSymbol));
                        }
                    }
                    catch
                    {
                        //If the family itself could not be loaded, let the user know where the family was expected to be found.
                        MessageBox.Show(String.Format("The {0} family could not be found at {1}. Please place the {0} family in the {1} folder for this tool to work.",
                                                      Path.GetFileNameWithoutExtension(Properties.Settings.Default.RevitRoomTagSymbol),
                                                      Path.GetDirectoryName(Properties.Settings.Default.RevitRoomTagSymbol)));
                    }

                    try
                    {
                        //Verify there are rooms to tag and the family symbol to use is not null
                        if (previousRoomsToTag.Count > 0 && symbol != null)
                        {
                            //Cycle through the demoed rooms
                            foreach (Room demoRoom in previousRoomsToTag)
                            {
                                //Get the location point of the demo room as a point
                                LocationPoint roomLocationPoint = demoRoom.Location as LocationPoint;
                                //Make a new symbol at the locatoin
                                FamilyInstance newSymbol = doc.Create.NewFamilyInstance(roomLocationPoint.Point, symbol, activeView);
                                //Update the parameter values for room Name and Number in the symbol
                                newSymbol.GetParameters("Name").First().Set(demoRoom.get_Parameter(BuiltInParameter.ROOM_NAME).AsString());
                                newSymbol.GetParameters("Number").First().Set(demoRoom.get_Parameter(BuiltInParameter.ROOM_NUMBER).AsString());
                            }
                        }
                        t.Commit();
                    }
                    catch (Exception f)
                    {
                        //Well, crap, the symbol didn't place in the view
                        MessageBox.Show(f.ToString(), "Placement Error");
                        t.RollBack();
                    }
                }
                else
                {
                    //If the previous phase was null, then the current phase of the view is the first phase, so let the user know
                    MessageBox.Show("The currently viewed phase is the earliest phase in the project. Please verify you are viewing a new construction phase, but showing previous and demoed elements.");
                }
            }
        }