REVIT Перенос эскиза пола в Void Extrusion in Family - PullRequest
0 голосов
/ 08 октября 2019

Борьба с некоторым кодом Revit для копирования профиля пола и использования его в качестве профиля эскиза для вытеснения пустот в семье.

Вот полный код разработки Sharp. Он наполовину работает в моем пользовательском шаблоне проекта, когда я пытаюсь использовать его в готовом проекте, сгенерированном из шаблона revit по умолчанию, он выдает ошибку «управляемое исключение было сгенерировано revit или одним из его внешних приложений»

В моем шаблоне он не может правильно разделить кривые на вторичный массив. Он говорит, что элементы массива изменяются, но когда цикл запускается снова, элемент i возвращается к своему первоначальному содержимому ??? TaskDialog четко говорит, что элементы изменились, пока цикл не повторяется снова.

Полный код: Для работы требуется наличие в проекте общего семейства с именем «Void - Custom». «Если найдено» рядом с последней последней страницей и половиной кода, то цикл for работает не так, как ожидалось.

        /*
 * Created by SharpDevelop.
 * User: arautio
 * Date: 4/30/2019
 * Time: 11:10 AM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using System.Text;
using System.IO;
using System.Diagnostics;

namespace ARC
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("3411F411-6FC1-4A4D-9CFD-37ABB2028A15")]
    public partial class ThisApplication
    {
        private void Module_Startup(object sender, EventArgs e)
        {

        }

        private void Module_Shutdown(object sender, EventArgs e)
        {

        }

        #region Revit Macros generated code
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(Module_Startup);
            this.Shutdown += new System.EventHandler(Module_Shutdown);
        }
        #endregion


public void FloorGrating()
    {

        StringBuilder sb = new StringBuilder();
        Dictionary<Floor, List<ModelCurve>> dict_SketchLines = new Dictionary<Floor, List<ModelCurve>>();

        UIDocument uidoc = this.ActiveUIDocument;
        Document document = uidoc.Document;
        View activev = document.ActiveView;

        ElementId levelId = null;
        levelId = activev.LevelId;
        Element levelem = document.GetElement( levelId );
        Level lev = document.ActiveView.GenLevel;

          Reference refsel = uidoc.Selection.PickObject(ObjectType.Element, "Select Floor to Add Grating To");
          Element elem = document.GetElement(refsel.ElementId);

            Floor f = elem as Floor;
            List<ElementId> _deleted = null;
            using (Transaction t = new Transaction(document, "temp"))
            {
                t.Start();
                document.Regenerate();
                _deleted = document.Delete(elem.Id).ToList();
                t.RollBack();
            }
            bool SketchLinesFound = false;
            List<ModelCurve> _sketchCurves = new List<ModelCurve>();

            foreach (var id in _deleted)
            {
                ModelCurve mc = document.GetElement(id) as ModelCurve;
                if (mc != null)
                {
                    _sketchCurves.Add(mc);
                    SketchLinesFound = true;
                }
                else
                {
                    if (SketchLinesFound) break;
                }
            }
            dict_SketchLines.Add(f, _sketchCurves);

        foreach (Floor key in dict_SketchLines.Keys)
        {
            List<ModelCurve> _curves = dict_SketchLines[key];
            sb.AppendLine(string.Format("floor {0} has sketchlines:", key.Id));

            foreach (ModelCurve mc in _curves)
            {
                sb.AppendLine(string.Format("{0}  <{1}>", mc.GetType(), mc.Id));
                sb.AppendLine(string.Format("<{0}>", mc.GeometryCurve.IsBound.ToString()));

                if (mc.GetType().ToString() == "Autodesk.Revit.DB.ModelArc" && mc.GeometryCurve.IsBound == false)
                {
                    TaskDialog.Show("Revit", "Circle Found");
                }
                try
                {
                    sb.AppendLine(string.Format("<{0}  --  {1}>", mc.GeometryCurve.GetEndPoint(0), mc.GeometryCurve.GetEndPoint(1)));
                }
                catch
                {

                }
            }
            sb.AppendLine();
        }
        //TaskDialog.Show("debug", sb.ToString());

        Document docfamily;
        Family fam;

        string ftitle = document.Title;
        string fpath = document.PathName;
        int ftitlelen = ftitle.Length + 4;
        int fpathlen = fpath.Length;
        int finpathlen = fpathlen - ftitlelen;
        string sfinpath = fpath.Substring(0,finpathlen);
        string famname = "GratingVoid";
        string fext = ".rfa";

        int counter = 1;
        while (counter < 100)
        {
            famname = ("GratingVoid" + counter as String);
            Family family = FindElementByName(document,typeof(Family),famname)as Family;
                if( null == family )
                {
                    sfinpath = (sfinpath + famname + fext);
                    counter = 1000;
                }
                counter += 1;
        }

        FilteredElementCollector collector0 = new FilteredElementCollector(document);
        ICollection<Element> collection0 = collector0.WhereElementIsNotElementType().ToElements();
        List<FamilySymbol> fsym0 = new FilteredElementCollector(document).OfClass(typeof(FamilySymbol)).Cast<FamilySymbol>().ToList();
        FamilySymbol famsymb0 = null;
            foreach (FamilySymbol symb in fsym0)
            {
                if (symb.Name == "Void - Custom")
                {
                    famsymb0 = symb as FamilySymbol;
                }
            }

            fam = famsymb0.Family;

            docfamily = document.EditFamily(fam);               
            try
            {
                docfamily.SaveAs(@sfinpath);
            }
            catch
            {
                TaskDialog.Show("Revit", "Could Not Save Void Family");
            }

        using (Transaction trans = new Transaction(docfamily))
            {
               trans.Start("family");
                bool circleflag = false;
                ElementId delid = null;
                FilteredElementCollector collector = new FilteredElementCollector( docfamily );
                foreach(Element element in collector.OfClass(typeof(GenericForm)))
                {
                    delid = element.Id;
                }
                docfamily.Delete(delid);

                CurveArray loccurva = new CurveArray();

                foreach (Floor key in dict_SketchLines.Keys)
                {
                    List<ModelCurve> _curves = dict_SketchLines[key];
                    foreach (ModelCurve mc in _curves)
                    {

                        if (mc.GetType().ToString() == "Autodesk.Revit.DB.ModelArc" && mc.GeometryCurve.IsBound == false)
                        {
                            circleflag = true;
                        }
                        LocationCurve lcurve = mc.Location as LocationCurve;
                        Curve c = lcurve.Curve as Curve;
                        loccurva.Append(c);
                    }
                }
                try
                {
                    if (circleflag == true && loccurva.Size == 2)
                    {
                        Curve tempc;
                        if (loccurva.get_Item(0).GetType().ToString() == "Autodesk.Revit.DB.Arc")
                        {
                            tempc = loccurva.get_Item(0);
                        }
                        else
                        {
                            tempc = loccurva.get_Item(1);
                        }
                        loccurva.Clear();
                        loccurva.Append(tempc);
                    }

                CurveArrArray newcurarr = new CurveArrArray();
                newcurarr.Append(loccurva);
                SortCurvesContiguousArray(newcurarr);

                TaskDialog.Show("Revit CurveArray Array Size" , newcurarr.Size.ToString());


                foreach (CurveArray ca in newcurarr)
                {
                    TaskDialog.Show("Revit CurveArray within Array Size" , ca.Size.ToString());
                }

                // Below is edited for error control - leaving out the secondary loops for now

                CurveArrArray switcharr = new CurveArrArray();
                //switcharr.Append(newcurarr.get_Item(1));
                switcharr.Append(newcurarr.get_Item(0));

                //SortCurvesContiguousArray(loccurva);
                //CurveArrArray newcurarr = new CurveArrArray();
                //newcurarr.Append(loccurva);

                double end = 1;
                SketchPlane sketch = FindElementByName( docfamily,typeof( SketchPlane ), "Ref. Level" ) as SketchPlane;
                docfamily.FamilyCreate.NewExtrusion(false, switcharr, sketch, end);

                }
                catch
                {
                    TaskDialog.Show("Revit", "Could Not Write to Curve Array or Create Extrusion");
                }

                trans.Commit();
            }

            docfamily.Save();
            docfamily.LoadFamily(document, new CustomFamilyLoadOption());
            docfamily.Close();
            File.Delete(sfinpath);

            Family familynew = FindElementByName(document,typeof(Family),famname)as Family;
                if( null == familynew )
                {
                    TaskDialog.Show("Revit", "Family Does Not Exist");
                }

            FilteredElementCollector collector1 = new FilteredElementCollector(document);
            ICollection<Element> collection = collector1.WhereElementIsNotElementType().ToElements();
            List<FamilySymbol> fsym = new FilteredElementCollector(document).OfClass(typeof(FamilySymbol)).Cast<FamilySymbol>().ToList();
            FamilySymbol famsymb = null;
            foreach (FamilySymbol symb in fsym)
            {
                if (symb.Name == famname)
                {
                    famsymb = symb as FamilySymbol;
                }
            }

            using (Transaction trans = new Transaction(document))
            {
                trans.Start("PlaceVoid");
                    if( ! famsymb.IsActive )
                    {
                        famsymb.Activate();
                    }
                    XYZ p = new XYZ(0,0,0);
                    FamilyInstance gratingvoid = document.Create.NewFamilyInstance( p, famsymb, lev, lev, StructuralType.NonStructural );
                    document.Regenerate();
                trans.Commit();
            }

    }


//--------------------------------------------------------------------------------------------------------------------------------------------------------


static public Element FindElementByName(Document doc,Type targetType,string targetName)
{
    return new FilteredElementCollector( doc ).OfClass( targetType ).FirstOrDefault<Element>(e => e.Name.Equals( targetName ) );
}


//--------------------------------------------------------------------------------------------------------------------------------------------------------


public class CustomFamilyLoadOption : IFamilyLoadOptions
        {
            public bool OnFamilyFound(bool familyInUse,  out bool overwriteParameterValues)
            {
                overwriteParameterValues = true;
                return true;
            }

            public bool OnSharedFamilyFound(Family sharedFamily,bool familyInUse,out FamilySource source, out bool overwriteParameterValues)
            {
                source = FamilySource.Family;
                overwriteParameterValues = true;
                return true;
            }
        }


//--------------------------------------------------------------------------------------------------------------------------------------------------------


const double _inch = 1.0 / 12.0;
const double _sixteenth = _inch / 16.0;

static Curve CreateReversedCurve(Curve orig )
{
  //if( !IsSupported( orig ) )
  //{
  //  throw new NotImplementedException("CreateReversedCurve for type " + orig.GetType().Name );
  //}

  if( orig is Line )
  {
    //return creapp.NewLineBound(orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ) );
    return Line.CreateBound(orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ) );
  }
  else if( orig is Arc )
  {
   // return creapp.NewArc( orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ), orig.Evaluate( 0.5, true ) );
    return Arc.Create( orig.GetEndPoint( 1 ), orig.GetEndPoint( 0 ), orig.Evaluate( 0.5, true ) );
  }
  else
  {
    throw new Exception(
      "CreateReversedCurve - Unreachable" );
  }
}

public static void SortCurvesContiguousArray(CurveArrArray curvesarr)
{
    double _precision1 = 1.0 / 12.0 / 16.0; // around 0.00520833
    double _precision2 = 0.001; // limit for CurveLoop.Create(...)

    int cn = curvesarr.Size;
    int ci = 0;

    while (ci < cn)

 {
    CurveArray curves = curvesarr.get_Item(ci);
    ci +=1;

    // account for multiple curve loops with secondary array
    CurveArray loop1 = new CurveArray();
    CurveArray loop2 = new CurveArray();

    int n = curves.Size;
    int split = 1;

    // Walk through each curve (after the first)
    // to match up the curves in order

    for (int i = 0; i < n; ++i)
    {
        TaskDialog.Show("Revit I Loop Run", i.ToString());
        Curve curve = curves.get_Item(i);

        if (curve.GetType().ToString() == "Autodesk.Revit.DB.Arc" && curve.IsBound == false)
        {
            break;
        }   

        XYZ beginPoint = curve.GetEndPoint(0);
        XYZ endPoint = curve.GetEndPoint(1);

        XYZ p,q;

        // Find curve with start point = end point

        bool found = (i + 1 >= n);

        for (int j = i + 1; j < n; ++j)
        {
            p = curves.get_Item(j).GetEndPoint(0);
            q = curves.get_Item(j).GetEndPoint(1);

            // If there is a match end->start,
            // this is the next curve
            if (p.DistanceTo(endPoint) < _precision1)
            {
                if (p.DistanceTo(endPoint) > _precision2)
                {
                    XYZ intermediate = new XYZ((endPoint.X + p.X) / 2.0, (endPoint.Y + p.Y) / 2.0, (endPoint.Z + p.Z) / 2.0);

                    curves.set_Item(i, Line.CreateBound(beginPoint, intermediate));

                    curves.set_Item(j, Line.CreateBound(intermediate, q));
                }

                if (i + 1 != j)
                {
                    Curve tmp = curves.get_Item(i + 1);
                    curves.set_Item(i + 1, curves.get_Item(j));
                    curves.set_Item(j, tmp);
                }
                found = true;
                break;
            }

            // If there is a match end->end,
            // reverse the next curve

            if (q.DistanceTo(endPoint) < _precision1)
            {
                if (q.DistanceTo(endPoint) > _precision2)
                {
                    XYZ intermediate = new XYZ((endPoint.X + q.X) / 2.0, (endPoint.Y + q.Y) / 2.0, (endPoint.Z + q.Z) / 2.0);

                    curves.set_Item(i, Line.CreateBound(beginPoint, intermediate));

                    curves.set_Item(j, Line.CreateBound(p, intermediate));
                }

                if (i + 1 == j)
                {
                    curves.set_Item(i + 1, CreateReversedCurve(curves.get_Item(j)));
                }
                else
                {
                    Curve tmp = curves.get_Item(i + 1);
                    curves.set_Item(i + 1, CreateReversedCurve(curves.get_Item(j)));
                    curves.set_Item(j, tmp);
                }
                found = true;
                break;
                }
            }

            if (!found)
            {
                // if not found, must be part of a new loop - move it to the back and keep going and add to second array
                TaskDialog.Show("Revit No Match Found for item", i.ToString());
                TaskDialog.Show("Revit", "Moveing it to back of list");
                Curve tmp1 = curves.get_Item(i);
                TaskDialog.Show("Revit tmp1 Current i item endpt", tmp1.GetEndPoint(0).ToString());
                loop2.Append(tmp1);
                Curve tmp2 = curves.get_Item(n - split);
                TaskDialog.Show("Revit tmp2 Back of list item endpt", tmp2.GetEndPoint(0).ToString());

                // set current item to rear
                curves.set_Item(i, tmp2);
                // set rear item to current
                curves.set_Item(n - split, tmp1);

                TaskDialog.Show("Revit new item i endpt", curves.get_Item(i).GetEndPoint(0).ToString());
                TaskDialog.Show("Revit moved item endpt", curves.get_Item(n - split).GetEndPoint(0).ToString());

                // error testing - try to append in a different manner and check values
                    //curves.set_Item(i, Line.CreateBound(curves.get_Item(i).GetEndPoint(0), curves.get_Item(i).GetEndPoint(1)));
                    //curves.set_Item(n - split, Line.CreateBound(curves.get_Item(n - split).GetEndPoint(0), curves.get_Item(n - split).GetEndPoint(1)));
                    //Curve ncurve = Line.CreateBound(curves.get_Item(n - split).GetEndPoint(0), curves.get_Item(n - split).GetEndPoint(1));
                    //TaskDialog.Show("Revit Appended to Loop2 Endpoint", ncurve.GetEndPoint(0).ToString());
                    //loop2.Append(ncurve);

                //set the split off counter so items not fitting in first loop can be split to new array.
                split += 1;
                //reset the counter back so item moved from rear can be checked in next run of for loop
                i -= 2;
            }

            //set counter to end for loop when all items that do not fit in first loop are processed
            if (i >= n - (split + 1))
            {
                TaskDialog.Show("Revit", "End Of Looping");
                TaskDialog.Show("Revit - The Split Number", split.ToString());
                i = n;
            }
        }

        int counter = 0;

        // recreate array with only items from first loop found
        while (counter <= (n - split))
        {
            loop1.Append(curves.get_Item(counter));
            counter += 1;
        }

        TaskDialog.Show("Revit loop1 Size", loop1.Size.ToString());

        curvesarr.Clear();
        curvesarr.Append(loop1);

        if (loop2.Size > 0)
        {
            string stringinfo = "";

            // run the loop detection on a second array that was split from the first

            TaskDialog.Show("Revit loop2 Size", loop2.Size.ToString());
            CurveArrArray tmpcurvesarr = new CurveArrArray();
            tmpcurvesarr.Append(loop2);
            SortCurvesContiguousArray(tmpcurvesarr);
            loop2.Clear();
            loop2 = tmpcurvesarr.get_Item(0);
            curvesarr.Append(loop2);

            foreach (Curve ccc in loop2)
            {
                stringinfo = (stringinfo + " " + ccc.GetEndPoint(0).ToString() + " - " + ccc.GetEndPoint(1).ToString());
            }
             TaskDialog.Show("Revit", stringinfo);
        }

    }

  }
}




}

Спасибо за любую помощь.

Шейн

...