/// <summary> /// Does this ray intersect with the provided face? /// </summary> /// <param name="face">The Face to intersect with.</param> /// <param name="result">The intersection result.</param> /// <returns>True if an intersection occurs, otherwise false. If true, check the intersection result for the location of the intersection.</returns> internal bool Intersects(Face face, out Vector3 result) { var plane = face.Plane(); if (Intersects(plane, out Vector3 intersection)) { var boundaryPolygon = face.Outer.ToPolygon(); var voids = face.Inner?.Select(v => v.ToPolygon())?.ToList(); var transformToPolygon = new Transform(plane.Origin, plane.Normal); var transformFromPolygon = new Transform(transformToPolygon); transformFromPolygon.Invert(); var transformedIntersection = transformFromPolygon.OfVector(intersection); IEnumerable <Line> curveList = boundaryPolygon.Segments(); if (voids != null) { curveList = curveList.Union(voids.SelectMany(v => v.Segments())); } curveList = curveList.Select(l => l.TransformedLine(transformFromPolygon)); if (Polygon.Contains(curveList, transformedIntersection, out _)) { result = intersection; return(true); } } result = default(Vector3); return(false); }
/// <summary> /// Does this ray intersect with the provided GeometricElement? Only GeometricElements with Solid Representations are currently supported, and voids will be ignored. /// </summary> /// <param name="element">The element to intersect with.</param> /// <param name="result">The list of intersection results.</param> /// <returns></returns> public bool Intersects(GeometricElement element, out List <Vector3> result) { if (element.Representation == null || element.Representation.SolidOperations == null || element.Representation.SolidOperations.Count == 0) { element.UpdateRepresentations(); } List <Vector3> resultsOut = new List <Vector3>(); var transformFromElement = new Transform(element.Transform); transformFromElement.Invert(); var transformToElement = new Transform(element.Transform); var transformedRay = new Ray(transformFromElement.OfPoint(Origin), transformFromElement.OfVector(Direction)); //TODO: extend to handle voids when void solids in Representations are supported generally var intersects = false; foreach (var solidOp in element.Representation.SolidOperations.Where(e => !e.IsVoid)) { if (transformedRay.Intersects(solidOp, out List <Vector3> tempResults)) { intersects = true; resultsOut.AddRange(tempResults.Select(t => transformToElement.OfPoint(t))); } ; } result = resultsOut; return(intersects); }
/// <summary> /// Does this ray intersect with the provided GeometricElement? Only GeometricElements with Solid Representations are currently supported, and voids will be ignored. /// </summary> /// <param name="element">The element to intersect with.</param> /// <param name="result">The list of intersection results.</param> /// <returns></returns> public bool Intersects(GeometricElement element, out List <Vector3> result) { List <Vector3> resultsOut = new List <Vector3>(); var transformFromElement = new Transform(element.Transform); transformFromElement.Invert(); var transformToElement = new Transform(element.Transform); var transformMinusTranslation = new Transform(transformFromElement); // This transform ignores position so it can be used to transform the ray direction vector transformMinusTranslation.Move(transformMinusTranslation.Origin.Negate()); var transformedRay = new Ray(transformFromElement.OfPoint(Origin), transformMinusTranslation.OfVector(Direction)); //TODO: extend to handle voids when void solids in Representations are supported generally var intersects = false; foreach (var solidOp in element.Representation.SolidOperations.Where(e => !e.IsVoid)) { if (transformedRay.Intersects(solidOp, out List <Vector3> tempResults)) { intersects = true; resultsOut.AddRange(tempResults.Select(t => transformToElement.OfPoint(t))); } ; } result = resultsOut; return(intersects); }
/// <summary> /// Calculate a counter-clockwise plane angle between this vector and the provided vector, projected to the plane perpendicular to the provided normal. /// </summary> /// <param name="v">The vector with which to measure the angle.</param> /// <param name="normal">The normal of the plane in which you wish to calculate the angle.</param> /// <returns>Angle in degrees between 0 and 360, or NaN if the projected input vectors are invalid.</returns> public double PlaneAngleTo(Vector3 v, Vector3 normal) { var transformFromPlane = new Transform(Vector3.Origin, normal); transformFromPlane.Invert(); var thisTransformed = transformFromPlane.OfVector(this); var otherTransformed = transformFromPlane.OfVector(v); // project to Plane Vector3 a = new Vector3(thisTransformed.X, thisTransformed.Y, 0); Vector3 b = new Vector3(otherTransformed.X, otherTransformed.Y, 0); // reject very small vectors if (a.Length() < Vector3.EPSILON || b.Length() < Vector3.EPSILON) { return(double.NaN); } Vector3 aUnitized = a.Unitized(); Vector3 bUnitized = b.Unitized(); // Cos^-1(a dot b), a dot b clamped to [-1, 1] var angle = Math.Acos(Math.Max(Math.Min(aUnitized.Dot(bUnitized), 1.0), -1.0)); if (Math.Abs(angle) < Vector3.EPSILON) { return(0); } // check if should be reflex angle Vector3 aCrossB = aUnitized.Cross(bUnitized).Unitized(); if (Vector3.ZAxis.Dot(aCrossB) > 0) { return(angle * 180 / Math.PI); } else { return((Math.PI * 2 - angle) * 180 / Math.PI); } }
public static UnityEngine.Vector3[] ToUnityVertices(this double[] arr, Elements.Geometry.Transform t) { var verts = new UnityEngine.Vector3[arr.Length / 3]; var index = 0; for (var i = 0; i < arr.Length / 3; i += 3) { var vt = t != null?t.OfVector(new Vector3(arr[i], arr[i + 1], arr[i + 2])) : new Vector3(arr[i], arr[i + 1], arr[i + 2]); var v = vt.ToUnityVector3(); verts[index] = v; index++; } return(verts); }
/// <summary> /// Does this ray intersect with the provided face? /// </summary> /// <param name="face">The Face to intersect with.</param> /// <param name="result">The intersection result.</param> /// <returns>True if an intersection occurs, otherwise false. If true, check the intersection result for the location of the intersection.</returns> internal bool Intersects(Face face, out Vector3 result) { var plane = face.Plane(); if (Intersects(plane, out Vector3 intersection)) { var boundaryPolygon = face.Outer.ToPolygon(); var transformToPolygon = new Transform(plane.Origin, plane.Normal); var transformFromPolygon = new Transform(transformToPolygon); transformFromPolygon.Invert(); var transformedPolygon = transformFromPolygon.OfPolygon(boundaryPolygon); var transformedIntersection = transformFromPolygon.OfVector(intersection); if (transformedPolygon.Contains(transformedIntersection) || transformedPolygon.Touches(transformedIntersection)) { result = intersection; return(true); } } result = default(Vector3); return(false); }
/// <summary> /// Does this ray intersect the provided polygon area? /// </summary> /// <param name="polygon">The Polygon to intersect with.</param> /// <param name="result">The intersection result.</param> /// <returns>True if an intersection occurs, otherwise false. If true, check the intersection result for the location of the intersection.</returns> public bool Intersects(Polygon polygon, out Vector3 result) { var plane = new Plane(polygon.Vertices.First(), polygon.Vertices); if (Intersects(plane, out Vector3 intersection)) { var transformToPolygon = new Transform(plane.Origin, plane.Normal); var transformFromPolygon = new Transform(transformToPolygon); transformFromPolygon.Invert(); var transformedIntersection = transformFromPolygon.OfVector(intersection); IEnumerable <Line> curveList = polygon.Segments(); curveList = curveList.Select(l => l.TransformedLine(transformFromPolygon)); if (Polygon.Contains(curveList, transformedIntersection, out _)) { result = intersection; return(true); } } result = default(Vector3); return(false); }