Vector m_startPnt; //start point #endregion Fields #region Constructors /// <summary> /// The default constructor /// </summary> public Line3D() { m_startPnt = new Vector(0.0, 0.0, 0.0); m_endPnt = new Vector(1.0, 0.0, 0.0); m_length = 1.0; m_normal = new Vector(1.0, 0.0, 0.0); }
/// <summary> /// constructor, /// get a user coordinate system /// </summary> /// <param name="origin">origin of user coordinate system</param> /// <param name="xAxis">xAxis of user coordinate system</param> /// <param name="yAxis">yAxis of user coordinate system</param> /// <param name="flag">select left handness or right handness</param> public UCS(Vector origin, Vector xAxis, Vector yAxis, bool flag) { Vector x2 = xAxis / ~xAxis; Vector y2 = yAxis / ~yAxis; Vector z2 = x2 & y2; if (~z2 < double.Epsilon) { throw new InvalidOperationException(); } if (!flag) { z2 = -z2; } m_origin = origin; m_xAxis = x2; m_yAxis = y2; m_zAxis = z2; }
/// <summary> /// calculate EndPoint by StartPoint, Length and Direction /// </summary> private void CalculateEndPoint() { m_endPnt = m_startPnt + m_normal * m_length; }
/// <summary> /// calculate Direction by StartPoint and EndPoint /// </summary> private void CalculateDirection() { CalculateLength(); m_normal = (m_endPnt - m_startPnt) / m_length; }
/// <summary> /// get line from List<XYZ>(points) and add line to m_lines list /// </summary> /// <param name="points">a List<XYZ> contain points of the Curve</param> private void AddLine(List<XYZ> points) { if (null == points || 0 == points.Count) { return; } Autodesk.Revit.DB.XYZ previousPoint; previousPoint = points[0]; for (int i = 1; i < points.Count; i++) { Autodesk.Revit.DB.XYZ point; point = points[i]; Line3D line = new Line3D(); Vector pointStart = new Vector(); Vector pointEnd = new Vector(); for (int j = 0; j < 3; j++) { pointStart[j] = previousPoint[j]; pointEnd[j] = point[j]; } line.StartPoint = pointStart; line.EndPoint = pointEnd; m_lines.Add(line); previousPoint = point; } }
/// <summary> /// transform 3d point to 2d (if all points in the same plane) /// </summary> private void Frame3DTo2D(ReadOnlyCollection<Line3D> line3Ds) { const double LengthEpsilon = 0.01; const double AngleEpsilon = 0.1; // find 3 points to form 2 lines whose length is bigger than LengthEpsilon // and angle between them should be bigger than AngleEpsilon Line3D line0 = line3Ds[0]; Vector vector0 = new Vector(); Vector vector1 = new Vector(); // to find the first 2 points to form first line int index = 0; for (int i = 1; i < line3Ds.Count; i++) { vector0 = line3Ds[i].StartPoint - line0.StartPoint; if (vector0.GetLength() > LengthEpsilon) { index = i; break; } } if (index == 0) { return; } // to find the last points to form the second line for (int j = index + 1; j < line3Ds.Count; j++) { vector1 = line3Ds[j].StartPoint - line3Ds[index].StartPoint; double angle = Vector.GetAngleOf2Vectors(vector0, vector1, true); if (vector1.GetLength() > LengthEpsilon && angle > AngleEpsilon) { break; } } // find the local coordinate system in which the profile of opening is horizontal Vector zAxis = (vector0 & vector1).GetNormal(); Vector xAxis = zAxis & (new Vector(0.0, 1.0, 0.0)); Vector yAxis = zAxis & xAxis; Vector origin = new Vector(0.0, 0.0, 0.0); UCS ucs = new UCS(origin, xAxis, yAxis); // transform all the 3D lines to UCS and create accordingly 2D lines bool isFirst = true; foreach (Line3D line in line3Ds) { Line3D tmp = ucs.GC2LC(line); PointF startPnt = new PointF((float)tmp.StartPoint.X, (float)tmp.StartPoint.Y); PointF endPnt = new PointF((float)tmp.EndPoint.X, (float)tmp.EndPoint.Y); Line2D line2D = new Line2D(startPnt, endPnt); LineSketch aLineSketch = new LineSketch(line2D); if (isFirst) { m_boundingBox = aLineSketch.BoundingBox; isFirst = false; } else { m_boundingBox = RectangleF.Union(m_boundingBox, aLineSketch.BoundingBox); } m_objects.Add(aLineSketch); } }
/// <summary> /// The default constructor, /// </summary> public UCS(Vector origin, Vector xAxis, Vector yAxis) : this(origin, xAxis, yAxis, true) { }
/// <summary> /// subtraction of two vector /// </summary> /// <param name="lhs">first vector</param> /// <param name="rhs">second vector</param> /// <returns>subtraction of two vector</returns> public static Vector operator -(Vector lhs, Vector rhs) { Vector result = new Vector(lhs); result.X -= rhs.X; result.Y -= rhs.Y; result.Z -= rhs.Z; return result; }
/// <summary> /// Transform global coordinate to local coordinate /// </summary> /// <param name="arg">a vector which need to transform</param> public Vector GC2LC(Vector arg) { Vector result = new Vector(); arg = arg - m_origin; result.X = m_xAxis * arg; result.Y = m_yAxis * arg; result.Z = m_zAxis * arg; return result; }
/// <summary> /// copy constructor /// </summary> public Vector(Vector rhs) { m_x = rhs.X; m_y = rhs.Y; m_z = rhs.Z; }
/// <summary> /// estimate whether two vector are equal /// </summary> /// <param name="lhs">first vector</param> /// <param name="rhs">second vector</param> /// <returns> whether two are equal</returns> private static bool IsEqual(Vector lhs, Vector rhs) { if (lhs.X == rhs.X && lhs.X == rhs.X && lhs.X == rhs.X) { return true; } else { return false; } }
/// <summary> /// get Normal by vector /// </summary> public Vector GetNormal() { Vector direct = new Vector(); double len = GetLength(); direct.X = m_x / len; direct.Y = m_y / len; direct.Z = m_z / len; return direct; }
/// <summary> /// get angle of two vector /// </summary> /// <param name="lhs">first vector</param> /// <param name="rhs">second vector</param> /// <returns> angle of two vector</returns> public static double GetAngleOf2Vectors(Vector lhs, Vector rhs, bool acuteAngleDesired) { double angle = Math.Acos(lhs.GetNormal() * rhs.GetNormal()); if (acuteAngleDesired && angle > Math.PI / 2) { angle = Math.PI - angle; } return angle; }
/// <summary> /// negative of vector /// </summary> /// <param name="lhs">vector</param> /// <returns>negative of vector</returns> public static Vector operator -(Vector lhs) { Vector result = new Vector(lhs); result.X = -lhs.X; result.Y = -lhs.Y; result.Z = -lhs.Z; return result; }
/// <summary> /// Transform local coordinate to global coordinate /// </summary> /// <param name="arg">a vector which need to transform</param> public Vector LC2GC(Vector arg) { Vector result = new Vector(); result.X = arg.X * m_xAxis.X + arg.Y * m_yAxis.X + arg.Z * m_zAxis.X + m_origin.X; result.Y = arg.X * m_xAxis.Y + arg.Y * m_yAxis.Y + arg.Z * m_zAxis.Y + m_origin.Y; result.Z = arg.X * m_xAxis.Z + arg.Y * m_yAxis.Z + arg.Z * m_zAxis.Z + m_origin.Z; return result; }
/// <summary> /// The default constructor /// </summary> /// <param name="startPnt">start point of line</param> /// <param name="endPnt">enn point of line</param> public Line3D(Vector startPnt, Vector endPnt) { m_startPnt = startPnt; m_endPnt = endPnt; CalculateDirection(); }
/// <summary> /// add two vector /// </summary> /// <param name="lhs">first vector</param> /// <param name="rhs">second vector</param> /// <returns>add two vector</returns> public static Vector operator +(Vector lhs, Vector rhs) { Vector result = new Vector(lhs); result.X += rhs.X; result.Y += rhs.Y; result.Z += rhs.Z; return result; }