mirror of
https://github.com/jeremytammik/RevitSdkSamples.git
synced 2026-08-06 05:01:35 +00:00
369 lines
13 KiB
C#
369 lines
13 KiB
C#
//
|
|
// (C) Copyright 2003-2023 by Autodesk, Inc.
|
|
//
|
|
// Permission to use, copy, modify, and distribute this software in
|
|
// object code form for any purpose and without fee is hereby granted,
|
|
// provided that the above copyright notice appears in all copies and
|
|
// that both that copyright notice and the limited warranty and
|
|
// restricted rights notice below appear in all supporting
|
|
// documentation.
|
|
//
|
|
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
|
|
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
|
|
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
|
|
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
|
|
// UNINTERRUPTED OR ERROR FREE.
|
|
//
|
|
// Use, duplication, or disclosure by the U.S. Government is subject to
|
|
// restrictions set forth in FAR 52.227-19 (Commercial Computer
|
|
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
|
|
// (Rights in Technical Data and Computer Software), as applicable.
|
|
//
|
|
namespace Revit.SDK.Samples.CreateComplexAreaRein.CS
|
|
{
|
|
using System;
|
|
using System.Collections.Generic;
|
|
|
|
using Autodesk.Revit.DB;
|
|
|
|
using GeoElement = Autodesk.Revit.DB.GeometryElement;
|
|
using GeoSolid = Autodesk.Revit.DB.Solid;
|
|
using Element = Autodesk.Revit.DB.Element;
|
|
|
|
|
|
/// <summary>
|
|
/// provide some common geometry judgement and calculate method
|
|
/// </summary>
|
|
class GeomUtil
|
|
{
|
|
const double PRECISION = 0.00001; //precision when judge whether two doubles are equal
|
|
|
|
/// <summary>
|
|
/// get all faces that compose the geometry solid of given element
|
|
/// </summary>
|
|
/// <param name="elem">element to be calculated</param>
|
|
/// <returns>all faces</returns>
|
|
public static FaceArray GetFaces(Element elem)
|
|
{
|
|
List<Face> faces = new List<Face>();
|
|
|
|
Autodesk.Revit.DB.Options geoOptions = Command.CommandData.Application.Application.Create.NewGeometryOptions();
|
|
geoOptions.ComputeReferences = true;
|
|
|
|
GeoElement geoElem = elem.get_Geometry(geoOptions);
|
|
//GeometryObjectArray geoElems = geoElem.Objects;
|
|
IEnumerator<GeometryObject> Objects = geoElem.GetEnumerator();
|
|
//foreach (object o in geoElems)
|
|
while (Objects.MoveNext())
|
|
{
|
|
object o = Objects.Current;
|
|
|
|
GeoSolid geoSolid = o as GeoSolid;
|
|
if (null == geoSolid)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
return geoSolid.Faces;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// get all points proximate to the given face
|
|
/// </summary>
|
|
/// <param name="face">face to be calculated</param>
|
|
/// <returns></returns>
|
|
public static List<Autodesk.Revit.DB.XYZ> GetPoints(Face face)
|
|
{
|
|
List<Autodesk.Revit.DB.XYZ> points = new List<Autodesk.Revit.DB.XYZ>();
|
|
List<Autodesk.Revit.DB.XYZ> XYZs = face.Triangulate().Vertices as List<Autodesk.Revit.DB.XYZ>;
|
|
|
|
|
|
|
|
foreach (Autodesk.Revit.DB.XYZ point in XYZs)
|
|
{
|
|
points.Add(point);
|
|
}
|
|
|
|
return points;
|
|
}
|
|
|
|
/// <summary>
|
|
/// judge whether the given face is horizontal
|
|
/// </summary>
|
|
/// <param name="face">face to be judged</param>
|
|
/// <returns>is horizontal</returns>
|
|
public static bool IsHorizontalFace(Face face)
|
|
{
|
|
List<Autodesk.Revit.DB.XYZ> points = GetPoints(face);
|
|
double z1 = points[0].Z;
|
|
double z2 = points[1].Z;
|
|
double z3 = points[2].Z;
|
|
double z4 = points[3].Z;
|
|
bool flag = IsEqual(z1, z2);
|
|
flag = flag && IsEqual(z2, z3);
|
|
flag = flag && IsEqual(z3, z4);
|
|
flag = flag && IsEqual(z4, z1);
|
|
|
|
return flag;
|
|
}
|
|
|
|
/// <summary>
|
|
/// judge whether a face and a line are parallel
|
|
/// </summary>
|
|
/// <param name="face"></param>
|
|
/// <param name="line"></param>
|
|
/// <returns></returns>
|
|
public static bool IsParallel(Face face, Line line)
|
|
{
|
|
List<Autodesk.Revit.DB.XYZ> points = GetPoints(face);
|
|
Autodesk.Revit.DB.XYZ vector1 = SubXYZ(points[0], points[1]);
|
|
Autodesk.Revit.DB.XYZ vector2 = SubXYZ(points[1], points[2]);
|
|
Autodesk.Revit.DB.XYZ refer = SubXYZ(line.GetEndPoint(0), line.GetEndPoint(1));
|
|
|
|
Autodesk.Revit.DB.XYZ cross = CrossMatrix(vector1, vector2);
|
|
double result = DotMatrix(cross, refer);
|
|
|
|
if (result < PRECISION)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// judge whether given 4 lines can form a rectangular
|
|
/// </summary>
|
|
/// <param name="lines"></param>
|
|
/// <returns>is rectangular</returns>
|
|
public static bool IsRectangular(IList<Curve> curves)
|
|
{
|
|
//make sure the CurveArray contains 4 line
|
|
if (curves.Count != 4)
|
|
{
|
|
return false;
|
|
}
|
|
Line[] lines = new Line[4];
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
lines[i] = curves[i] as Line;
|
|
if (null == lines[i])
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//make sure the first line is vertical to 2 lines and parallel to another line
|
|
Line iniLine = lines[0];
|
|
Line[] verticalLines = new Line[2];
|
|
Line paraLine = null;
|
|
int index = 0;
|
|
for (int i = 1; i < 4; i++)
|
|
{
|
|
if (IsVertical(lines[0], lines[i]))
|
|
{
|
|
verticalLines[index] = lines[i];
|
|
index++;
|
|
}
|
|
else
|
|
{
|
|
paraLine = lines[i];
|
|
}
|
|
}
|
|
if (index != 2)
|
|
{
|
|
return false;
|
|
}
|
|
bool flag = IsVertical(paraLine, verticalLines[0]);
|
|
return flag;
|
|
}
|
|
|
|
/// <summary>
|
|
/// get the length of the given line
|
|
/// </summary>
|
|
/// <param name="line"></param>
|
|
/// <returns>length</returns>
|
|
public static double GetLength(Line line)
|
|
{
|
|
Autodesk.Revit.DB.XYZ sub = SubXYZ(line.GetEndPoint(0), line.GetEndPoint(1));
|
|
double length = Math.Sqrt(sub.X * sub.X + sub.Y * sub.Y + sub.Z * sub.Z);
|
|
return length;
|
|
}
|
|
|
|
/// <summary>
|
|
/// get parallel line with give distance with given line in XY plane
|
|
/// </summary>
|
|
/// <param name="inLine">given line</param>
|
|
/// <param name="distance">distance from given line</param>
|
|
/// <returns>paralleled line</returns>
|
|
public static Line GetXYParallelLine(Line inLine, double distance)
|
|
{
|
|
Autodesk.Revit.DB.XYZ direct = SubXYZ(inLine.GetEndPoint(1), inLine.GetEndPoint(0));
|
|
double length = Math.Sqrt((-direct.Y) * (-direct.Y) + direct.X * direct.X);
|
|
double temp = distance / length;
|
|
|
|
Autodesk.Revit.DB.XYZ dPerp = new XYZ(-direct.Y * temp,
|
|
direct.X * temp, 0.0);
|
|
|
|
Autodesk.Revit.DB.XYZ startPoint = AddXYZ(inLine.GetEndPoint(0), dPerp);
|
|
Autodesk.Revit.DB.XYZ endPoint = AddXYZ(inLine.GetEndPoint(1), dPerp);
|
|
Line outLine = Line.CreateBound(startPoint, endPoint);
|
|
//Line outLine = new Line(ref startPoint, ref endPoint);
|
|
|
|
return outLine;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get scaled line which has both the same center and direction with give line
|
|
/// </summary>
|
|
/// <param name="inLine">given line</param>
|
|
/// <param name="scale">scale value</param>
|
|
/// <returns>scaled line</returns>
|
|
public static Line GetScaledLine(Line inLine, double scale)
|
|
{
|
|
Autodesk.Revit.DB.XYZ startPoint = inLine.GetEndPoint(0);
|
|
Autodesk.Revit.DB.XYZ endPoint = inLine.GetEndPoint(1);
|
|
|
|
Autodesk.Revit.DB.XYZ temp1 = SubXYZ(endPoint, startPoint);
|
|
Autodesk.Revit.DB.XYZ temp2 = MultiXYZ(temp1, (scale - 1) / 2);
|
|
Autodesk.Revit.DB.XYZ startPoint2 = SubXYZ(startPoint, temp2);
|
|
Autodesk.Revit.DB.XYZ endPoint2 = AddXYZ(endPoint, temp2);
|
|
|
|
Line outLine = Line.CreateBound(startPoint2, endPoint2);
|
|
//Line outLine = new Line(ref startPoint2, ref endPoint2);
|
|
return outLine;
|
|
}
|
|
|
|
/// <summary>
|
|
/// judge whether two lines are vertical
|
|
/// </summary>
|
|
/// <param name="line1"></param>
|
|
/// <param name="line2"></param>
|
|
/// <returns></returns>
|
|
private static bool IsVertical(Line line1, Line line2)
|
|
{
|
|
Autodesk.Revit.DB.XYZ vector1 = SubXYZ(line1.GetEndPoint(0), line1.GetEndPoint(1));
|
|
Autodesk.Revit.DB.XYZ vector2 = SubXYZ(line2.GetEndPoint(0), line2.GetEndPoint(1));
|
|
|
|
double result = DotMatrix(vector1, vector2);
|
|
|
|
if (Math.Abs(result) < PRECISION)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// subtraction of two Autodesk.Revit.DB.XYZ as Matrix
|
|
/// </summary>
|
|
/// <param name="p1"></param>
|
|
/// <param name="p2"></param>
|
|
/// <returns></returns>
|
|
private static Autodesk.Revit.DB.XYZ SubXYZ(Autodesk.Revit.DB.XYZ p1, Autodesk.Revit.DB.XYZ p2)
|
|
{
|
|
double x = p1.X - p2.X;
|
|
double y = p1.Y - p2.Y;
|
|
double z = p1.Z - p2.Z;
|
|
|
|
Autodesk.Revit.DB.XYZ result = new Autodesk.Revit.DB.XYZ(x, y, z);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// add two XYZ
|
|
/// </summary>
|
|
/// <param name="p1"></param>
|
|
/// <param name="p2"></param>
|
|
/// <returns></returns>
|
|
private static Autodesk.Revit.DB.XYZ AddXYZ(Autodesk.Revit.DB.XYZ p1, Autodesk.Revit.DB.XYZ p2)
|
|
{
|
|
double x = p1.X + p2.X;
|
|
double y = p1.Y + p2.Y;
|
|
double z = p1.Z + p2.Z;
|
|
|
|
Autodesk.Revit.DB.XYZ result = new Autodesk.Revit.DB.XYZ(x, y, z);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// multiply Autodesk.Revit.DB.XYZ with a double
|
|
/// </summary>
|
|
/// <param name="p1"></param>
|
|
/// <param name="para"></param>
|
|
/// <returns></returns>
|
|
private static Autodesk.Revit.DB.XYZ MultiXYZ(Autodesk.Revit.DB.XYZ p1, double para)
|
|
{
|
|
double x = p1.X * para;
|
|
double y = p1.Y * para;
|
|
double z = p1.Z * para;
|
|
|
|
Autodesk.Revit.DB.XYZ result = new Autodesk.Revit.DB.XYZ(x, y, z);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// multiplication cross of two Autodesk.Revit.DB.XYZ as Matrix
|
|
/// </summary>
|
|
/// <param name="p1"></param>
|
|
/// <param name="p2"></param>
|
|
/// <returns></returns>
|
|
private static Autodesk.Revit.DB.XYZ CrossMatrix(Autodesk.Revit.DB.XYZ p1, Autodesk.Revit.DB.XYZ p2)
|
|
{
|
|
double v1 = p1.X;
|
|
double v2 = p1.Y;
|
|
double v3 = p1.Z;
|
|
|
|
double u1 = p2.X;
|
|
double u2 = p2.Y;
|
|
double u3 = p2.Z;
|
|
|
|
double x = v3 * u2 - v2 * u3;
|
|
double y = -v3 * u1 + v1 * u3;
|
|
double z = v2 * u1 - v1 * u2;
|
|
|
|
Autodesk.Revit.DB.XYZ point = new Autodesk.Revit.DB.XYZ(x, y, z);
|
|
return point;
|
|
}
|
|
|
|
/// <summary>
|
|
/// dot product of two Autodesk.Revit.DB.XYZ as Matrix
|
|
/// </summary>
|
|
/// <param name="p1"></param>
|
|
/// <param name="p2"></param>
|
|
/// <returns></returns>
|
|
private static double DotMatrix(Autodesk.Revit.DB.XYZ p1, Autodesk.Revit.DB.XYZ p2)
|
|
{
|
|
double v1 = p1.X;
|
|
double v2 = p1.Y;
|
|
double v3 = p1.Z;
|
|
|
|
double u1 = p2.X;
|
|
double u2 = p2.Y;
|
|
double u3 = p2.Z;
|
|
|
|
double result = v1 * u1 + v2 * u2 + v3 * u3;
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// judge whether the subtraction of two doubles is less than the internal decided precision
|
|
/// </summary>
|
|
/// <param name="d1"></param>
|
|
/// <param name="d2"></param>
|
|
/// <returns></returns>
|
|
private static bool IsEqual(double d1, double d2)
|
|
{
|
|
double diff = Math.Abs(d1 - d2);
|
|
if (diff < PRECISION)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
}
|