protected virtual float find_target_hit(Ray3f worldRay, out ControlPoint hitPoint) { hitPoint = null; double near_t = double.MaxValue; Ray3d rayS = (Ray3d)Scene.ToSceneRay(worldRay); foreach (ControlPoint point in GizmoPoints.Values) { if (point.initialized == false) { continue; } // USE INDICATOR HIT-TEST ?? Vector3d centerS = (Vector3d)point.currentFrameS.Origin; float r = point.sizeS; LinearIntersection isect = PointIntersectionTest(rayS, centerS, r, point.id); if (isect.intersects && isect.numIntersections == 2 && isect.parameter.a < near_t) { near_t = isect.parameter.a; hitPoint = point; } } return((float)near_t); }
private List <Point3d> getIntersectionPointsOfClippingPlanes(List <Plane3d> clippingPlanes) { double unitFactor = GetGunits(); List <Point3d> intersectionPoints = new List <Point3d>(); for (int i = 0; i < clippingPlanes.Count; i++) { for (int j = 0; j < clippingPlanes.Count; j++) { for (int k = 0; k < clippingPlanes.Count; k++) { if (i != j && i != k && j != k && i < j && j < k) { Plane3d p0 = clippingPlanes[i]; Plane3d p1 = clippingPlanes[j]; Plane3d p2 = clippingPlanes[k]; Ray3d ray = new Ray3d(); Point3d intersectionPoint = new Point3d(); double param = 0; if (MSApp.Plane3dIntersectsPlane3d(ref ray, ref p0, ref p1) && MSApp.Plane3dIntersectsRay3d(ref intersectionPoint, ref param, ref p2, ray)) { intersectionPoints.Add(MSApp.Point3dScale(intersectionPoint, unitFactor)); } } } } } return(intersectionPoints.Count > 0 ? intersectionPoints : null); }
/// <summary> /// Return objects that are within maxDistance of the specified ray. /// If none, returns an empty array (not null). /// </summary> /// <param name="ray">The ray. Passing as ref to improve performance since it won't have to be copied.</param> /// <param name="maxDistance">Maximum distance from the ray to consider.</param> /// <returns>Objects within range.</returns> public T[] GetNearby(Ray3d ray, float maxDistance) { List <T> collidingWith = new List <T>(); rootNode.GetNearby(ref ray, ref maxDistance, collidingWith); return(collidingWith.ToArray()); }
public static Model3d Raycast(OctreeNode node, Ray3d ray) { IntersectionTest3D.RaycastResult raycast = new IntersectionTest3D.RaycastResult(); IntersectionTest3D.Ray3dWithAABB3d(node.m_bounds, ray, ref raycast); FloatL t = raycast.m_t; if (t >= 0) { if (node.m_children == null) { return(FindClosest(node.m_models, ray)); } else { /*std::vector<Model*> results;*/ List <Model3d> results = new List <Model3d>(); for (int i = 0; i < 8; ++i) { Model3d result = Raycast(node.m_children[i], ray); if (result != null) { results.Add(result); } } return(FindClosest(results, ray)); } } return(null); }
public int FindNearestHitTriangle(Ray3d ray, double fMaxDist = double.MaxValue) { var save_filter = SourceSpatial.TriangleFilterF; SourceSpatial.TriangleFilterF = source_filter; int hit_source_tid = SourceSpatial.FindNearestHitTriangle(ray); SourceSpatial.TriangleFilterF = save_filter; int hit_edit_tid; IntrRay3Triangle3 edit_hit = find_added_hit(ref ray, out hit_edit_tid); if (hit_source_tid == DMesh3.InvalidID && hit_edit_tid == DMesh3.InvalidID) { return(DMesh3.InvalidID); } else if (hit_source_tid == DMesh3.InvalidID) { return(hit_edit_tid); } else if (hit_edit_tid == DMesh3.InvalidID) { return(hit_source_tid); } IntrRay3Triangle3 source_hit = (hit_source_tid != -1) ? MeshQueries.TriangleIntersection(SourceMesh, hit_source_tid, ray) : null; return((edit_hit.RayParameter < source_hit.RayParameter) ? hit_edit_tid : hit_source_tid); }
public void CanQueryPointsAlongRay() { var filename = Config.TEST_FILE_NAME_PTS; if (!File.Exists(filename)) { Assert.Ignore($"File not found: {filename}"); } var config = ImportConfig.Default .WithInMemoryStore() .WithKey("key1") .WithOctreeSplitLimit(1000) .WithReadBufferSizeInBytes(64 * 1024 * 1024) ; var pointset = PointCloud.Import(filename, config); var ray1 = new Ray3d(new V3d(0.1, -1.0, -0.2), V3d.OIO); var ray2 = new Ray3d(new V3d(0.1, -0.5, -0.2), V3d.OIO); var count1 = 0; var count2 = 0; foreach (var x in pointset.QueryPointsNearRay(ray1, 0.1)) { count1 += x.Positions.Length; } foreach (var x in pointset.QueryPointsNearRay(ray2, 0.1)) { count2 += x.Positions.Length; } Assert.IsTrue(count1 >= count2); }
public void TriangleIntersectionWithRayTest() { Point3d p1 = new Point3d(0, 0, 0); Point3d p2 = new Point3d(6, 0, 0); Point3d p3 = new Point3d(0, 6, 0); Triangle t = new Triangle(p1, p2, p3); Ray3d r = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, 1, 0)); Assert.IsTrue((Segment3d)t.IntersectionWith(r) == new Segment3d(new Point3d(1, 1, 0), new Point3d(3, 3, 0))); t = new Triangle(p1, p3, p2); r = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, 1, 0)); Assert.IsTrue((Segment3d)t.IntersectionWith(r) == new Segment3d(new Point3d(1, 1, 0), new Point3d(3, 3, 0))); r = new Ray3d(new Point3d(0, 0, 10), new Vector3d(0, 0, -1)); Assert.IsTrue((Point3d)t.IntersectionWith(r) == new Point3d(0, 0, 0)); r = new Ray3d(new Point3d(0, 0, -10), new Vector3d(0, 0, 1)); Assert.IsTrue((Point3d)t.IntersectionWith(r) == new Point3d(0, 0, 0)); r = new Ray3d(new Point3d(4, 4, -10), new Vector3d(0, 0, 1)); Assert.IsNull(t.IntersectionWith(r)); }
public static Model3d FindClosest(List <Model3d> set, Ray3d ray) { if (set.Count == 0) { return(null); } Model3d closest = null; FloatL closest_t = -1; for (int i = 0, size = set.Count; i < size; ++i) { FloatL this_t = IntersectionTest3D.Ray3dWithModel3d(ray, set[i]); if (this_t < 0) { continue; } if (closest_t < 0 || this_t < closest_t) { closest_t = this_t; closest = set[i]; } } return(closest); }
public static Matrix2d GetMatrixFromRayShoot(Grid grid, Mesh union, bool top = false) { Matrix2d grid2d = new Matrix2d(grid.NumX, grid.NumY); double zDim = -MAX_LIMIT; Vector3d axis = Vector3d.ZAxis; if (top) { zDim = MAX_LIMIT; axis = -Vector3d.ZAxis; } for (int i = 0; i < grid.NumX; i++) { for (int j = 0; j < grid.NumY; j++) { Point3d point = new Point3d((i * grid.DimX) + grid.MinX, (j * grid.DimY) + grid.MinY, zDim); Ray3d ray = new Ray3d(point, axis); var intersection = Rhino.Geometry.Intersect.Intersection.MeshRay(union, ray); if (intersection != -1.0) { int value = (int)Math.Round((float)ray.PointAt(intersection).Z, MidpointRounding.AwayFromZero); if (value < 0) { value = 0; } grid2d[i, j] = value; } } } return(grid2d); }
public void UpdatePositionOnTerrain() { hitInfoExists = false; var vx = (2 * Input.mouseAbsPosNormalized.X) / Camera.cbData.projMatrix.M11; var vy = (-2 * Input.mouseAbsPosNormalized.Y) / Camera.cbData.projMatrix.M22; var wInv = Matrix.Invert(Camera.cbData.viewMatrix); Vector3d pos = Convert.ToV3d(Vector3.TransformCoordinate(new Vector3(0, 0, 0), wInv)); Vector3d dir = Convert.ToV3d(Vector3.TransformNormal(new Vector3(vx, vy, 1.0F), wInv)); Ray3d ray = new Ray3d(pos, dir); t.position = Convert.ToV3(Editor.scenario.terrain.GetHitLocationFromRay(ray)); DataStream d = new DataStream(16, true, true); d.Write <float>(t.position.X); d.Write <float>(t.position.Y); d.Write <float>(t.position.Z); d.Write <float>(0f); d.Position = 0; Renderer.viewport.Context.UpdateSubresource(new DataBox(0, 0, d), cursorPosition, 0); d.Dispose(); }
private void CheckUndercuts() { List <Polyline> NewResultPaths = new List <Polyline>(); Ray3d ray; bool F****d; double d; foreach (Polyline p in ResultPaths) { F****d = false; foreach (Point3d pt in p) { ray = new Ray3d(pt, Workplane.ZAxis); foreach (Mesh m in DriveGeometry) { d = Rhino.Geometry.Intersect.Intersection.MeshRay(m, ray); if (d > 0.0) { F****d = true; } } } if (!F****d) { NewResultPaths.Add(p); } } ResultPaths = NewResultPaths; }
static void assert_same_hit(AxisAlignedBox3d aabox, Box3d obox, Ray3d ray, bool bIsAlwaysHit) { IntrRay3Box3 ohit = new IntrRay3Box3(ray, obox); ohit.Find(); if (bIsAlwaysHit) { Debug.Assert(ohit.Find() == true); } IntrRay3AxisAlignedBox3 aabbhit = new IntrRay3AxisAlignedBox3(ray, aabox); aabbhit.Find(); if (bIsAlwaysHit) { Debug.Assert(aabbhit.Find() == true); } Debug.Assert(ohit.Find() == aabbhit.Find()); Debug.Assert(ohit.Test() == ohit.Find()); Debug.Assert(aabbhit.Test() == aabbhit.Find()); if (ohit.Find()) { Debug.Assert(MathUtil.EpsilonEqual(ohit.RayParam0, aabbhit.RayParam0, MathUtil.ZeroTolerance)); } }
public static List <Point3d> GetMatrixFromRayShoot(Grid grid, Mesh union, ref Matrix2d matrix) { List <Point3d> points = new List <Point3d>(); int zDim = Building.MAX_LIMIT; Vector3d axis = -Vector3d.ZAxis; for (int i = 0; i < grid.NumX; i++) { for (int j = 0; j < grid.NumY; j++) { Point3d point = new Point3d((i * grid.DimX) + grid.MinX, (j * grid.DimY) + grid.MinY, zDim); Ray3d ray = new Ray3d(point, axis); var intersection = Rhino.Geometry.Intersect.Intersection.MeshRay(union, ray); if (intersection != -1.0) { double value = ray.PointAt(intersection).Z; if (value < 0) { value = 0; } Grid.FilterListBasedOnNumber(grid.Height.ToList(), value).ForEach(v => { points.Add(new Point3d(point.X, point.Y, v)); }); matrix[i, j] = (int)Math.Round((float)value, MidpointRounding.AwayFromZero); } } } return(points); }
public void RayIntersectionWithSegmentTest() { Segment3d s = new Segment3d(new Point3d(0, 0, 0), new Point3d(10, 0, 0)); Ray3d r = new Ray3d(new Point3d(-1, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), s); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), s); r = new Ray3d(new Point3d(1, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), new Segment3d(new Point3d(1, 0, 0), new Point3d(10, 0, 0))); r = new Ray3d(new Point3d(5, 0, 0), new Vector3d(-1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), new Segment3d(new Point3d(0, 0, 0), new Point3d(5, 0, 0))); r = new Ray3d(new Point3d(10, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), new Point3d(10, 0, 0)); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(-1, 0, 0)); Assert.AreEqual(r.IntersectionWith(s), new Point3d(0, 0, 0)); r = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, -1, 0)); Assert.AreEqual(r.IntersectionWith(s), new Point3d(2, 0, 0)); r = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, -1, 1)); Assert.IsNull(r.IntersectionWith(s)); }
public void RayIntersectionWithRayTest() { Ray3d r1 = new Ray3d(new Point3d(0, 0, 0), new Vector3d(1, 0, 0)); Ray3d r2 = new Ray3d(new Point3d(0, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r1.IntersectionWith(r2), r1); r2 = new Ray3d(new Point3d(-1, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r1.IntersectionWith(r2), r1); r2 = new Ray3d(new Point3d(1, 0, 0), new Vector3d(1, 0, 0)); Assert.AreEqual(r1.IntersectionWith(r2), r2); r2 = new Ray3d(new Point3d(0, 0, 0), new Vector3d(-1, 0, 0)); Assert.AreEqual(r1.IntersectionWith(r2), new Point3d(0, 0, 0)); r2 = new Ray3d(new Point3d(1, 0, 0), new Vector3d(-1, 0, 0)); Assert.AreEqual(r1.IntersectionWith(r2), new Segment3d(new Point3d(0, 0, 0), new Point3d(1, 0, 0))); r2 = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, -1, 0)); Assert.AreEqual(r1.IntersectionWith(r2), new Point3d(2, 0, 0)); r2 = new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, -1, 1)); Assert.IsNull(r1.IntersectionWith(r2)); }
public void RayDistanceToCrossingLineTest2() { Line3d l = new Line3d(new Point3d(0, 0, 0), new Vector3d(1, 0, 0)); Ray3d r = new Ray3d(new Point3d(2, 4, 3), new Vector3d(0, 1, 0)); Assert.IsTrue(Abs(r.DistanceTo(l) - 5) < GeometRi3D.Tolerance); }
public void RayIntersectionWithPlaneTest2() { Plane3d s = new Plane3d(0, 0, 1, 0); Ray3d r = new Ray3d(new Point3d(1, 1, 1), new Vector3d(1, 1, 1)); Assert.IsTrue(r.IntersectionWith(s) == null); }
public void RayProjectionToPlaneTest() { Plane3d s = new Plane3d(0, 0, 1, 0); Ray3d r = new Ray3d(new Point3d(1, 1, 1), new Vector3d(1, 1, 1)); Assert.IsTrue((Ray3d)r.ProjectionTo(s) == new Ray3d(new Point3d(1, 1, 0), new Vector3d(1, 1, 0))); }
public static GH_Mesh ProjectMeshToTopoFast(Mesh topoMesh, Mesh featureMesh) { GH_Mesh ghMesh = new GH_Mesh(); Mesh mesh = featureMesh.DuplicateMesh(); ///Move patch verts to topo for (int i = 0; i < mesh.Vertices.Count; i++) { Ray3d ray = new Ray3d((Point3d)mesh.Vertices[i], moveDir); double t = Rhino.Geometry.Intersect.Intersection.MeshRay(topoMesh, ray); if (t >= 0.0) { mesh.Vertices.SetVertex(i, (Point3f)ray.PointAt(t)); } else { Ray3d rayOpp = new Ray3d((Point3d)mesh.Vertices[i], -moveDir); double tOpp = Rhino.Geometry.Intersect.Intersection.MeshRay(topoMesh, rayOpp); if (tOpp >= 0.0) { mesh.Vertices.SetVertex(i, (Point3f)rayOpp.PointAt(tOpp)); } else { //mesh.Vertices.SetVertex(i, new Point3f(0, 0, 0)); //return null; } } } GH_Convert.ToGHMesh(mesh, GH_Conversion.Primary, ref ghMesh); return(ghMesh); }
///Projection engines public static GH_Point ProjectPointToTopo(Mesh topoMesh, Point3d pt) { GH_Point ghPoint = new GH_Point(); Ray3d ray = new Ray3d(pt, moveDir); double t = Rhino.Geometry.Intersect.Intersection.MeshRay(topoMesh, ray); if (t >= 0.0) { GH_Convert.ToGHPoint(ray.PointAt(t), GH_Conversion.Primary, ref ghPoint); } else { Ray3d rayOpp = new Ray3d(pt, -moveDir); double tOpp = Rhino.Geometry.Intersect.Intersection.MeshRay(topoMesh, rayOpp); if (tOpp >= 0.0) { GH_Convert.ToGHPoint(rayOpp.PointAt(tOpp), GH_Conversion.Primary, ref ghPoint); } else { return(null); } } return(ghPoint); }
/// <summary> /// エージェントの視野を障害物か視野半径でカットするメソッド /// </summary> /// <returns></returns> /// /// 20190622 Matsu 作成 /// 20190629 Matsu 交点がないときの処理を追加 public void CutViewRay() { var intersectVecLs = new List <Vector3d>(); var centerPt = agent.AgentBasePlane.Origin; List <Point3d> intersectPt = new List <Point3d>(); //エージェントのビューから取得 var vecLs = ShootRayView(); for (var i = 0; i < vecLs.Count; i++) { var ray = new Ray3d(centerPt, vecLs[i]); try { intersectPt = Rhino.Geometry.Intersect.Intersection.RayShoot(ray, agent.Obstacles, 1).ToList(); } catch (ArgumentNullException) { Point3d pt = ray.PointAt(agent.ViewRaidius); intersectPt.Add(pt); } IsInnerRadius(centerPt, intersectPt[0], out Vector3d vec); intersectVecLs.Add(vec); } //エージェントクラス内に格納 agent.AgentViewRay = intersectVecLs; }
public Vector3d GetHitLocationFromRay(Ray3d ray) { Vector3d vout = new Vector3d(0, 0, 0); int currHitTri = -1; IntrRay3Triangle3 hitInfo; int x = 0, y = 0; foreach (TerrainChunk t in terrainChunks) { currHitTri = t.dMeshAABB.FindNearestHitTriangle(ray); if (currHitTri != -1) { x = t.arrayX; y = t.arrayY; break; } } if (currHitTri != -1) { hitInfo = MeshQueries.TriangleIntersection(terrainChunks[x, y].dMesh, currHitTri, ray); vout = hitInfo.Ray.PointAt(hitInfo.RayParameter); } return(vout); }
public void RayIntersectionWithBoxTest() { Rotation rot = new Rotation(); Point3d p = new Point3d(0, 0, 0); Box3d b = new Box3d(p, 2, 2, 2, rot); Ray3d r = new Ray3d(new Point3d(-1, -1, -1), new Vector3d(1, 1, 1)); Segment3d s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(-1, -1, -1), new Point3d(1, 1, 1))); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(1, 1, 1)); s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(0, 0, 0), new Point3d(1, 1, 1))); r = new Ray3d(new Point3d(1, -1, -1), new Vector3d(-1, 1, 1)); s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(1, -1, -1), new Point3d(-1, 1, 1))); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(1, 0, 0)); s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(0, 0, 0), new Point3d(1, 0, 0))); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(0, -1, 0)); s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(0, 0, 0), new Point3d(0, -1, 0))); r = new Ray3d(new Point3d(0, 0, 0), new Vector3d(0, 0, 1)); s = (Segment3d)b.IntersectionWith(r); Assert.AreEqual(s, new Segment3d(new Point3d(0, 0, 0), new Point3d(0, 0, 1))); // Intersection is point r = new Ray3d(new Point3d(-1, -1, 1), new Vector3d(1, 1, 1)); Assert.AreEqual((Point3d)b.IntersectionWith(r), new Point3d(-1, -1, 1)); }
/// <summary> /// Return objects that are within maxDistance of the specified ray. /// </summary> /// <param name="ray">The ray.</param> /// <param name="maxDistance">Maximum distance from the ray to consider.</param> /// <param name="result">List result.</param> /// <returns>Objects within range.</returns> public void GetNearby(ref Ray3d ray, ref float maxDistance, List <T> result) { // Does the ray hit this node at all? // Note: Expanding the bounds is not exactly the same as a real distance check, but it's fast. // TODO: Does someone have a fast AND accurate formula to do this check? bounds.Inflate(maxDistance * 2, maxDistance * 2, maxDistance * 2); // Point3d[] pts = Rhino.Geometry.Intersect.Intersection.RayShoot(ray, new[] { (GeometryBase)bounds.ToBrep()}, 1); bool intersected = bounds.IntersectRay(ray); //bounds.size = actualBoundsSize; if (!intersected) { return; } // Check against any objects in this node for (int i = 0; i < objects.Count; i++) { if (SqrDistanceToRay(ray, objects[i].Pos) <= (maxDistance * maxDistance)) { result.Add(objects[i].Obj); } } // Check children if (children != null) { for (int i = 0; i < 8; i++) { children[i].GetNearby(ref ray, ref maxDistance, result); } } }
internal void MoveAllPointsDepthDependant(CuttingInfo info, DMesh3 newMesh, Dictionary <int, BacksideAlgorithm.PeprStatusVert> stati) { var tree = new DMeshAABBTree3(info.oldMesh, true); tree.TriangleFilterF = i => tree.Mesh.GetTriangleGroup(i) != info.data.ColorNum; foreach (var status in stati) { var shellPoint = newMesh.GetVertex(status.Value.idNewMeshOuter.Value); var normal = info.oldMesh.CalcVertexNormal(status.Value.idOldMeshOuter); var position = shellPoint + info.data.minDepth * normal; Ray3d ray = new Ray3d(shellPoint - normal * info.data.minDepth, -normal); //tiny shift to make sure it's not hitting itself int hit_tid = tree.FindNearestHitTriangle(ray); Debug.Log("Hit " + hit_tid); if (hit_tid != DMesh3.InvalidID) { IntrRay3Triangle3 intr = MeshQueries.TriangleIntersection(info.oldMesh, hit_tid, ray); double hit_dist = shellPoint.Distance(ray.PointAt(intr.RayParameter)); position = shellPoint - normal * hit_dist * (info.data.depth / 100); Debug.Log($"Hit Dist: {hit_dist}"); } else { StaticFunctions.ErrorMessage("Depth Dependant Calculation has encountered an error"); } info.mesh.SetVertex(status.Value.idOldMeshInner.Value, position); newMesh.SetVertex(status.Value.idNewMeshInner.Value, position); } }
public static Point3d[] VoxelPoints(Mesh mesh, Grid grid) { List <Point3d> pointForProjection = GetMinGridForProjection(mesh, grid); BoundingBox bbox = mesh.GetBoundingBox(true); double zMax = bbox.Max.Z; List <double> heights = grid.Height.Where(n => n <= zMax) .ToList(); List <Point3d> voxelPoints = new List <Point3d>(); Ray3d ray = new Ray3d(); foreach (Point3d pt in pointForProjection) { ray = new Ray3d(pt, Vector3d.ZAxis); var intersect = Rhino.Geometry.Intersect.Intersection.MeshRay(mesh, ray); if (intersect != -1.0) { foreach (double h in heights) { voxelPoints.Add(new Point3d(pt.X, pt.Y, h)); } } } return(voxelPoints.ToArray()); }
public Model3d Raycast(Ray3d ray) { if (m_octree != null) { // :: lets the compiler know to look outside class scope return(Octree3d.Raycast(m_octree, ray)); } Model3d result = null; FloatL result_t = -1; for (int i = 0, size = m_modleList.Count; i < size; ++i) { FloatL t = IntersectionTest3D.Ray3dWithModel3d(ray, m_modleList[i]); if (result == null && t >= 0) { result = m_modleList[i]; result_t = t; } else if (result != null && t < result_t) { result = m_modleList[i]; result_t = t; } } return(result); }
/// <summary> /// Returns an array of objects that intersect with the specified ray, if any. Otherwise returns an empty array. See also: IsColliding. /// </summary> /// <param name="checkRay">Ray to check. Passing by ref as it improves performance with structs.</param> /// <param name="maxDistance">Distance to check.</param> /// <param name="result">List result.</param> /// <returns>Objects that intersect with the specified ray.</returns> public void GetColliding(ref Ray3d checkRay, List <T> result, float maxDistance = float.PositiveInfinity) { float distance; // Is the input ray at least partially in this node? if (!bounds.IntersectRay(checkRay, out distance) || distance > maxDistance) { return; } // Check against any objects in this node for (int i = 0; i < objects.Count; i++) { if (objects[i].Bounds.IntersectRay(checkRay, out distance) && distance <= maxDistance) { result.Add(objects[i].Obj); } } // Check children if (children != null) { for (int i = 0; i < 8; i++) { children[i].GetColliding(ref checkRay, result, maxDistance); } } }
/// <summary> /// Check if the specified ray intersects with anything in the tree. See also: GetColliding. /// </summary> /// <param name="checkRay">Ray to check.</param> /// <param name="maxDistance">Distance to check.</param> /// <returns>True if there was a collision.</returns> public bool IsColliding(ref Ray3d checkRay, float maxDistance = float.PositiveInfinity) { // Is the input ray at least partially in this node? float distance; if (!bounds.IntersectRay(checkRay, out distance) || distance > maxDistance) { return(false); } // Check against any objects in this node for (int i = 0; i < objects.Count; i++) { if (objects[i].Bounds.IntersectRay(checkRay, out distance) && distance <= maxDistance) { return(true); } } // Check children if (children != null) { for (int i = 0; i < 8; i++) { if (children[i].IsColliding(ref checkRay, maxDistance)) { return(true); } } } return(false); }
/// <summary> /// Returns an array of objects that intersect with the specified ray, if any. Otherwise returns an empty array. See also: IsColliding. /// </summary> /// <param name="collidingWith">list to store intersections.</param> /// <param name="checkRay">ray to check.</param> /// <param name="maxDistance">distance to check.</param> /// <returns>Objects that intersect with the specified ray.</returns> public void GetColliding(List <T> collidingWith, Ray3d checkRay, float maxDistance = float.PositiveInfinity) { //#if UNITY_EDITOR // For debugging //AddCollisionCheck(checkRay); //#endif rootNode.GetColliding(ref checkRay, collidingWith, maxDistance); }
internal static extern double ON_Intersect_MeshRay1(IntPtr pMesh, ref Ray3d ray, IntPtr face_indices);
protected override void SolveInstance(IGH_DataAccess DA) { ITargetLength TargetLength = null; bool reset = false; int Flip = 0; List<Curve> FC = new List<Curve>(); List<Point3d> FV = new List<Point3d>(); double FixT = 0.01; double PullStrength = 0.8; double SmoothStrength = 0.8; double LengthTol = 0.15; bool Minim = false; int Iters = 1; GH_ObjectWrapper Surf = new GH_ObjectWrapper(); DA.GetData<GH_ObjectWrapper>(0, ref Surf); GH_ObjectWrapper Obj = null; DA.GetData<GH_ObjectWrapper>(1, ref Obj); TargetLength = Obj.Value as ITargetLength; DA.GetDataList<Curve>(2, FC); DA.GetDataList<Point3d>(3, FV); DA.GetData<int>(4, ref Flip); DA.GetData<double>(5, ref PullStrength); DA.GetData<int>(6, ref Iters); DA.GetData<bool>(7, ref reset); if (PullStrength == 0) { Minim = true; } if (Surf.Value is GH_Mesh) { DA.GetData<Mesh>(0, ref M); M.Faces.ConvertQuadsToTriangles(); } else { double L = 1.0; MeshingParameters MeshParams = new MeshingParameters(); MeshParams.MaximumEdgeLength = 3 * L; MeshParams.MinimumEdgeLength = L; MeshParams.JaggedSeams = false; MeshParams.SimplePlanes = false; Brep SB = null; DA.GetData<Brep>(0, ref SB); Mesh[] BrepMeshes = Mesh.CreateFromBrep(SB, MeshParams); M = new Mesh(); foreach (var mesh in BrepMeshes) M.Append(mesh); } if (reset || initialized == false) { #region reset M.Faces.ConvertQuadsToTriangles(); P = M.ToPlanktonMesh(); initialized = true; AnchorV.Clear(); FeatureV.Clear(); FeatureE.Clear(); //Mark any vertices or edges lying on features for (int i = 0; i < P.Vertices.Count; i++) { Point3d Pt = P.Vertices[i].ToPoint3d(); AnchorV.Add(-1); for (int j = 0; j < FV.Count; j++) { if (Pt.DistanceTo(FV[j]) < FixT) { AnchorV[AnchorV.Count - 1] = j; } } FeatureV.Add(-1); for (int j = 0; j < FC.Count; j++) { double param = new double(); FC[j].ClosestPoint(Pt, out param); if (Pt.DistanceTo(FC[j].PointAt(param)) < FixT) { FeatureV[FeatureV.Count - 1] = j; } } } int EdgeCount = P.Halfedges.Count / 2; for (int i = 0; i < EdgeCount; i++) { FeatureE.Add(-1); int vStart = P.Halfedges[2 * i].StartVertex; int vEnd = P.Halfedges[2 * i + 1].StartVertex; Point3d PStart = P.Vertices[vStart].ToPoint3d(); Point3d PEnd = P.Vertices[vEnd].ToPoint3d(); for (int j = 0; j < FC.Count; j++) { double paramS = new double(); double paramE = new double(); Curve thisFC = FC[j]; thisFC.ClosestPoint(PStart, out paramS); thisFC.ClosestPoint(PEnd, out paramE); if ((PStart.DistanceTo(thisFC.PointAt(paramS)) < FixT) && (PEnd.DistanceTo(thisFC.PointAt(paramE)) < FixT)) { FeatureE[FeatureE.Count - 1] = j; } } } #endregion } else { for (int iter = 0; iter < Iters; iter++) { int EdgeCount = P.Halfedges.Count / 2; double[] EdgeLength = P.Halfedges.GetLengths(); List<bool> Visited = new List<bool>(); Vector3d[] Normals = new Vector3d[P.Vertices.Count]; for (int i = 0; i < P.Vertices.Count; i++) { Visited.Add(false); Normals[i] = Normal(P, i); } double t = LengthTol; //a tolerance for when to split/collapse edges double smooth = SmoothStrength; //smoothing strength double pull = PullStrength; //pull to target mesh strength // Split the edges that are too long for (int i = 0; i < EdgeCount; i++) { if (P.Halfedges[2 * i].IsUnused == false) { int vStart = P.Halfedges[2 * i].StartVertex; int vEnd = P.Halfedges[2 * i + 1].StartVertex; if ((Visited[vStart] == false) && (Visited[vEnd] == false)) { double L2 = TargetLength.Calculate(P, 2 * i); if (EdgeLength[2 * i] > (1 + t) * (4f / 3f) * L2) { int SplitHEdge = P.Halfedges.TriangleSplitEdge(2 * i); if (SplitHEdge != -1) { int SplitCenter = P.Halfedges[SplitHEdge].StartVertex; P.Vertices.SetVertex(SplitCenter, MidPt(P, i)); //update the feature information FeatureE.Add(FeatureE[i]); FeatureV.Add(FeatureE[i]); AnchorV.Add(-1); //2 additional new edges have also been created (or 1 if split was on a boundary) //mark these as non-features int CEdgeCount = P.Halfedges.Count / 2; while (FeatureE.Count < CEdgeCount) { FeatureE.Add(-1); } Visited.Add(true); int[] Neighbours = P.Vertices.GetVertexNeighbours(SplitCenter); foreach (int n in Neighbours) { Visited[n] = true; } } } } } } //Collapse the edges that are too short for (int i = 0; i < EdgeCount; i++) { if (P.Halfedges[2 * i].IsUnused == false) { int vStart = P.Halfedges[2 * i].StartVertex; int vEnd = P.Halfedges[2 * i + 1].StartVertex; if ((Visited[vStart] == false) && (Visited[vEnd] == false)) { if (!(AnchorV[vStart] != -1 && AnchorV[vEnd] != -1)) // if both ends are anchored, don't collapse { int Collapse_option = 0; //0 for none, 1 for collapse to midpt, 2 for towards start, 3 for towards end //if neither are anchorV if (AnchorV[vStart] == -1 && AnchorV[vEnd] == -1) { // if both on same feature (or neither on a feature) if (FeatureV[vStart] == FeatureV[vEnd]) { Collapse_option = 1; } // if start is on a feature and end isn't if ((FeatureV[vStart] != -1) && (FeatureV[vEnd] == -1)) { Collapse_option = 2; } // if end is on a feature and start isn't if ((FeatureV[vStart] == -1) && (FeatureV[vEnd] != -1)) { Collapse_option = 3; } } else // so one end must be an anchor { // if start is an anchor if (AnchorV[vStart] != -1) { // if both are on same feature, or if the end is not a feature if ((FeatureE[i] != -1) || (FeatureV[vEnd] == -1)) { Collapse_option = 2; } } // if end is an anchor if (AnchorV[vEnd] != -1) { // if both are on same feature, or if the start is not a feature if ((FeatureE[i] != -1) || (FeatureV[vStart] == -1)) { Collapse_option = 3; } } } Point3d Mid = MidPt(P, i); double L2 = TargetLength.Calculate(P, 2 * i); if ((Collapse_option != 0) && (EdgeLength[2 * i] < (1 - t) * 4f / 5f * L2)) { int Collapsed = -1; int CollapseRtn = -1; if (Collapse_option == 1) { Collapsed = P.Halfedges[2 * i].StartVertex; P.Vertices.SetVertex(Collapsed, MidPt(P, i)); CollapseRtn = P.Halfedges.CollapseEdge(2 * i); } if (Collapse_option == 2) { Collapsed = P.Halfedges[2 * i].StartVertex; CollapseRtn = P.Halfedges.CollapseEdge(2 * i); } if (Collapse_option == 3) { Collapsed = P.Halfedges[2 * i + 1].StartVertex; CollapseRtn = P.Halfedges.CollapseEdge(2 * i + 1); } if (CollapseRtn != -1) { int[] Neighbours = P.Vertices.GetVertexNeighbours(Collapsed); foreach (int n in Neighbours) { Visited[n] = true; } } } } } } } EdgeCount = P.Halfedges.Count / 2; if ((Flip == 0) && (PullStrength > 0)) { //Flip edges to reduce valence error for (int i = 0; i < EdgeCount; i++) { if (!P.Halfedges[2 * i].IsUnused && (P.Halfedges[2 * i].AdjacentFace != -1) && (P.Halfedges[2 * i + 1].AdjacentFace != -1) && (FeatureE[i] == -1) // don't flip feature edges ) { int Vert1 = P.Halfedges[2 * i].StartVertex; int Vert2 = P.Halfedges[2 * i + 1].StartVertex; int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex; int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex; int Valence1 = P.Vertices.GetValence(Vert1); int Valence2 = P.Vertices.GetValence(Vert2); int Valence3 = P.Vertices.GetValence(Vert3); int Valence4 = P.Vertices.GetValence(Vert4); if (P.Vertices.NakedEdgeCount(Vert1) > 0) { Valence1 += 2; } if (P.Vertices.NakedEdgeCount(Vert2) > 0) { Valence2 += 2; } if (P.Vertices.NakedEdgeCount(Vert3) > 0) { Valence3 += 2; } if (P.Vertices.NakedEdgeCount(Vert4) > 0) { Valence4 += 2; } int CurrentError = Math.Abs(Valence1 - 6) + Math.Abs(Valence2 - 6) + Math.Abs(Valence3 - 6) + Math.Abs(Valence4 - 6); int FlippedError = Math.Abs(Valence1 - 7) + Math.Abs(Valence2 - 7) + Math.Abs(Valence3 - 5) + Math.Abs(Valence4 - 5); if (CurrentError > FlippedError) { P.Halfedges.FlipEdge(2 * i); } } } } else { //Flip edges based on angle for (int i = 0; i < EdgeCount; i++) { if (!P.Halfedges[2 * i].IsUnused && (P.Halfedges[2 * i].AdjacentFace != -1) && (P.Halfedges[2 * i + 1].AdjacentFace != -1) && (FeatureE[i] == -1) // don't flip feature edges ) { int Vert1 = P.Halfedges[2 * i].StartVertex; int Vert2 = P.Halfedges[2 * i + 1].StartVertex; int Vert3 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i].NextHalfedge].NextHalfedge].StartVertex; int Vert4 = P.Halfedges[P.Halfedges[P.Halfedges[2 * i + 1].NextHalfedge].NextHalfedge].StartVertex; Point3d P1 = P.Vertices[Vert1].ToPoint3d(); Point3d P2 = P.Vertices[Vert2].ToPoint3d(); Point3d P3 = P.Vertices[Vert3].ToPoint3d(); Point3d P4 = P.Vertices[Vert4].ToPoint3d(); double A1 = Vector3d.VectorAngle(new Vector3d(P3 - P1), new Vector3d(P4 - P1)) + Vector3d.VectorAngle(new Vector3d(P4 - P2), new Vector3d(P3 - P2)); double A2 = Vector3d.VectorAngle(new Vector3d(P1 - P4), new Vector3d(P2 - P4)) + Vector3d.VectorAngle(new Vector3d(P2 - P3), new Vector3d(P1 - P3)); if (A2 > A1) { P.Halfedges.FlipEdge(2 * i); } } } } if (Minim) { Vector3d[] SmoothC = LaplacianSmooth(P, 1, smooth); for (int i = 0; i < P.Vertices.Count; i++) { if (AnchorV[i] == -1) // don't smooth feature vertices { P.Vertices.MoveVertex(i, 0.5 * SmoothC[i]); } } } Vector3d[] Smooth = LaplacianSmooth(P, 0, smooth); for (int i = 0; i < P.Vertices.Count; i++) { if (AnchorV[i] == -1) // don't smooth feature vertices { // make it tangential only Vector3d VNormal = Normal(P, i); double ProjLength = Smooth[i] * VNormal; Smooth[i] = Smooth[i] - (VNormal * ProjLength); P.Vertices.MoveVertex(i, Smooth[i]); if (P.Vertices.NakedEdgeCount(i) != 0)//special smoothing for feature edges { int[] Neighbours = P.Vertices.GetVertexNeighbours(i); int ncount = 0; Point3d Avg = new Point3d(); for (int j = 0; j < Neighbours.Length; j++) { if (P.Vertices.NakedEdgeCount(Neighbours[j]) != 0) { ncount++; Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d(); } } Avg = Avg * (1.0 / ncount); Vector3d move = Avg - P.Vertices[i].ToPoint3d(); move = move * smooth; P.Vertices.MoveVertex(i, move); } if (FeatureV[i] != -1)//special smoothing for feature edges { int[] Neighbours = P.Vertices.GetVertexNeighbours(i); int ncount = 0; Point3d Avg = new Point3d(); for (int j = 0; j < Neighbours.Length; j++) { if ((FeatureV[Neighbours[j]] == FeatureV[i]) || (AnchorV[Neighbours[j]] != -1)) { ncount++; Avg = Avg + P.Vertices[Neighbours[j]].ToPoint3d(); } } Avg = Avg * (1.0 / ncount); Vector3d move = Avg - P.Vertices[i].ToPoint3d(); move = move * smooth; P.Vertices.MoveVertex(i, move); } //projecting points onto the target along their normals if (pull > 0) { Point3d Point = P.Vertices[i].ToPoint3d(); Vector3d normal = Normal(P, i); Ray3d Ray1 = new Ray3d(Point, normal); Ray3d Ray2 = new Ray3d(Point, -normal); double RayPt1 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray1); double RayPt2 = Rhino.Geometry.Intersect.Intersection.MeshRay(M, Ray2); Point3d ProjectedPt; if ((RayPt1 < RayPt2) && (RayPt1 > 0) && (RayPt1 < 1.0)) { ProjectedPt = Point * (1 - pull) + pull * Ray1.PointAt(RayPt1); } else if ((RayPt2 < RayPt1) && (RayPt2 > 0) && (RayPt2 < 1.0)) { ProjectedPt = Point * (1 - pull) + pull * Ray2.PointAt(RayPt2); } else { ProjectedPt = Point * (1 - pull) + pull * M.ClosestPoint(Point); } P.Vertices.SetVertex(i, ProjectedPt); } if (FeatureV[i] != -1) //pull feature vertices onto feature curves { Point3d Point = P.Vertices[i].ToPoint3d(); Curve CF = FC[FeatureV[i]]; double param1 = 0.0; Point3d onFeature = new Point3d(); CF.ClosestPoint(Point, out param1); onFeature = CF.PointAt(param1); P.Vertices.SetVertex(i, onFeature); } } else { P.Vertices.SetVertex(i, FV[AnchorV[i]]); //pull anchor vertices onto their points } } //end new AnchorV = CompactByVertex(P, AnchorV); //compact the fixed points along with the vertices FeatureV = CompactByVertex(P, FeatureV); FeatureE = CompactByEdge(P, FeatureE); P.Compact(); //this cleans the mesh data structure of unused elements } } DA.SetData(0, P); }
DataTree<Object> GetStepTree(Mesh terrainMesh, List<double> contourZList, DataTree<Curve> contourTree, List<Brep> brepList) { DataTree<Object> stepTree = new DataTree<Object>(); Plane basePlane = Plane.WorldXY; basePlane.OriginZ = terrainMesh.GetBoundingBox(true).Min.Z; // For each contour-plane for (int i = 0; i < contourTree.BranchCount; i++) { // create higher-Z pt list Point3dList winPtList = new Point3dList(); foreach (Curve contourCrv in contourTree.Branches[i]) { Plane frm; double t; contourCrv.NormalizedLengthParameter(0.5, out t); contourCrv.FrameAt(t, out frm); frm.Transform(Rhino.Geometry.Transform.PlanarProjection(basePlane)); Point3d samplePt0, samplePt1; samplePt0 = frm.Origin; samplePt1 = frm.Origin; samplePt0 += doc.ModelAbsoluteTolerance * frm.YAxis; samplePt1 -= doc.ModelAbsoluteTolerance * frm.YAxis; Ray3d ray0 = new Ray3d(samplePt0, Vector3d.ZAxis); Ray3d ray1 = new Ray3d(samplePt1, Vector3d.ZAxis); double rayParam0 = Rhino.Geometry.Intersect.Intersection.MeshRay(terrainMesh, ray0); double rayParam1 = Rhino.Geometry.Intersect.Intersection.MeshRay(terrainMesh, ray1); winPtList.Add(((rayParam0 > rayParam1) ? samplePt0 : samplePt1)); } // For each splitted region in contour-plane foreach (BrepFace brepFace in brepList[i].Faces) { Brep testBrep = brepFace.DuplicateFace(false); foreach (Point3d pt in winPtList) { LineCurve testRay = new LineCurve(new Line(pt, Vector3d.ZAxis, 1000)); Point3d[] outPts; Curve[] outCrvs; bool ix = Rhino.Geometry.Intersect.Intersection.CurveBrep(testRay, testBrep, doc.ModelAbsoluteTolerance, out outCrvs, out outPts); if (outPts.Length != 0) { stepTree.Add(testBrep, new GH_Path(i)); break; } } } } return stepTree; }
/// <summary> /// Computes point intersections that occur when shooting a ray to a collection of surfaces. /// </summary> /// <param name="ray">A ray used in intersection.</param> /// <param name="geometry">Only Surface and Brep objects are currently supported. Trims are ignored on Breps.</param> /// <param name="maxReflections">The maximum number of reflections. This value should be any value between 1 and 1000, inclusive.</param> /// <returns>An array of points: one for each face that was passed by the faceIds out reference.</returns> /// <exception cref="ArgumentNullException">geometry is null.</exception> /// <exception cref="ArgumentOutOfRangeException">maxReflections is strictly outside the [1-1000] range.</exception> public static Point3d[] RayShoot(Ray3d ray, IEnumerable<GeometryBase> geometry, int maxReflections) { if (geometry == null) throw new ArgumentNullException("geometry"); if (maxReflections < 1 || maxReflections > 1000) throw new ArgumentOutOfRangeException("maxReflections", "maxReflections must be between 1-1000"); // We should handle better the case of a null entry inside the geometry collection. // Currently a NullReferenceException occurs. using (Rhino.Runtime.InteropWrappers.SimpleArrayGeometryPointer geom = new Runtime.InteropWrappers.SimpleArrayGeometryPointer(geometry)) { IntPtr pGeometry = geom.ConstPointer(); Point3d[] rc = null; using (Rhino.Runtime.InteropWrappers.SimpleArrayPoint3d points = new Rhino.Runtime.InteropWrappers.SimpleArrayPoint3d()) { IntPtr pPoints = points.NonConstPointer(); int count = UnsafeNativeMethods.ON_RayShooter_ShootRay(ray.Position, ray.Direction, pGeometry, pPoints, maxReflections); if (count > 0) rc = points.ToArray(); } return rc; } }
/// <summary>Finds the first intersection of a ray with a mesh.</summary> /// <param name="mesh">A mesh to intersect.</param> /// <param name="ray">A ray to be casted.</param> /// <param name="meshFaceIndices">faces on mesh that ray intersects.</param> /// <returns> /// >= 0.0 parameter along ray if successful. /// < 0.0 if no intersection found. /// </returns> /// <remarks> /// The ray may intersect more than one face in cases where the ray hits /// the edge between two faces or the vertex corner shared by multiple faces. /// </remarks> public static double MeshRay(Mesh mesh, Ray3d ray, out int[] meshFaceIndices) { meshFaceIndices = null; using (Runtime.InteropWrappers.SimpleArrayInt indices = new Rhino.Runtime.InteropWrappers.SimpleArrayInt()) { IntPtr pConstMesh = mesh.ConstPointer(); double rc = UnsafeNativeMethods.ON_Intersect_MeshRay1(pConstMesh, ref ray, indices.m_ptr ); int[] vals = indices.ToArray(); if (vals!=null && vals.Length > 0) meshFaceIndices = vals; return rc; } }
/// <summary>Finds the first intersection of a ray with a mesh.</summary> /// <param name="mesh">A mesh to intersect.</param> /// <param name="ray">A ray to be casted.</param> /// <returns> /// >= 0.0 parameter along ray if successful. /// < 0.0 if no intersection found. /// </returns> public static double MeshRay(Mesh mesh, Ray3d ray) { IntPtr pConstMesh = mesh.ConstPointer(); return UnsafeNativeMethods.ON_Intersect_MeshRay1(pConstMesh, ref ray, IntPtr.Zero); }
public Ray3d ray() { if (!rayFormed) { _ray = new Ray3d(startPoint.txTx(), vector()); rayFormed = true; return _ray; } else { return _ray; } }
protected override Rhino.Commands.Result RunCommand(RhinoDoc doc, Rhino.Commands.RunMode mode) { Mesh meshObj; Point3d pointObj = new Point3d(0.0,0.0,0.0); RhinoApp.WriteLine("dikka dikka dikka..."); Rhino.Input.Custom.GetPoint gp = new Rhino.Input.Custom.GetPoint(); gp.SetCommandPrompt("Start of ray"); gp.Get(); if (gp.CommandResult() != Rhino.Commands.Result.Success) return gp.CommandResult(); pointObj = gp.Point(); doc.Objects.AddPoint(pointObj); Rhino.Input.Custom.GetObject go = new Rhino.Input.Custom.GetObject(); go.SetCommandPrompt("Select the mesh to print"); go.Get(); Result rc = go.CommandResult(); if (rc != Rhino.Commands.Result.Success) { RhinoApp.WriteLine("sdfafadsfda"); return rc; } RhinoApp.WriteLine("2 2 dikka dikka dikka..."); meshObj = new Mesh(); if (go.ObjectCount == 1) { ObjRef tmpRef = new ObjRef(go.Object(0).ObjectId); meshObj = tmpRef.Mesh(); if (meshObj == null) { return rc; } } Ray3d rayObj = new Ray3d(pointObj, new Vector3d(1.0, 1.0, 1.0)); doc.Objects.AddPoint(rayObj.PointAt(1.0)); doc.Objects.AddPoint(rayObj.PointAt(2.0)); doc.Objects.AddPoint(rayObj.PointAt(3.0)); double p = Intersection.MeshRay(meshObj, rayObj); string a = string.Format("mesh ray gives {0:0.00}",p); doc.Objects.AddPoint(rayObj.PointAt(p)); RhinoApp.WriteLine(a); return Rhino.Commands.Result.Success; }