838 lines
31 KiB
C#
838 lines
31 KiB
C#
using Autodesk.Revit.DB;
|
||
using Autodesk.Revit.DB.Architecture;
|
||
using Autodesk.Revit.UI;
|
||
using Autodesk.Revit.UI.Selection;
|
||
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
|
||
using Nice3point.Revit.Toolkit.External.Handlers;
|
||
|
||
using ShrlAlgoToolkit.Mvvm.Attributes;
|
||
|
||
using System.ComponentModel.DataAnnotations;
|
||
using System.Windows;
|
||
|
||
|
||
|
||
namespace ShrlAlgoToolkit.RevitAddins.RvCivil;
|
||
|
||
public partial class BricksFinishesViewModel : ObservableValidator
|
||
{
|
||
public BricksFinishesViewModel()
|
||
{
|
||
finishesHandler = new ActionEventHandler();
|
||
PavementLength = 600;
|
||
PavementWidth = 600;
|
||
PavementGap = 2;
|
||
WallBaseOffset = 0;
|
||
PavementThickness = 2;
|
||
PanelName = "铺砖";
|
||
}
|
||
|
||
private readonly ActionEventHandler finishesHandler;
|
||
|
||
[ObservableProperty]
|
||
private bool byRoom;
|
||
|
||
//边界限具有缝隙
|
||
[ObservableProperty]
|
||
private bool isEdgeExistGap;
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[IsNumeric]
|
||
[Minimum(10.0)]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private double pavementWidth;
|
||
|
||
//public double PavementWidth
|
||
//{
|
||
// get => pavementWidth;
|
||
// set => SetProperty(ref pavementWidth, value, true);
|
||
//}
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[IsNumeric]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private double wallBaseOffset;
|
||
|
||
// public double WallBaseOffset
|
||
//{
|
||
// get => wallBaseOffset;
|
||
// set => SetProperty(ref wallBaseOffset, value, true);
|
||
//}
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[IsNumeric]
|
||
[Minimum(1.0)]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private double pavementThickness;
|
||
|
||
// public double PavementThickness
|
||
//{
|
||
// get => pavementThickness;
|
||
// set => SetProperty(ref pavementThickness, value, true);
|
||
//}
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[IsNumeric]
|
||
[Minimum(10.0)]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private double pavementLength;
|
||
|
||
// public double PavementLength
|
||
//{
|
||
// get => pavementLength;
|
||
// set => SetProperty(ref pavementLength, value, true);
|
||
//}
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[IsNumeric]
|
||
[Minimum(1.0)]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private double pavementGap;
|
||
// public double PavementGap
|
||
//{
|
||
// get => pavementGap;
|
||
// set => SetProperty(ref pavementGap, value, true);
|
||
//}
|
||
|
||
[Required(ErrorMessage = "不可为空")]
|
||
[MinLength(1)]
|
||
[ObservableProperty]
|
||
[NotifyDataErrorInfo]
|
||
private string panelName;
|
||
|
||
// public string PanelName
|
||
//{
|
||
// get => panelName;
|
||
// set
|
||
// {
|
||
// SetProperty(ref panelName, value, true);
|
||
// PlaceBricksCommand.NotifyCanExecuteChanged();
|
||
// }
|
||
//}
|
||
|
||
|
||
private static CurtainSystemType SetCurtainSystemType(Document doc, double length, double width, double gap, double thickness, string panelName)
|
||
{
|
||
var curtainSystemTypeCollector = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(CurtainSystemType))
|
||
.OfCategory(BuiltInCategory.OST_CurtaSystem)
|
||
.Cast<CurtainSystemType>()
|
||
.ToList();
|
||
var panelTypeCollector = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(PanelType))
|
||
.OfCategory(BuiltInCategory.OST_CurtainWallPanels)
|
||
.Cast<PanelType>()
|
||
.ToList();
|
||
var curtainWallMullionsTypeCollector = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(MullionType))
|
||
.OfCategory(BuiltInCategory.OST_CurtainWallMullions)
|
||
.Cast<MullionType>()
|
||
.ToList();
|
||
|
||
CurtainSystemType curtainSystemType = null;
|
||
PanelType panelType = null;
|
||
MullionType mullionType = null;
|
||
|
||
var curtainSystemTypeName = $"铺砖-{length}mm x {width}mm";
|
||
var panelTypeName = panelName;
|
||
var mullionTypeName = $"{gap}mm x {thickness}mm";
|
||
|
||
//创建嵌板类型
|
||
try
|
||
{
|
||
var defaultPanelType = panelTypeCollector.FirstOrDefault();
|
||
panelType = defaultPanelType.Duplicate(panelTypeName) as PanelType;
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.ArgumentException)
|
||
{
|
||
foreach (var t in panelTypeCollector)
|
||
{
|
||
if (t.Name == panelTypeName)
|
||
{
|
||
panelType = t;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
panelType?.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_THICKNESS).Set(thickness / 304.8);
|
||
//嵌板偏移
|
||
panelType?.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_OFFSET).Set(0);
|
||
//创建竖挺类型
|
||
try
|
||
{
|
||
var defaultMullionType = curtainWallMullionsTypeCollector.FirstOrDefault(
|
||
m => m.FamilyName.Contains("矩形") || m.FamilyName.Contains("Rectangular")
|
||
);
|
||
mullionType = defaultMullionType.Duplicate(mullionTypeName) as MullionType;
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.ArgumentException)
|
||
{
|
||
foreach (var t in curtainWallMullionsTypeCollector)
|
||
{
|
||
if (t.Name == mullionTypeName)
|
||
{
|
||
mullionType = t;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//设置参数
|
||
|
||
mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_WIDTH1).Set(gap / 304.8 / 2);
|
||
mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_WIDTH2).Set(gap / 304.8 / 2);
|
||
mullionType?.get_Parameter(BuiltInParameter.RECT_MULLION_THICK).Set(thickness / 304.8);
|
||
|
||
//创建幕墙系统类型
|
||
try
|
||
{
|
||
var defaultCurtainSystemType = curtainSystemTypeCollector.FirstOrDefault();
|
||
curtainSystemType = defaultCurtainSystemType.Duplicate(curtainSystemTypeName) as CurtainSystemType;
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.ArgumentException)
|
||
{
|
||
foreach (var t in curtainSystemTypeCollector)
|
||
{
|
||
if (t.Name == curtainSystemTypeName)
|
||
{
|
||
curtainSystemType = t;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//mullionType.get_Parameter(BuiltInParameter.MULLION_OFFSET).Set(0);
|
||
//mullionType.get_Parameter(BuiltInParameter.MULLION_OFFSET).Set(thickness / 304.8 );
|
||
|
||
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LAYOUT_1).Set(1);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LAYOUT_2).Set(1);
|
||
|
||
//panelType.get_Parameter(BuiltInParameter.CURTAIN_WALL_SYSPANEL_OFFSET).Set(-thickness / 304.8 / 2);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LENGTH_1).Set((width + gap) / 304.8);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.SPACING_LENGTH_2).Set((length + gap) / 304.8);
|
||
if (mullionType != null && panelType != null)
|
||
{
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_PANEL).Set(panelType.Id);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_MULLION_INTERIOR_GRID1).Set(mullionType.Id);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.AUTO_MULLION_INTERIOR_GRID2).Set(mullionType.Id);
|
||
}
|
||
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.CURTAINGRID_ADJUST_BORDER_1).Set(1);
|
||
curtainSystemType?.get_Parameter(BuiltInParameter.CURTAINGRID_ADJUST_BORDER_2).Set(1);
|
||
//curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER1_GRID1).Set(mullionType.ViewId);
|
||
//curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER1_GRID2).Set(mullionType.ViewId);
|
||
//curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER2_GRID1).Set(mullionType.ViewId);
|
||
//curtainSystemType.get_Parameter(BuiltInParameter.AUTO_MULLION_BORDER2_GRID2).Set(mullionType.ViewId);
|
||
return curtainSystemType;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取偏移量
|
||
/// </summary>
|
||
/// <param name="coord">UV平面坐标系</param>
|
||
/// <param name="start">拾取的起铺点</param>
|
||
/// <returns></returns>
|
||
private static double[,] GetOffset(List<XYZ> coord, XYZ start)
|
||
{
|
||
var origin = coord[0];
|
||
//var insterIntersectionResult = line.ProjectOf(origin);
|
||
//var project = insterIntersectionResult?.XYZPoint;
|
||
//var dis = insterIntersectionResult?.DistanceX;
|
||
//var uDirection = XYZ.Zero;
|
||
//var vDirection = XYZ.Zero;
|
||
//bool lineIsU = false;
|
||
double uoffest;
|
||
double voffest;
|
||
var p = start - origin;
|
||
//u轴进行的偏移实际是v轴沿着u轴的偏移值,故应相反设置偏移值
|
||
//因为轴的模长度为1,所以直接等于p在轴上的投影长度
|
||
uoffest = p.DotProduct(coord[1]);
|
||
//if (coord[1].CrossProduct(p).Z < 0)
|
||
//{
|
||
// uoffest = -uoffest;
|
||
//}
|
||
voffest = p.DotProduct(coord[2]);
|
||
//if (coord[2].CrossProduct(p).Z < 0)
|
||
//{
|
||
// voffest = -voffest;
|
||
//}
|
||
//if (coord[1].CrossProduct(line.Direction).IsAlmostEqualTo(XYZ.Zero))
|
||
//{
|
||
// uoffest = coord[1].DotProduct(p) * coord[1];
|
||
// voffest = coord[2].DotProduct(p) * coord[2];
|
||
// ////得到起铺点相对幕墙系统原点的偏移量
|
||
// //double offest = default;
|
||
// //if ((start - origin).Normalize().IsAlmostEqualTo(coord[1]))
|
||
// //{
|
||
// // offest = (start - origin).GetLength();
|
||
// //}
|
||
// //else
|
||
// //{
|
||
// // offest = -(start - origin).GetLength();
|
||
// //}
|
||
// //result.Add(coord[1], offest);//u
|
||
// //if ((project - origin).Normalize().IsAlmostEqualTo(coord[2]))
|
||
// //{
|
||
// // offest = (project - origin).GetLength();
|
||
// //}
|
||
// //else
|
||
// //{
|
||
// // offest = -(project - origin).GetLength();
|
||
// //}
|
||
// //result.Add(coord[2], offest);//v
|
||
//}
|
||
//else if (coord[2].CrossProduct(line.Direction).IsAlmostEqualTo(XYZ.Zero))
|
||
//{
|
||
// isInvert = true;
|
||
// uoffest = coord[2].DotProduct(p) * coord[2];
|
||
// voffest = coord[1].DotProduct(p) * coord[1];
|
||
// //double offest = default;
|
||
// //if ((project - origin).Normalize().IsAlmostEqualTo(coord[1]))
|
||
// //{
|
||
// // offest = (project - origin).GetLength();
|
||
// //}
|
||
// //else
|
||
// //{
|
||
// // offest = -(project - origin).GetLength();
|
||
// //}
|
||
// //result.Add(coord[1], offest);//v
|
||
|
||
|
||
// //if ((start - origin).DotProduct(coord[1]) > 0)
|
||
// //{
|
||
// // offest = (start - origin).GetLength();
|
||
// //}
|
||
// //else
|
||
// //{
|
||
// // offest = -(start - origin).GetLength();
|
||
// //}
|
||
// //result.Add(coord[1], offest);//v
|
||
//}
|
||
////if (project != null)
|
||
////{
|
||
//// var offset = project.DistanceTo(start);
|
||
//// //判断正方向还是反方向
|
||
//// if ((start - project).Normalize().IsAlmostEqualTo(-coord[1]))
|
||
//// {
|
||
//// offset = -offset;
|
||
//// }
|
||
//// //var direction = XYZ.BasisZ.CrossProduct(pl.FaceNormal);
|
||
|
||
//// //if (direction.IsAlmostEqualTo(line.Direction))
|
||
//// //{
|
||
//// // offset = xyz.DistanceTo(startPoint) * 304.8;
|
||
//// //}
|
||
//// //else
|
||
//// //{
|
||
//// // offset = xyz.DistanceTo(endPoint) * 304.8;
|
||
//// //}
|
||
//// //offset = x;
|
||
//// var n = Math.Floor(offset / interval);
|
||
//// offset -= Math.Floor(n) * interval;
|
||
//// return offset;
|
||
////}
|
||
//if (voffest == null || uoffest == null)
|
||
//{
|
||
// return null;
|
||
//}
|
||
return new[,]
|
||
{
|
||
{ uoffest, voffest }
|
||
};
|
||
}
|
||
|
||
private static FaceArray GetFaceArray(Document doc, List<CurveLoop> curveLoops, out DirectShape ds)
|
||
{
|
||
FaceArray array = new();
|
||
|
||
var solid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoops, -XYZ.BasisZ, 10.0);
|
||
ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_Mass));
|
||
|
||
ds?.AppendShape(new List<GeometryObject> { solid });
|
||
|
||
foreach (Face face in solid.Faces)
|
||
{
|
||
var pf = face as PlanarFace;
|
||
if (pf.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ))
|
||
{
|
||
array.Append(face);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return array;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取最终幕墙系统坐标
|
||
/// </summary>
|
||
/// <param name="doc"></param>
|
||
/// <param name="array"></param>
|
||
/// <param name="line"></param>
|
||
/// <param name="rotation"></param>
|
||
/// <returns></returns>
|
||
private static List<XYZ> GetCoordinateSystem(Document doc, FaceArray array, Line line, out Rotation rotation)
|
||
{
|
||
var curtainSystemTypeCollector = new FilteredElementCollector(doc)
|
||
.OfClass(typeof(CurtainSystemType))
|
||
.OfCategory(BuiltInCategory.OST_CurtaSystem);
|
||
XYZ origin = null;
|
||
XYZ u = null;
|
||
XYZ v = null;
|
||
rotation = null;
|
||
using (Transaction trans = new(doc, "获取坐标系"))
|
||
{
|
||
trans.Start();
|
||
if (curtainSystemTypeCollector.FirstOrDefault() is CurtainSystemType defaultCurtainSystemType)
|
||
{
|
||
defaultCurtainSystemType.get_Parameter(BuiltInParameter.SPACING_LAYOUT_1).Set(2);
|
||
defaultCurtainSystemType.get_Parameter(BuiltInParameter.SPACING_LAYOUT_2).Set(2);
|
||
var curtainSystem = doc.Create.NewCurtainSystem(array, defaultCurtainSystemType);
|
||
//编号
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_NUM_DIVISIONS_1).Set(1);
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_NUM_DIVISIONS_2).Set(1);
|
||
//对正
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2);
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2);
|
||
//
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(0);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(0);
|
||
doc.Regenerate();
|
||
origin = GetOrigin(doc, curtainSystem, out u, out v);
|
||
var list = new List<XYZ> { origin, u, v };
|
||
//获取旋转角度
|
||
rotation = GetRotation(list, line);
|
||
//设置旋转角
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(rotation.Radian);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(rotation.Radian);
|
||
//得到转换后的角度
|
||
doc.Regenerate();
|
||
origin = GetOrigin(doc, curtainSystem, out u, out v);
|
||
}
|
||
|
||
trans.RollBack();
|
||
//trans.Commit();
|
||
}
|
||
|
||
return [origin, u, v];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 得到旋转角度
|
||
/// </summary>
|
||
/// <param name="coordSystem"></param>
|
||
/// <param name="line"></param>
|
||
/// <returns></returns>
|
||
private static Rotation GetRotation(List<XYZ> coordSystem, Line line)
|
||
{
|
||
var radian1 = coordSystem[1].AngleTo(line.Direction);
|
||
Rotation rotation1 =
|
||
new()
|
||
{
|
||
Radian = radian1,
|
||
Direction = line.Direction,
|
||
Orientation = Orientation.U,
|
||
CoordSystemAxis = coordSystem[1]
|
||
};
|
||
var radian2 = coordSystem[1].AngleTo(-line.Direction);
|
||
Rotation rotation2 =
|
||
new()
|
||
{
|
||
Radian = radian2,
|
||
Direction = -line.Direction,
|
||
Orientation = Orientation.U,
|
||
CoordSystemAxis = coordSystem[1]
|
||
};
|
||
|
||
var radian3 = coordSystem[2].AngleTo(line.Direction);
|
||
Rotation rotation3 =
|
||
new()
|
||
{
|
||
Radian = radian3,
|
||
Direction = line.Direction,
|
||
Orientation = Orientation.V,
|
||
CoordSystemAxis = coordSystem[2]
|
||
};
|
||
var radian4 = coordSystem[2].AngleTo(-line.Direction);
|
||
Rotation rotation4 =
|
||
new()
|
||
{
|
||
Radian = radian4,
|
||
Direction = -line.Direction,
|
||
Orientation = Orientation.V,
|
||
CoordSystemAxis = coordSystem[2]
|
||
};
|
||
List<Rotation> rotations = [rotation1, rotation2, rotation3, rotation4];
|
||
var rotation = rotations.OrderBy(r => r.Radian).First();
|
||
|
||
if (rotation.CoordSystemAxis.CrossProduct(rotation.Direction).Z < 0)
|
||
{
|
||
rotation.Radian = -rotation.Radian;
|
||
}
|
||
|
||
return rotation;
|
||
//double radian;
|
||
////grid2的轴向单位向量
|
||
////在平面
|
||
//if (pl.FaceNormal.IsAlmostEqualTo(XYZ.BasisZ))
|
||
//{
|
||
|
||
// var perpendicularVector = line.Direction.CrossProduct(XYZ.BasisZ);
|
||
// if (perpendicularVector.Y < 0)
|
||
// {
|
||
// perpendicularVector = -perpendicularVector;
|
||
// }
|
||
|
||
// radian = perpendicularVector.X > 0 ? -perpendicularVector.AngleTo(XYZ.BasisY) : perpendicularVector.AngleTo(XYZ.BasisY);
|
||
|
||
// //angle = radian * 180 / Math.PI;
|
||
|
||
|
||
// if (Math.Abs(Math.Round(radian, MidpointRounding.AwayFromZero) - Math.PI / 2) < 0.0001)
|
||
// {
|
||
// radian = 0;
|
||
// }
|
||
//}
|
||
//else//在垂直面
|
||
//{
|
||
// radian = 0;
|
||
//}
|
||
|
||
//return radian;
|
||
}
|
||
|
||
private static void CreateCurtainSystemByFace(
|
||
UIDocument uidoc,
|
||
double length,
|
||
double width,
|
||
double gap,
|
||
double thickness,
|
||
double wallBaseOffset,
|
||
string panelName,
|
||
bool isEdgeExistGap
|
||
)
|
||
{
|
||
var doc = uidoc.Document;
|
||
var faceReference = uidoc.Selection.PickObject(ObjectType.Face, "请选择铺贴的面");
|
||
var element = doc.GetElement(faceReference);
|
||
double baseHeight = default;
|
||
double height = default;
|
||
doc.InvokeGroup(
|
||
tg =>
|
||
{
|
||
if (element is Wall)
|
||
{
|
||
doc.Invoke(
|
||
ts =>
|
||
{
|
||
//顶部约束
|
||
var topConstraint = element.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
|
||
if (topConstraint == ElementId.InvalidElementId) //未连接
|
||
{
|
||
//无连接高度
|
||
height = element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).AsDouble();
|
||
element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).Set(height - (wallBaseOffset / 304.8));
|
||
}
|
||
|
||
baseHeight = element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).AsDouble();
|
||
element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(baseHeight + (wallBaseOffset / 304.8));
|
||
},
|
||
"设置墙底部高度"
|
||
);
|
||
}
|
||
|
||
var face = element.GetGeometryObjectFromReference(faceReference) as Face;
|
||
var pl = face as PlanarFace;
|
||
if (pl == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
double radian = 0;
|
||
double actualU = 0;
|
||
double actualV = 0;
|
||
FaceArray array = new();
|
||
array.Append(face);
|
||
|
||
var referEdge = uidoc.Selection.PickObject(ObjectType.Edge, new EdgeFilter(element), "请选择对齐的边");
|
||
var xyz = uidoc.Selection.PickPoint(
|
||
ObjectSnapTypes.Intersections
|
||
| ObjectSnapTypes.Endpoints
|
||
| ObjectSnapTypes.Centers
|
||
| ObjectSnapTypes.Midpoints
|
||
| ObjectSnapTypes.Points
|
||
| ObjectSnapTypes.Nearest
|
||
| ObjectSnapTypes.Perpendicular
|
||
| ObjectSnapTypes.WorkPlaneGrid
|
||
| ObjectSnapTypes.Quadrants
|
||
| ObjectSnapTypes.Tangents,
|
||
"请选择起铺点"
|
||
);
|
||
var edgeObj = element.GetGeometryObjectFromReference(referEdge) as Edge;
|
||
//var ourterEdgeArray = face.EdgeLoops.get_Item(0);
|
||
|
||
|
||
if (edgeObj != null && edgeObj.AsCurve() is Line)
|
||
{
|
||
var line = edgeObj.AsCurve() as Line;
|
||
var coordinateSystem = GetCoordinateSystem(doc, array, line, out var rotation);
|
||
var startPoint = line!.GetEndPoint(0);
|
||
var endPoint = line.GetEndPoint(1);
|
||
var start = line.Project(xyz).XYZPoint;
|
||
var totalLength = start.DistanceTo(startPoint) + start.DistanceTo(endPoint);
|
||
//判断点是否在直线上
|
||
if (totalLength - line.Length > 0.0001)
|
||
{
|
||
MessageBox.Show("选择点不在对齐的边上", "错误");
|
||
return;
|
||
}
|
||
|
||
radian = rotation.Radian;
|
||
var uv = GetOffset(coordinateSystem, start);
|
||
|
||
if (uv != null)
|
||
{
|
||
//原始起铺点基于幕墙系统原点平面uv偏移量
|
||
var intervalU = (length + gap) / 304.8;
|
||
var intervalV = (width + gap) / 304.8;
|
||
var n = Math.Floor(uv[0, 0] / intervalU);
|
||
var m = Math.Floor(uv[0, 1] / intervalV);
|
||
|
||
if (isEdgeExistGap)
|
||
{
|
||
actualU = uv[0, 0] - (n * intervalU);
|
||
actualV = uv[0, 1] - (m * intervalV);
|
||
}
|
||
else
|
||
{
|
||
actualU = uv[0, 0] - (n * intervalU) - (gap / 2 / 304.8);
|
||
actualV = uv[0, 1] - (m * intervalV) - (gap / 2 / 304.8);
|
||
}
|
||
}
|
||
}
|
||
|
||
CurtainSystem curtainSystem = null;
|
||
//doc.Regenerate();
|
||
doc.Invoke(
|
||
_ =>
|
||
{
|
||
var curtainSystemType = SetCurtainSystemType(doc, length, width, gap, thickness, panelName);
|
||
curtainSystem = doc.Create.NewCurtainSystem(array, curtainSystemType);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(radian);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(radian);
|
||
doc.Regenerate();
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(actualU);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(actualV);
|
||
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2);
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2);
|
||
|
||
ElementTransformUtils.MoveElement(doc, curtainSystem.Id, pl.FaceNormal * thickness / 304.8 / 2);
|
||
},
|
||
"创建幕墙系统"
|
||
);
|
||
if (element is Wall)
|
||
{
|
||
doc.Invoke(
|
||
_ =>
|
||
{
|
||
element.get_Parameter(BuiltInParameter.WALL_BASE_OFFSET).Set(baseHeight);
|
||
var topConstraint = element.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
|
||
if (topConstraint == ElementId.InvalidElementId) //未连接
|
||
{
|
||
//无连接高度
|
||
element.get_Parameter(BuiltInParameter.WALL_USER_HEIGHT_PARAM).Set(height);
|
||
}
|
||
},
|
||
"设置墙偏移"
|
||
);
|
||
}
|
||
|
||
if (curtainSystem != null)
|
||
{
|
||
doc.Invoke(_ =>
|
||
{
|
||
var iterator = curtainSystem.CurtainGrids.ForwardIterator();
|
||
iterator.MoveNext();
|
||
var grid = iterator.Current as CurtainGrid;
|
||
var panels = grid!.GetPanelIds().Select(id => doc.GetElement(id) as Panel);
|
||
var area = width / 304.8 * length / 304.8;
|
||
var errorPanels =
|
||
from panel in panels
|
||
where panel!.get_Parameter(BuiltInParameter.HOST_AREA_COMPUTED).AsDouble() < area / 4
|
||
select panel;
|
||
foreach (var panel in errorPanels)
|
||
{
|
||
var overrideGraphicSettings = doc.ActiveView.GetElementOverrides(panel.Id);
|
||
overrideGraphicSettings.SetProjectionLineColor(new Color(255, 0, 0));
|
||
//在当前视图下设置,其它视图保持原来的
|
||
doc.ActiveView.SetElementOverrides(panel.Id, overrideGraphicSettings);
|
||
doc.Regenerate();
|
||
}
|
||
});
|
||
}
|
||
},
|
||
"创建饰面"
|
||
);
|
||
//CreateCurtainSystem(length, width, gap, thickness, angle, offset, doc, curveLoops, pl.FaceNormal);
|
||
|
||
|
||
//var xyz = referEdge.GlobalPoint;
|
||
|
||
//if (angle > Math.PI / 2)
|
||
//{
|
||
// angle -= Math.PI;
|
||
// if (perpendicularVector.Y>0)
|
||
// {
|
||
// angle -= Math.PI / 2 ;
|
||
// }
|
||
// else
|
||
// {
|
||
// angle = Math.PI / 2 - angle;
|
||
// }
|
||
//}
|
||
}
|
||
|
||
private static void CreateCurtainSystemByRoom(UIDocument uidoc, double length, double width, double gap, double thickness, string panelName)
|
||
{
|
||
var doc = uidoc.Document;
|
||
|
||
var rooms = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rooms);
|
||
if (!rooms.Any())
|
||
{
|
||
MessageBox.Show("项目中当前没有房间", "提示", MessageBoxButton.OK, MessageBoxImage.Stop);
|
||
return;
|
||
}
|
||
|
||
var refer = uidoc.Selection.PickObject(ObjectType.Element, new GenericFilter<Room>(), "请选择铺贴的房间");
|
||
var room = doc.GetElement(refer) as Room;
|
||
List<CurveLoop> curveLoops = [];
|
||
var opts = new SpatialElementBoundaryOptions();
|
||
var segmentsList = room!.GetBoundarySegments(opts);
|
||
if (segmentsList != null)
|
||
{
|
||
foreach (var boundarySegments in segmentsList)
|
||
{
|
||
CurveLoop curveLoop = new();
|
||
|
||
foreach (var boundarySegment in boundarySegments)
|
||
{
|
||
curveLoop.Append(boundarySegment.GetCurve());
|
||
}
|
||
|
||
curveLoops.Add(curveLoop);
|
||
}
|
||
}
|
||
|
||
doc.Invoke(
|
||
_ =>
|
||
{
|
||
//double angle = 0;
|
||
var array = GetFaceArray(doc, curveLoops, out var ds);
|
||
var curtainSystemType = SetCurtainSystemType(doc, length, width, gap, thickness, panelName);
|
||
|
||
var curtainSystem = doc.Create.NewCurtainSystem(array, curtainSystemType);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_1).Set(0);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ANGLE_2).Set(0);
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_1).Set(2);
|
||
curtainSystem.get_Parameter(BuiltInParameter.SPACING_JUSTIFICATION_2).Set(2);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_1).Set(0);
|
||
curtainSystem.get_Parameter(BuiltInParameter.CURTAINGRID_ORIGIN_2).Set(0);
|
||
if (ds != null)
|
||
{
|
||
doc.Delete(ds.Id);
|
||
}
|
||
|
||
ElementTransformUtils.MoveElement(doc, curtainSystem.Id, XYZ.BasisZ * thickness / 304.8 / 2);
|
||
},
|
||
"创建铺贴饰面"
|
||
);
|
||
//CreateCurtainSystem(length, width, gap, thickness, angle, offset, doc, curveLoops, XYZ.BasisZ);
|
||
}
|
||
|
||
[RelayCommand]
|
||
private void PlaceBricks()
|
||
{
|
||
finishesHandler.Raise(uiapp =>
|
||
{
|
||
var uidoc = uiapp.ActiveUIDocument;
|
||
try
|
||
{
|
||
if (ByRoom)
|
||
{
|
||
CreateCurtainSystemByRoom(uidoc, PavementLength, PavementWidth, PavementGap, PavementThickness, PanelName);
|
||
}
|
||
else
|
||
{
|
||
CreateCurtainSystemByFace(
|
||
uidoc,
|
||
PavementLength,
|
||
PavementWidth,
|
||
PavementGap,
|
||
PavementThickness,
|
||
WallBaseOffset,
|
||
PanelName,
|
||
IsEdgeExistGap
|
||
);
|
||
}
|
||
}
|
||
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { }
|
||
});
|
||
}
|
||
|
||
private static XYZ GetOrigin(Document doc, CurtainSystem curtainSystem, out XYZ u, out XYZ v)
|
||
{
|
||
XYZ origin = null;
|
||
var iterator = curtainSystem.CurtainGrids.ForwardIterator();
|
||
iterator.MoveNext();
|
||
var grid = iterator.Current as CurtainGrid;
|
||
var uLineId = grid.GetUGridLineIds().FirstOrDefault();
|
||
var vLineId = grid.GetVGridLineIds().FirstOrDefault();
|
||
var uLine = doc.GetElement(uLineId) as CurtainGridLine;
|
||
var vLine = doc.GetElement(vLineId) as CurtainGridLine;
|
||
var l1 = uLine.FullCurve as Line;
|
||
u = l1.Direction;
|
||
var l2 = vLine.FullCurve as Line;
|
||
v = l2.Direction;
|
||
var result = l1.Intersect(l2, out var resultArray);
|
||
if (result != SetComparisonResult.Disjoint)
|
||
{
|
||
if (!resultArray.IsEmpty)
|
||
{
|
||
origin = resultArray.get_Item(0).XYZPoint;
|
||
}
|
||
}
|
||
|
||
return origin;
|
||
}
|
||
}
|
||
|
||
public class EdgeFilter : ISelectionFilter
|
||
{
|
||
public EdgeFilter(Element preElement)
|
||
{
|
||
element = preElement;
|
||
}
|
||
|
||
private readonly Element element;
|
||
|
||
public bool AllowElement(Element elem)
|
||
{
|
||
return element.Id == elem.Id;
|
||
}
|
||
|
||
public bool AllowReference(Reference reference, XYZ position)
|
||
{
|
||
return true;
|
||
}
|
||
}
|