Esempio n. 1
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            try
            {
                UIApplication uiapp = commandData.Application;
                UIDocument    uidoc = uiapp.ActiveUIDocument;
                Application   app   = uiapp.Application;
                Document      doc   = uidoc.Document;

                string outputFile = @"C:\Temp\reportSheetSummary.csv";

                StringBuilder sb = new StringBuilder();

                //store the name of the missing parameter (is any). Either 'Mx Export_Sheet Filter' or 'CAAD File Name'
                string paramError = "";

                string paramExportSheetFilter = "Mx Export_Sheet Filter";

                try
                {
                    File.WriteAllText(outputFile,
                                      "Sheet Number," +
                                      "Group" +
                                      Environment.NewLine
                                      );

                    //List<ViewScheduleOption> viewScheduleOptions = Helpers.GetViewScheduleOptions(doc);

                    List <ViewSchedule> viewSchedule = Helpers.SheetList(doc);


                    using (var form = new SheetSummaryForm())
                    {
                        //set the form sheets
                        form.cboxSheetDataSource = viewSchedule;

                        //set the form title
                        form.Text = "Populate Sheet Filter";

                        //use ShowDialog to show the form as a modal dialog box.
                        form.ShowDialog();

                        //if the user hits cancel just drop out of macro
                        if (form.DialogResult == winForm.DialogResult.Cancel)
                        {
                            return(Result.Cancelled);
                        }

                        //selected Sheet List
                        ViewSchedule selectedSheetList = form.selectedViewSchedule;

                        //Sheets in selected sheet list
                        var selectedSheets = new FilteredElementCollector(doc, selectedSheetList.Id).OfClass(typeof(ViewSheet)).ToElements().Cast <ViewSheet>();

                        int    n       = selectedSheets.Count();
                        string s       = "{0} of " + n.ToString() + " sheets processed...";
                        string caption = "Find oversized views";

                        int countOverlappingViewports    = 0;
                        int countNonOverlappingViewports = 0;
                        int countNoPlansViewports        = 0;
                        int keynotesCount = 0;

                        string sheetGroup = ""; //No plans, Plans not Overlapping, Plans Overlapping, Keynotes, No Keynotes

                        //Find the sheets that have plans with keynotes on it. Note: this does not ensure there is a keynote on the Sheet! Could not find
                        //a better way of doing this
                        string sheetsWithKeynotes = Helpers.FindSheetsWithKeynotesOnPlan(doc);

                        using (Transaction t = new Transaction(doc, "Set Sheet Parameter"))
                        {
                            t.Start();

                            using (ProgressForm pf = new ProgressForm(caption, s, n))
                            {
                                foreach (ViewSheet vs in selectedSheets)
                                {
                                    if (pf.abortFlag)
                                    {
                                        break;
                                    }

                                    //if Mx Export_Sheet Filter param does not exists, exit
                                    if (vs.LookupParameter(paramExportSheetFilter) == null)
                                    {
                                        paramError = $"{paramExportSheetFilter} not found on Sheets.";
                                        throw new System.NullReferenceException();
                                    }

                                    //select all viewports on the current sheet..not needed TBC
                                    ICollection <ElementId> viewports = vs.GetAllViewports();

                                    //Select all the views on a sheet
                                    ISet <ElementId> placedViewsIds = vs.GetAllPlacedViews();

                                    //if "Mx Keyplan (Y as required) param does not exists, exit
                                    if (placedViewsIds.Count > 0)
                                    {
                                        if (doc.GetElement(placedViewsIds.First()).LookupParameter("Mx Keyplan (Y as required)") == null)
                                        {
                                            paramError = "'Mx Keyplan (Y as required)' not found on Views.";
                                            throw new System.NullReferenceException();
                                        }
                                    }


                                    //Filter the views that are plans (Floor,Ceiling,Engineering or Area)
                                    List <View> planViews = Helpers.FilterPlanViewport(doc, placedViewsIds);


                                    if (planViews.Count > 0) //sheet has plan views
                                    {
                                        //check if they are overlapping
                                        string testOverlappingView = Helpers.CheckVPOverlaps(doc, planViews);
                                        if (testOverlappingView.Contains("xref"))
                                        {
                                            sheetGroup = "Plans Overlapping";
                                            countOverlappingViewports += 1;
                                        }
                                        else
                                        {
                                            sheetGroup = "Plans not Overlapping";
                                            countNonOverlappingViewports += 1;
                                        }
                                        //check if there is a keynote
                                        if (sheetsWithKeynotes.Contains(vs.SheetNumber))
                                        {
                                            sheetGroup    += "-Keynote";
                                            keynotesCount += 1;
                                        }
                                    }
                                    else
                                    {
                                        sheetGroup             = "No plan views";
                                        countNoPlansViewports += 1;
                                    }

                                    //store the group data in a sheet parameter - hardcoded
                                    Parameter p = vs.LookupParameter(paramExportSheetFilter);

                                    if (p.HasValue && p.AsString() != "")
                                    {
                                        throw new System.ArgumentException();
                                    }
                                    else
                                    {
                                        p.Set(sheetGroup);
                                    }



                                    sb.AppendLine($"{vs.SheetNumber},{sheetGroup}");
                                } //close foreach
                            }     //close ProgressForm

                            t.Commit();
                        }
                        File.AppendAllText(outputFile, sb.ToString());

                        TaskDialog myDialog = new TaskDialog("Summary");
                        myDialog.MainIcon    = TaskDialogIcon.TaskDialogIconNone;
                        myDialog.MainContent = $"Operation completed.\n{countNoPlansViewports} sheets do not have plan views\n{countNonOverlappingViewports} sheets do not have overlapping views\n{countOverlappingViewports} sheets do have overlapping views\n{keynotesCount} keynotes found";

                        myDialog.AddCommandLink(TaskDialogCommandLinkId.CommandLink4, $"Open Log File {outputFile}", "");

                        TaskDialogResult res = myDialog.Show();

                        if (TaskDialogResult.CommandLink4 == res)
                        {
                            System.Diagnostics.Process process = new System.Diagnostics.Process();
                            process.StartInfo.FileName = outputFile;
                            process.Start();
                        }
                    } //close using form
                }     //close try
                catch (System.NullReferenceException)
                {
                    TaskDialog.Show("Error", $"Shared Parameter {paramError}");
                    return(Result.Failed);
                }
                catch (System.ArgumentException)
                {
                    TaskDialog.Show("Error", $"The parameter '{paramExportSheetFilter}' is not empty. Operation cancelled.");
                    return(Result.Failed);
                }
                catch (System.IO.IOException)
                {
                    TaskDialog.Show("Error", "Please close the log file before exporting.");
                    return(Result.Failed);
                }
                catch (Exception ex)
                {
                    TaskDialog.Show("Error", ex.GetType().ToString());
                    return(Result.Failed);
                }

                return(Result.Succeeded);
            }//close form
            catch (Exception ex)
            {
                TaskDialog.Show("Result", ex.Message);
                return(Result.Cancelled);
            }
        }//close execute
