Автоматическое создание стен по экземплярам семейств в проект
Вопрос: я разрабатываю расширение для автоматического создания стен по граням семейства, определяющего внутреннее пространство здания
Поскольку я не могу создать стены в самом семействе, мне приходится создавать их по координатам (x, y, z) используя API, т.е., мне нужно создавать стены по произвольному кубу.
Моя проблема заключается в том, что когда угол поворота не равен 0 градусам, я не знаю как преобразовать координаты начальных и конечных точек стен.
Какие формулы мне нужно использовать чтобы получить требуемые мне координаты? Я приложил документ efortune_trigrevitapi.pdf с моими соображениями о том, как определять углы.
Ответ: Вы сильно переусложнили формулы в Вашем пятистраничном PDF. Судя по Вашему описанию проблемы, все можно сделать намного проще, причем совершенно не заботясь о том, в каком квадранте находятся искомые точки.
Прямую вертикальную стену можно описать с помощью двух точек p и q, определяющих начальную и конечную точки стены.
Куб, который вставлен в модель определяется с помощью преобразования T, определяющего поворот на угол a и перенос на вектор v.
Вы можете сначала повернуть обе точки p и q вокруг начала координат (или любой другой оси) на угол a, а затем перенести их вдоль вектора v.
В качестве альтернативы, Вы можете использовать модельные координаты вершин куба.
Файл с примером: autowalls.rvt
Код для создания стен и дверей:
- using System.Collections.Generic;
- using System.Linq;
- using Autodesk.Revit.Attributes;
- using Autodesk.Revit.DB;
- using Autodesk.Revit.DB.Structure;
- using Autodesk.Revit.Exceptions;
- using Autodesk.Revit.UI;
- namespace AutoWallsByCubes
- {
- [Transaction(TransactionMode.Manual)]
- public class CreateWallsAutomaticallyCommand : IExternalCommand
- {
- public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
- {
- var uiapp = commandData.Application;
- var uidoc = uiapp.ActiveUIDocument;
- var doc = uidoc.Document;
- var cubes = FindCubes(doc);
- using (var transaction = new Transaction(doc, "create walls"))
- {
- transaction.Start();
- foreach (var cube in cubes)
- {
- var countours = FindCountors(cube)
- .SelectMany(x => x);
- var height = cube.LookupParameter("height").AsDouble();
- foreach (var countour in countours)
- {
- var wall = CreateWall(cube, countour, height);
- CreateDoor(wall);
- }
- }
- transaction.Commit();
- }
- return Result.Succeeded;
- }
- private static Wall CreateWall(FamilyInstance cube, Curve curve, double height)
- {
- var doc = cube.Document;
- var wallTypeId = doc.GetDefaultElementTypeId(ElementTypeGroup.WallType);
- return Wall.Create(doc, curve.CreateReversed(), wallTypeId, cube.LevelId, height, 0, false, false);
- }
- private static void CreateDoor(Wall wall)
- {
- var locationCurve = (LocationCurve) wall.Location;
- var position = locationCurve.Curve.Evaluate(0.5, true);
- var document = wall.Document;
- var level = (Level)document.GetElement(wall.LevelId);
- var symbolId = document.GetDefaultFamilyTypeId(new ElementId(BuiltInCategory.OST_Doors));
- var symbol = (FamilySymbol)document.GetElement(symbolId);
- if (!symbol.IsActive)
- symbol.Activate();
- document.Create.NewFamilyInstance(position, symbol, wall, level, StructuralType.NonStructural);
- }
- private static IEnumerable<FamilyInstance> FindCubes(Document doc)
- {
- var collector = new FilteredElementCollector(doc);
- return collector
- .OfCategory(BuiltInCategory.OST_GenericModel)
- .OfClass(typeof (FamilyInstance))
- .OfType<FamilyInstance>()
- .Where(x => x.Symbol.FamilyName == "cube");
- }
- private static IEnumerable<CurveLoop> FindCountors(FamilyInstance familyInstance)
- {
- return GetSolids(familyInstance)
- .SelectMany(x => GetCountours(x, familyInstance));
- }
- private static IEnumerable<Solid> GetSolids(Element element)
- {
- var geometry = element
- .get_Geometry(new Options { ComputeReferences = true, IncludeNonVisibleObjects = true });
- if (geometry == null)
- return Enumerable.Empty<Solid>();
- return GetSolids(geometry)
- .Where(x => x.Volume > 0);
- }
- private static IEnumerable<Solid> GetSolids(IEnumerable<GeometryObject> geometryElement)
- {
- foreach (var geometry in geometryElement)
- {
- var solid = geometry as Solid;
- if (solid != null)
- yield return solid;
- var instance = geometry as GeometryInstance;
- if (instance != null)
- foreach (var instanceSolid in GetSolids(instance.GetInstanceGeometry()))
- yield return instanceSolid;
- var element = geometry as GeometryElement;
- if (element != null)
- foreach (var elementSolid in GetSolids(element))
- yield return elementSolid;
- }
- }
- private static IEnumerable<CurveLoop> GetCountours(Solid solid, Element element)
- {
- try
- {
- var plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, element.get_BoundingBox(null).Min);
- var analyzer = ExtrusionAnalyzer.Create(solid, plane, XYZ.BasisZ);
- var face = analyzer.GetExtrusionBase();
- return face.GetEdgesAsCurveLoops();
- }
- catch (InvalidOperationException)
- {
- return Enumerable.Empty<CurveLoop>();
- }
- }
- }
- }
Семейства в проекте до запуска команды:
Стены и двери по контуру куба после запуска команды:
Если Вам больше нравится другой подход, посмотрите как работать с 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