public EllipsoidTangentPlane(Ellipsoid ellipsoid, IEnumerable <Vector3> positions) { if (ellipsoid == null) { throw new ArgumentNullException("ellipsoid"); } if (positions == null) { throw new ArgumentNullException("positions"); } if (!CollectionAlgorithms.EnumerableCountGreaterThanOrEqual(positions, 1)) { throw new ArgumentOutOfRangeException("positions", "At least one position is required."); } AxisAlignedBoundingBox box = new AxisAlignedBoundingBox(positions); _origin = ellipsoid.ScaleToGeodeticSurface(box.Center); _normal = ellipsoid.GeodeticSurfaceNormal(_origin); _d = -_origin.Dot(_origin); _yAxis = _origin.Cross(_origin.MostOrthogonalAxis).Normalize(); _xAxis = _yAxis.Cross(_origin).Normalize(); }
public ICollection <Vector2> ComputePositionsOnPlane(IEnumerable <Vector3D> positions) { if (positions == null) { throw new ArgumentNullException("positions"); } IList <Vector2> positionsOnPlane = new List <Vector2>(CollectionAlgorithms.EnumerableCount(positions)); foreach (Vector3 position in positions) { Vector3 intersectionPoint; if (IntersectionTests.TryRayPlane(Vector3.Zero, position.Normalize(), _normal, _d, out intersectionPoint)) { Vector3D v = intersectionPoint - _origin; positionsOnPlane.Add(new Vector2D(_xAxis.Dot(v), _yAxis.Dot(v))); } else { // Ray does not intersect plane } } return(positionsOnPlane); }
public ICollection <Geodetic2D> ToGeodetic2D(IEnumerable <Vector3> positions) { if (positions == null) { throw new ArgumentNullException("positions"); } IList <Geodetic2D> geodetics = new List <Geodetic2D>(CollectionAlgorithms.EnumerableCount(positions)); foreach (Vector3 position in positions) { geodetics.Add(ToGeodetic2D(position)); } return(geodetics); }
/// <summary> /// 返回一个mesh对象 /// </summary> /// <param name="positions"></param> /// <param name="indices"></param> /// <param name="granularity"></param> /// <returns></returns> public static Mesh <Vector3> Compute(IEnumerable <Vector3> positions, ushort[] indices, double granularity) { if (positions == null) { throw new ArgumentNullException("positions"); } if (indices == null) { throw new ArgumentNullException("positions"); } if (indices.Count() < 3) { throw new ArgumentOutOfRangeException("indices", "At least three indices are required."); } if (indices.Count() % 3 != 0) { throw new ArgumentException("indices", "The number of indices must be divisable by three."); } if (granularity <= 0.0) { throw new ArgumentOutOfRangeException("granularity", "Granularity must be greater than zero."); } // // Use two queues: one for triangles that need (or might need) to be // subdivided and other for triangles that are fully subdivided. // Queue <TriangleIndicesUnsignedShort> triangles = new Queue <TriangleIndicesUnsignedShort>(indices.Count() / 3); Queue <TriangleIndicesUnsignedShort> done = new Queue <TriangleIndicesUnsignedShort>(indices.Count() / 3); for (int i = 0; i < indices.Count(); i += 3) { triangles.Enqueue(new TriangleIndicesUnsignedShort(indices[i], indices[i + 1], indices[i + 2])); } // // New positions due to edge splits are appended to the positions list. // IList <Vector3> subdividedPositions = CollectionAlgorithms.CopyEnumerableToList(positions); // // Used to make sure shared edges are not split more than once. // Dictionary <Edge, int> edges = new Dictionary <Edge, int>(); // // Subdivide triangles until we run out // while (triangles.Count != 0) { TriangleIndicesUnsignedShort triangle = triangles.Dequeue(); Vector3 v0 = subdividedPositions[triangle.UI0]; Vector3 v1 = subdividedPositions[triangle.UI1]; Vector3 v2 = subdividedPositions[triangle.UI2]; double g0 = v0.AngleBetween(v1); double g1 = v1.AngleBetween(v2); double g2 = v2.AngleBetween(v0); double max = Math.Max(g0, Math.Max(g1, g2)); if (max > granularity) { if (g0 == max) { Edge edge = new Edge(Math.Min(triangle.UI0, triangle.UI1), Math.Max(triangle.UI0, triangle.UI1)); int i; if (!edges.TryGetValue(edge, out i)) { subdividedPositions.Add((v0 + v1) * 0.5f); i = subdividedPositions.Count - 1; edges.Add(edge, i); } triangles.Enqueue(new TriangleIndicesUnsignedShort(triangle.UI0, (ushort)i, triangle.UI2)); triangles.Enqueue(new TriangleIndicesUnsignedShort((ushort)i, triangle.UI1, triangle.UI2)); } else if (g1 == max) { Edge edge = new Edge(Math.Min(triangle.I1, triangle.I2), Math.Max(triangle.I1, triangle.I2)); int i; if (!edges.TryGetValue(edge, out i)) { subdividedPositions.Add((v1 + v2) * 0.5f); i = subdividedPositions.Count - 1; edges.Add(edge, i); } triangles.Enqueue(new TriangleIndicesUnsignedShort(triangle.UI1, (ushort)i, triangle.UI0)); triangles.Enqueue(new TriangleIndicesUnsignedShort((ushort)i, triangle.UI2, triangle.UI0)); } else if (g2 == max) { Edge edge = new Edge(Math.Min(triangle.I2, triangle.I0), Math.Max(triangle.I2, triangle.I0)); int i; if (!edges.TryGetValue(edge, out i)) { subdividedPositions.Add((v2 + v0) * 0.5f); i = subdividedPositions.Count - 1; edges.Add(edge, i); } triangles.Enqueue(new TriangleIndicesUnsignedShort(triangle.UI2, (ushort)i, triangle.UI1)); triangles.Enqueue(new TriangleIndicesUnsignedShort((ushort)i, triangle.UI0, triangle.UI1)); } } else { done.Enqueue(triangle); } } // // New indices // List <ushort> subdividedIndices = new List <ushort>(done.Count * 3); foreach (TriangleIndicesUnsignedShort t in done) { subdividedIndices.Add(t.UI0); subdividedIndices.Add(t.UI1); subdividedIndices.Add(t.UI2); } var mesh = new Mesh <Vector3>(); mesh.Positions = subdividedPositions.ToArray(); mesh.Indices = subdividedIndices.ToArray(); return(mesh); }