/** * Fill up Grid GridPoints using TriangleList input - Grid information should have been set by SetGridInfo * * @param SamplePoints : Sample Point List * @param TriangleList : List of triangles */ public void GenerateGridElements(List <BSPoint> SamplePoints, List <BSTriangle> TriangleList) { if (!(NumGridDivisions.X > 0 && NumGridDivisions.Y > 0)) { return; } //if(!(GridDimensions.IsValid)) int TotalNumGridPoints = (int)(NumGridPointsForAxis.X * NumGridPointsForAxis.Y); GridPoints.Clear(); if (SamplePoints.Count == 0 || TriangleList.Count == 0) { return; } for (int i = 0; i < TotalNumGridPoints; ++i) { GridPoints.Add(new GridElement()); } Vector3 GridPointPosition; for (int GridPositionX = 0; GridPositionX < NumGridPointsForAxis.X; ++GridPositionX) { for (int GridPositionY = 0; GridPositionY < NumGridPointsForAxis.Y; ++GridPositionY) { BSTriangle SelectedTriangle = null; GridElement GridPoint = GridPoints[GridPositionX * (int)NumGridPointsForAxis.Y + GridPositionY]; GridPointPosition = GetPosFromIndex(GridPositionX, GridPositionY); Vector3 Weights = Vector3.Zero; if (FindTriangleThisPointBelongsTo(GridPointPosition, ref Weights, ref SelectedTriangle, TriangleList)) { // found it GridPoint.Weights[0] = Weights.X; GridPoint.Weights[1] = Weights.Y; GridPoint.Weights[2] = Weights.Z; // need to find sample point index // @todo fix this with better solution // lazy me GridPoint.Indices[0] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[0]); }); GridPoint.Indices[1] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[1]); }); GridPoint.Indices[2] = SamplePoints.FindIndex((point) => { return(point == SelectedTriangle.Vertices[2]); }); //check(GridPoint.Indices[0] != INDEX_NONE); //check(GridPoint.Indices[1] != INDEX_NONE); //check(GridPoint.Indices[2] != INDEX_NONE); } else { List <BSSortByDistance> SortedTriangles = new List <BSSortByDistance>(); for (int TriangleIndex = 0; TriangleIndex < TriangleList.Count; ++TriangleIndex) { // Check if points are collinear BSTriangle Triangle = TriangleList[TriangleIndex]; Vector3 EdgeA = Triangle.Vertices[1].Position - Triangle.Vertices[0].Position; Vector3 EdgeB = Triangle.Vertices[2].Position - Triangle.Vertices[0].Position; float Result = EdgeA.X * EdgeB.Y - EdgeA.Y * EdgeB.X; // Only add valid triangles if (Result > 0.0f) { SortedTriangles.Add(new BSSortByDistance(TriangleIndex, Triangle.GetDistance(GridPointPosition))); } } if (SortedTriangles.Count > 0) { // SortedTriangles.Sort([](FSortByDistance A, FSortByDistance B) { return A.Distance < B.Distance; }); BSTriangle ClosestTriangle = TriangleList[SortedTriangles[0].Index]; // For the closest triangle, determine which of its edges is closest to the grid point List <BSSortByDistance> Edges = new List <BSSortByDistance>(); List <Vector3> PointsOnEdges = new List <Vector3>(); for (int EdgeIndex = 0; EdgeIndex < 3; ++EdgeIndex) { Vector3 ClosestPoint = ClosestPointOnLine(ClosestTriangle.Edges[EdgeIndex].Vertices[0].Position, ClosestTriangle.Edges[EdgeIndex].Vertices[1].Position, GridPointPosition); Edges.Add(new BSSortByDistance(EdgeIndex, (ClosestPoint - GridPointPosition).LengthSquared())); PointsOnEdges.Add(ClosestPoint); } //Edges.Sort([](FSortByDistance A, FSortByDistance B) { return A.Distance < B.Distance; }); // Calculate weighting using the closest edge points and the clamped grid position on the line Vector3 GridWeights = GetBaryCentric2D(PointsOnEdges[Edges[0].Index], ClosestTriangle.Vertices[0].Position, ClosestTriangle.Vertices[1].Position, ClosestTriangle.Vertices[2].Position); for (int Index = 0; Index < 3; ++Index) { GridPoint.Weights[Index] = GridWeights[Index]; GridPoint.Indices[Index] = SamplePoints.FindIndex((point) => { return(point == ClosestTriangle.Vertices[Index]); }); } } else { // This means that there is either one point, two points or collinear triangles on the grid if (SamplePoints.Count == 1) { // Just one, fill all grid points to the single sample GridPoint.Weights[0] = 1.0f; GridPoint.Indices[0] = 0; } else { // Two points or co-linear triangles, first find the two closest samples List <BSSortByDistance> SampleDistances = new List <BSSortByDistance>(); for (int PointIndex = 0; PointIndex < SamplePoints.Count; ++PointIndex) { var vec = (SamplePoints[PointIndex].Position - GridPointPosition); Vector2 vector2 = new Vector2(vec.X, vec.Y); float DistanceFromSampleToPoint = vector2.LengthSquared(); SampleDistances.Add(new BSSortByDistance(PointIndex, DistanceFromSampleToPoint)); } SampleDistances.Sort((A, B) => { if (A.Distance == B.Distance) { return(0); } return(A.Distance > B.Distance ? 1 : -1); }); // Find closest point on line between the two samples (clamping the grid position to the line, just like clamping to the triangle edges) BSPoint[] Samples = new BSPoint[2]; Samples[0] = SamplePoints[SampleDistances[0].Index]; Samples[1] = SamplePoints[SampleDistances[1].Index]; Vector3 ClosestPointOnTheLine = ClosestPointOnLine(Samples[0].Position, Samples[1].Position, GridPointPosition); var temp = (Samples[0].Position - Samples[1].Position); Vector2 tempVector2 = new Vector2(temp.X, temp.Y); float LineLength = tempVector2.LengthSquared(); // Weight the samples according to the distance from the grid point on the line to the samples for (int SampleIndex = 0; SampleIndex < 2; ++SampleIndex) { var thelength3D = (Samples[SampleIndex].Position - ClosestPointOnTheLine); var thelength2D = new Vector2(thelength3D.X, thelength3D.Y); GridPoint.Weights[SampleIndex] = (LineLength - thelength2D.LengthSquared()) / LineLength; GridPoint.Indices[SampleIndex] = SamplePoints.FindIndex((point) => { return(point == Samples[SampleIndex]); }); } } } } } } }
public void Reset() { GridPoints.Clear(); }