ADN Open CIS
Сообщество программистов Autodesk в СНГ

30/05/2018

Автоматическое создание стен по экземплярам семейств в проект

Вопрос: я разрабатываю расширение для автоматического создания стен по граням семейства, определяющего внутреннее пространство здания

Поскольку я не могу создать стены в самом семействе, мне приходится создавать их по координатам (x, y, z) используя API, т.е., мне нужно создавать стены по произвольному кубу.

Моя проблема заключается в том, что когда угол поворота не равен 0 градусам, я не знаю как  преобразовать координаты начальных и конечных точек стен.

Какие формулы мне нужно использовать чтобы получить требуемые мне координаты? Я приложил документ efortune_trigrevitapi.pdf с моими соображениями о том, как определять углы.

Ответ: Вы сильно переусложнили формулы в Вашем пятистраничном PDF. Судя по Вашему описанию проблемы, все можно сделать намного проще, причем совершенно не заботясь о том, в каком квадранте находятся искомые точки.

Прямую вертикальную стену можно описать с помощью двух точек p и q, определяющих начальную и конечную точки стены.

Куб, который вставлен в модель определяется с помощью преобразования T, определяющего поворот на угол a и перенос на вектор v.

Вы можете сначала повернуть обе точки p и q вокруг начала координат (или любой другой оси) на угол a, а затем перенести их вдоль вектора v.

В качестве альтернативы, Вы можете использовать модельные координаты вершин куба.

Файл с примером: autowalls.rvt

Код для создания стен и дверей:

Код - C#: [Выделить]
  1.  using System.Collections.Generic;
  2. using System.Linq;
  3. using Autodesk.Revit.Attributes;
  4. using Autodesk.Revit.DB;
  5. using Autodesk.Revit.DB.Structure;
  6. using Autodesk.Revit.Exceptions;
  7. using Autodesk.Revit.UI;
  8.  
  9. namespace AutoWallsByCubes
  10. {
  11.     [Transaction(TransactionMode.Manual)]
  12.     public class CreateWallsAutomaticallyCommand : IExternalCommand
  13.     {
  14.         public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
  15.         {
  16.             var uiapp = commandData.Application;
  17.             var uidoc = uiapp.ActiveUIDocument;
  18.             var doc = uidoc.Document;
  19.  
  20.             var cubes = FindCubes(doc);
  21.  
  22.             using (var transaction = new Transaction(doc, "create walls"))
  23.             {
  24.                 transaction.Start();
  25.  
  26.                 foreach (var cube in cubes)
  27.                 {
  28.                     var countours = FindCountors(cube)
  29.                         .SelectMany(x => x);
  30.  
  31.                     var height = cube.LookupParameter("height").AsDouble();
  32.  
  33.                     foreach (var countour in countours)
  34.                     {
  35.                         var wall = CreateWall(cube, countour, height);
  36.  
  37.                         CreateDoor(wall);
  38.                     }
  39.                 }
  40.  
  41.                 transaction.Commit();
  42.             }
  43.            
  44.             return Result.Succeeded;
  45.         }
  46.  
  47.         private static Wall CreateWall(FamilyInstance cube, Curve curve, double height)
  48.         {
  49.             var doc = cube.Document;
  50.  
  51.             var wallTypeId = doc.GetDefaultElementTypeId(ElementTypeGroup.WallType);
  52.  
  53.             return Wall.Create(doc, curve.CreateReversed(), wallTypeId, cube.LevelId, height, 0, false, false);
  54.         }
  55.  
  56.         private static void CreateDoor(Wall wall)
  57.         {
  58.             var locationCurve = (LocationCurve) wall.Location;
  59.  
  60.             var position = locationCurve.Curve.Evaluate(0.5, true);
  61.  
  62.             var document = wall.Document;
  63.  
  64.             var level = (Level)document.GetElement(wall.LevelId);
  65.  
  66.             var symbolId = document.GetDefaultFamilyTypeId(new ElementId(BuiltInCategory.OST_Doors));
  67.  
  68.             var symbol = (FamilySymbol)document.GetElement(symbolId);
  69.  
  70.             if (!symbol.IsActive)
  71.                 symbol.Activate();
  72.  
  73.             document.Create.NewFamilyInstance(position, symbol, wall, level, StructuralType.NonStructural);
  74.         }
  75.  
  76.         private static IEnumerable<FamilyInstance> FindCubes(Document doc)
  77.         {
  78.             var collector = new FilteredElementCollector(doc);
  79.  
  80.             return collector
  81.                 .OfCategory(BuiltInCategory.OST_GenericModel)
  82.                 .OfClass(typeof (FamilyInstance))
  83.                 .OfType<FamilyInstance>()
  84.                 .Where(x => x.Symbol.FamilyName == "cube");
  85.         }
  86.  
  87.         private static IEnumerable<CurveLoop> FindCountors(FamilyInstance familyInstance)
  88.         {
  89.             return GetSolids(familyInstance)
  90.                 .SelectMany(x => GetCountours(x, familyInstance));
  91.         }
  92.  
  93.         private static IEnumerable<Solid> GetSolids(Element element)
  94.         {
  95.             var geometry = element
  96.               .get_Geometry(new Options { ComputeReferences = true, IncludeNonVisibleObjects = true });
  97.  
  98.             if (geometry == null)
  99.                 return Enumerable.Empty<Solid>();
  100.  
  101.             return GetSolids(geometry)
  102.                 .Where(x => x.Volume > 0);
  103.         }
  104.  
  105.         private static IEnumerable<Solid> GetSolids(IEnumerable<GeometryObject> geometryElement)
  106.         {
  107.             foreach (var geometry in geometryElement)
  108.             {
  109.                 var solid = geometry as Solid;
  110.                 if (solid != null)
  111.                     yield return solid;
  112.  
  113.                 var instance = geometry as GeometryInstance;
  114.                 if (instance != null)
  115.                     foreach (var instanceSolid in GetSolids(instance.GetInstanceGeometry()))
  116.                         yield return instanceSolid;
  117.  
  118.                 var element = geometry as GeometryElement;
  119.                 if (element != null)
  120.                     foreach (var elementSolid in GetSolids(element))
  121.                         yield return elementSolid;
  122.             }
  123.         }
  124.  
  125.         private static IEnumerable<CurveLoop> GetCountours(Solid solid, Element element)
  126.         {
  127.             try
  128.             {
  129.                 var plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, element.get_BoundingBox(null).Min);
  130.  
  131.                 var analyzer = ExtrusionAnalyzer.Create(solid, plane, XYZ.BasisZ);
  132.  
  133.                 var face = analyzer.GetExtrusionBase();
  134.  
  135.                 return face.GetEdgesAsCurveLoops();
  136.             }
  137.             catch (InvalidOperationException)
  138.             {
  139.                 return Enumerable.Empty<CurveLoop>();
  140.             }
  141.         }
  142.     }
  143. }

Семейства в проекте до запуска команды:

 

Стены и двери по контуру куба после  запуска команды:

 

Если Вам больше нравится другой подход, посмотрите как работать с Transform

Матрицу преобразования экземпляра семейства Вы можете получить с помощью метода familyInstance.GetTotalTransform

Источник: http://thebuildingcoder.typepad.com/blog/2017/11/automatic-wall-creation.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=

Опубликовано 30.05.2018