Esempio n. 2
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            //Goal: convert the Viewport centre coordinates on a Sheet to Project Base Point (and then Survey Point) coordinates.
            //Solution: Find the Viewport's view centre point which is in PBP coordinates.
            //Problem: the Vieport centre does not always match the View centre. Annotations, Matchlines and Grids can affect the extent of the viewport.
            //Solution: hide all these categories and find the Viewport centre that matches the View centre. Then find the View centre point in PBP coordinates and translate it
            //by the vector from Viewport original centre and the centre of the Viewport with the categories hidden.
            //https://thebuildingcoder.typepad.com/blog/2018/03/boston-forge-accelerator-and-aligning-plan-views.html

            UIApplication uiapp = commandData.Application;
            UIDocument    uidoc = uiapp.ActiveUIDocument;
            Application   app   = uiapp.Application;
            Document      doc   = uidoc.Document;

            StringBuilder sb = new StringBuilder();

            sb.AppendLine($"Sheet Number,View Centre WCS-X,View Centre WCS-Y,View Centre WCS-Z,Angle to North,Viewport Centre-X,Viewport Centre-Y,Viewport Centre-Z,Viewport Width,Viewport Height,Xref name,Group");

            string outputFile = "summary.csv";

            ProjectLocation pl           = doc.ActiveProjectLocation;
            Transform       ttr          = pl.GetTotalTransform().Inverse;
            ProjectPosition projPosition = doc.ActiveProjectLocation.GetProjectPosition(new XYZ(0, 0, 0)); //rotation

            IEnumerable <ViewSheet> allSheets = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Sheets)
                                                .WhereElementIsNotElementType().ToElements().Cast <ViewSheet>();

            IList <string> dWGExportOptions = DWGExportOptions.GetPredefinedSetupNames(doc);

            //List<ViewScheduleOption> viewScheduleOptions = Helpers.GetViewScheduleOptions(doc);

            //find all the sheet list
            List <ViewSchedule> viewSchedule = Helpers.SheetList(doc);

            int counter = 0;


            try
            {
                using (var form = new Form1())
                {
                    form.CboxExportSettingsDataSource = dWGExportOptions;
                    //set the form sheets
                    form.CboxSheetDataSource = viewSchedule;
                    //set the form title
                    form.Text = "Mx CADD Export Xrefs";

                    //use ShowDialog to show the form as a modal dialog box.
                    form.ShowDialog();

                    //if the user hits cancel just drop out of macro
                    if (form.DialogResult == winForm.DialogResult.Cancel)
                    {
                        return(Result.Cancelled);
                    }

                    string destinationFolder = form.TBoxDestinationFolder;

                    //string[] sheetNumbers = form.tboxSelectedSheets.Split(' ');
                    //selected Sheet List
                    ViewSchedule selectedSheetList = form.selectedViewSchedule;

                    //Sheets in selected sheet list
                    var selectedSheets = new FilteredElementCollector(doc, selectedSheetList.Id).OfClass(typeof(ViewSheet)).ToElements().Cast <ViewSheet>();

                    string exportSettings = form.TBoxExportSettings;

                    int    n       = selectedSheets.Count();
                    string s       = "{0} of " + n.ToString() + " plans exported...";
                    string caption = "Export xrefs";

                    string sheetWithoutArchOrEngViewports = "";

                    var watch = System.Diagnostics.Stopwatch.StartNew();

                    using (ProgressForm pf = new ProgressForm(caption, s, n))
                    {
                        foreach (ViewSheet vs in selectedSheets)
                        {
                            if (pf.abortFlag)
                            {
                                break;
                            }

                            try
                            {
                                //Collect all the viewports on the sheet
                                ICollection <ElementId> viewportIds = vs.GetAllViewports();

                                //Collect all views on the sheet
                                ISet <ElementId> placedViewsIds = vs.GetAllPlacedViews();

                                //Filter the views that are plans (Floor,Ceiling,Engineering or Area) and exclude Keyplans. I need the
                                //viewport associate with the view so I cannot reuse this filter
                                List <View> planViews = Helpers.FilterPlanViewport(doc, placedViewsIds);

                                //Collect the viewports that shows a Floor Plan (Architecture) or Structural Plan (Engineering).
                                Dictionary <Viewport, View> viewportViewDict = new Dictionary <Viewport, View>();

                                //if the sheet does not contain FloorPlan, EngineeringPlan or CeilingPlan, do not export it
                                int hasArchOrStrViewports = 0;

                                foreach (ElementId eid in viewportIds)
                                {
                                    Viewport vport    = doc.GetElement(eid) as Viewport;
                                    View     planView = doc.GetElement(vport.ViewId) as View;

                                    //Filter the views that are plans (Floor,Ceiling,Engineering or Area)
                                    if (planView.ViewType == ViewType.FloorPlan || planView.ViewType == ViewType.EngineeringPlan || planView.ViewType == ViewType.CeilingPlan || planView.ViewType == ViewType.AreaPlan)
                                    {
                                        //if planview is not a keyplan do not export it
                                        if (Helpers.IsNotKeyplan(planView))
                                        {
                                            viewportViewDict.Add(vport, planView);
                                            //vpPlan.Add(planView);
                                            hasArchOrStrViewports += 1;
                                        }
                                    }
                                }

                                if (hasArchOrStrViewports != 0)
                                {
                                    //if the parameter does not exists use the SheetNumber
                                    string CAADparameter = vs.LookupParameter("CADD File Name").AsString() ?? vs.SheetNumber;

                                    //remove white spaces from the name
                                    string fileName = Helpers.RemoveWhitespace(CAADparameter);

                                    foreach (Viewport vp in viewportViewDict.Keys)
                                    {
                                        View vpPlan = viewportViewDict[vp];
                                        //Get the current Viewport Centre for Autocad Viewport
                                        XYZ unchangedVPcenter = vp.GetBoxCenter();
                                        //Set its Z value to 0
                                        XYZ flattenVPcenter = new XYZ(unchangedVPcenter.X, unchangedVPcenter.Y, 0);
                                        //The current Viewport Centre does not match the view center. Hide all the elements in the view and set the annotation crop to the minimum (3mm). Now the
                                        //Viewport centre will match the View centre. We can then use the unchangedCenter to changedCenter vector to move the view centerpoint to the original
                                        //viewport centre.

                                        //Instead of hiding categories, we can isolate an empty one. Check that this category (OST_Loads) exists in the model or it will throw an error
                                        ICollection <ElementId> categoryToIsolate = new List <ElementId>();
                                        Categories groups = doc.Settings.Categories;
                                        categoryToIsolate.Add(groups.get_Item(BuiltInCategory.OST_Loads).Id);

                                        //This is the new Viewport centre, aligned with the View centre
                                        XYZ changedVPcenter = null;

                                        // This is the View centre
                                        XYZ centroid = null;

                                        double scale = 304.8;

                                        using (Transaction t = new Transaction(doc, "Hide categories"))
                                        {
                                            t.Start();

                                            vpPlan.IsolateCategoriesTemporary(categoryToIsolate);

                                            //Use the annotation crop region to find the view centroid
                                            ViewCropRegionShapeManager vcr = vpPlan.GetCropRegionShapeManager();
                                            //Set the annotation offset to the minimum (3mm)
                                            vcr.BottomAnnotationCropOffset = 3 / scale;
                                            vcr.TopAnnotationCropOffset    = 3 / scale;
                                            vcr.LeftAnnotationCropOffset   = 3 / scale;
                                            vcr.RightAnnotationCropOffset  = 3 / scale;
                                            //Get the Viewport Center. This will match the View centroid
                                            changedVPcenter = vp.GetBoxCenter();

                                            //Find the view centroid using the annotation crop shape (it should always be a rectangle, while the cropbox shape can be a polygon).
                                            CurveLoop  cloop = vcr.GetAnnotationCropShape();
                                            List <XYZ> pts   = new List <XYZ>();

                                            foreach (Curve crv in cloop)
                                            {
                                                pts.Add(crv.GetEndPoint(0));
                                                pts.Add(crv.GetEndPoint(1));
                                            }

                                            //View centroid with elements hidden
                                            centroid = Helpers.GetCentroid(pts, pts.Count);

                                            t.RollBack();
                                        }

                                        //Set ChangedVP center Z value to 0
                                        XYZ flattenChangedVPcenter = new XYZ(changedVPcenter.X, changedVPcenter.Y, 0);

                                        //This is the vector from the Viewport original centre to Viewport centre with all the elements hidden and the cropbox set to 3mm evenly
                                        XYZ viewPointsVector = (flattenVPcenter - flattenChangedVPcenter) * vpPlan.Scale;

                                        //View center adjusted to Viewport original centre (the one to be used in Autocad)
                                        XYZ translatedCentroid = centroid + viewPointsVector;

                                        //View center per Survey Point coordinates
                                        XYZ viewCentreWCS = ttr.OfPoint(translatedCentroid);

                                        XYZ viewCentreWCSZ = new XYZ(viewCentreWCS.X, viewCentreWCS.Y, vpPlan.get_BoundingBox(vpPlan).Transform.Origin.Z);

                                        //Viewport outline width and height to be used to update the autocad viewport
                                        XYZ maxPt  = vp.GetBoxOutline().MaximumPoint;
                                        XYZ minPt  = vp.GetBoxOutline().MinimumPoint;
                                        int width  = Convert.ToInt32((maxPt.X - minPt.X) * 304.8);
                                        int height = Convert.ToInt32((maxPt.Y - minPt.Y) * 304.8);

                                        //string xrefName = $"{vs.SheetNumber}-{vp.Id}-xref";

                                        //Set the file name to CAAD parameter
                                        string xrefName = $"{fileName}-{vp.Id}-xref";


                                        if (!Helpers.ExportDWG(doc, vpPlan, exportSettings, xrefName, destinationFolder))
                                        {
                                            TaskDialog.Show("Error", "Check that the destination folder exists");
                                        }
                                        else
                                        {
                                            counter += 1;
                                        }

                                        //Check if views are overlapping. If they are, xref should not be bind
                                        string group = "";

                                        // TBC dictionary values are working. Seems to work more accurately than planViews. TBC2 they seem to
                                        // give the same output
                                        //if (Helpers.CheckSingleViewOverlaps(doc, vpPlan, planViews))
                                        if (Helpers.CheckSingleViewOverlaps(doc, vpPlan, viewportViewDict.Values.ToList()))
                                        {
                                            group = "xref";
                                        }
                                        else
                                        {
                                            group = "bind";
                                        }

                                        sb.AppendLine($"{ fileName}," +
                                                      $"{ Helpers.PointToString(viewCentreWCSZ)}," +
                                                      $"{projPosition.Angle * 180 / Math.PI}," +
                                                      $"{Helpers.PointToString(flattenVPcenter)}," +
                                                      $"{width.ToString()},{height.ToString()}," +
                                                      $"{xrefName}," +
                                                      $"{group}");
                                    } //close foreach
                                }     //close if sheet has viewports to export
                                else
                                {
                                    sheetWithoutArchOrEngViewports += $"{vs.SheetNumber}\n";
                                }

                                pf.Increment();
                            }
                            catch (Exception ex)
                            {
                                sheetWithoutArchOrEngViewports += $"{vs.SheetNumber}: {ex.Message}\n";
                                //TaskDialog.Show("r", vs.SheetNumber);
                            }
                        }
                        File.WriteAllText($"{destinationFolder}\\{outputFile}", sb.ToString());
                    }//close form
                    watch.Stop();
                    var elapsedMinutes = watch.ElapsedMilliseconds / 1000 / 60;

                    TaskDialog.Show("Done", $"{counter} plans have been exported and the csv has been created in {elapsedMinutes} min.\nNot exported:\n{sheetWithoutArchOrEngViewports}");
                    return(Result.Succeeded);
                }//close form
            }
            catch (Exception ex)
            {
                TaskDialog.Show("Error", ex.Message);
                return(Result.Failed);
            }
        }