//*************************************************************** // X p a n d I n i t //*************************************************************** void XpandInit(ref SurfaceGrid Zgrid, ref ScatteredData Data) { NumXcoords = Convert.ToInt32(Zgrid.xsize); NumYcoords = Convert.ToInt32(Zgrid.ysize); TotalGridPoints = (long)NumXcoords * (long)NumYcoords; xIndex = yIndex = 0; NumberDone = TotalRange = TotalShells = 0; NumDataPoints = Data.Size; if (NumDataPoints < 3) { return; } xGridMin = Zgrid.x(0); xGridMax = Zgrid.x(NumXcoords - 1); yGridMin = Zgrid.y(0); yGridMax = Zgrid.y(NumYcoords - 1); float xRange = Data.xMax - Data.xMin; float yRange = Data.yMax - Data.yMin; float Volume = xRange * yRange; float VolPerPoint = Volume / ((float)NumDataPoints / (float)nSample); Radius = (float)Math.Sqrt(VolPerPoint / Math.PI); Diameter = Radius * 2; DiameterSq = Diameter * Diameter; xyStopDistSq = DiameterSq * DensityStopRatio * DensityStopRatio; EdgeSenseDistSq = DiameterSq * EdgeSenseFactor * EdgeSenseFactor; LocateInit(ref Data, ref Zgrid); }
//************************************************************** // X p a n d // Generate the entire grid in one call. //************************************************************* public Xpand(ref SurfaceGrid Zgrid, ref ScatteredData RandomData) { XpandInit(ref Zgrid, ref RandomData); while (XpandPoint(ref Zgrid, ref RandomData)) { ; } }
//************************************************************** // L o c a t e I n i t //************************************************************** static void LocateInit(ref ScatteredData Data, ref SurfaceGrid Grid) { int ix = 0, iy = 0; Locator.New(NumDataPoints, NumXcoords, NumYcoords); for (long i = 0; i < NumDataPoints; i += nSample) { if (LocateGridX(ref ix, ref iy, Data.X[i], Data.Y[i], ref Grid)) { Locator.setnext(i, ix, iy); } } Locator.Sort(); }
//********************************************************************** // S c a n O n e G r i d //********************************************************************** static void ScanOneGrid(int i, int j, ref ScatteredData Data, ref SurfaceGrid Grid) { long GotOne; for (int n = 0; true; n++) { GotOne = Locator.Search(i, j, n); if (GotOne < 0) { return; } PutInOctant(Grid.x(xIndex), Grid.y(yIndex), ref Data, GotOne); TotalRange++; } }
//****************************************************************** // X p a n d P o i n t // // Evaluates one grid intersection only and advances indexes so // the next call will evaluate the next one. //****************************************************************** bool XpandPoint(ref SurfaceGrid Zgrid, ref ScatteredData RandomData) { float Zvalue; //assert( xIndex < NumXcoords ); //assert( yIndex < NumYcoords ); if (NumDataPoints < 3) { return(false); } // Select the closest point in each octant surround the grid point. SelectPoints(ref RandomData, ref Zgrid); // Check if point can be included and if so.. calculate it. if (IncludeGridPoint() > 0) { Zvalue = WeightedAverage(ref RandomData); } else { Zvalue = UndefinedZ; } Zgrid.zset(xIndex, yIndex, Zvalue); // Move to next grid intersection.... ++xIndex; if (xIndex >= NumXcoords) { ++yIndex; xIndex = 0; } if (yIndex >= NumYcoords) { Locator.New(0, NumXcoords, NumYcoords); return(false); } ++NumberDone; //assert( NumberDone <= TotalGridPoints); return(true); }
//************************************************************** // L o c a t e G r i d X //************************************************************** static bool LocateGridX(ref int ix, ref int iy, float xLocn, float yLocn, ref SurfaceGrid Grid) { // Finds the closest grid intersection to data point i. // Return's 1 if successful, // 0 if data point is too far away from the intersection. int test = 0, nx, ny, top, bot; float distance; // check to see if point too far outside the grid perimeter. distance = xGridMin - xLocn; if (xLocn < xGridMin && distance * distance > xyStopDistSq) { return(false); } distance = xGridMax - xLocn; if (xLocn > xGridMax && distance * distance > xyStopDistSq) { return(false); } distance = yGridMin - yLocn; if (yLocn < yGridMin && distance * distance > xyStopDistSq) { return(false); } distance = yGridMax - yLocn; if (yLocn > yGridMax && distance * distance > xyStopDistSq) { return(false); } // Binary search for closest in x. nx = NumXcoords; top = nx - 1; bot = 0; while ((top - bot) > 1) { test = (top - bot) / 2 + bot; if (xLocn > Grid.x(test)) { bot = test; } else { top = test; } } float dist = Math.Abs(xLocn - Grid.x(test)); if (test < (nx - 1)) { if (Math.Abs(xLocn - Grid.x(test + 1)) < dist) { test++; } } if (test > 0) { if (Math.Abs(xLocn - Grid.x(test - 1)) < dist) { test--; } } //assert( test >= 0 && test < nx ); ix = test; // Do the same for closest in y. ny = NumYcoords; top = ny - 1; bot = 0; while ((top - bot) > 1) { test = (top - bot) / 2 + bot; if (yLocn > Grid.y(test)) { bot = test; } else { top = test; } } dist = Math.Abs(yLocn - Grid.y(test)); if (test < (ny - 1)) { if (Math.Abs(yLocn - Grid.y(test + 1)) < dist) { test++; } } if (test > 0) { if (Math.Abs(yLocn - Grid.y(test - 1)) < dist) { test--; } } //assert( test >= 0 && test < ny); iy = test; return(true); }
// *************************************************************** // S e l e c t P o i n t s //***************************************************************** static void SelectPoints(ref ScatteredData Data, ref SurfaceGrid Grid) // This routine will search the array of Data points looking for // the closest point in each of the 8 octants surrounding the grid // coordinate currently being evaluated (at location x, y). { int Start, End, Row, Column; float TestDist; bool TopDone = false; // These are logical flags controlling the bool BottomDone = false; // Shelling process. bool LeftDone = false; bool RightDone = false; int i; // Zero out the arrays which keep track of closest point and its distance. for (i = 0; i < 8; i++) { PointInOctant[i] = -1; PointDistSquared[i] = 0.0f; } NoFound = 0; ScanOneGrid(xIndex, yIndex, ref Data, ref Grid); // Do home grid first. for (int shell = 1; true; shell++) // Now shell outwards from home. { Start = xIndex - shell; if (Start < 0) { Start = 0; // Thanks to Matt Gessner } End = xIndex + shell + 1; if (End > NumXcoords) { End = NumXcoords; } // Do top row. if (!TopDone) { Row = yIndex + shell; if (Row >= NumYcoords) { TopDone = true; } else { TestDist = Grid.y(Row) - Grid.y(yIndex); TestDist = TestDist * TestDist; if (((NoFound > 0) && ((TestDist > ClosestSquared * ScanStopRatio)) || (TestDist > xyStopDistSq))) { TopDone = true; } else { for (i = Start; i < End; i++) { ScanOneGrid(i, Row, ref Data, ref Grid); } } } } // Do bottom row. if (!BottomDone) { Row = yIndex - shell; if (Row < 0) { BottomDone = true; } else { TestDist = Grid.y(yIndex) - Grid.y(Row); TestDist = TestDist * TestDist; if (((NoFound > 0) && ((TestDist > ClosestSquared * ScanStopRatio)) || (TestDist > xyStopDistSq))) { BottomDone = true; } else { for (i = Start; i < End; i++) { ScanOneGrid(i, Row, ref Data, ref Grid); } } } } Start = yIndex - shell + 1; if (Start < 0) { Start = 0; // Thanks to Matt Gessner } End = yIndex + shell; if (End > NumYcoords) { End = NumYcoords; } // Do left column. if (!LeftDone) { Column = xIndex - shell; if (Column < 0) { LeftDone = true; } else { TestDist = Grid.x(xIndex) - Grid.x(Column); TestDist = TestDist * TestDist; if (((NoFound > 0) && ((TestDist > ClosestSquared * ScanStopRatio)) || (TestDist > xyStopDistSq))) { LeftDone = true; } else { for (i = Start; i < End; i++) { ScanOneGrid(Column, i, ref Data, ref Grid); } } } } // Do right column. if (!RightDone) { Column = xIndex + shell; if (Column >= NumXcoords) { RightDone = true; } else { TestDist = Grid.x(Column) - Grid.x(xIndex); TestDist = TestDist * TestDist; if (((NoFound > 0) && ((TestDist > ClosestSquared * ScanStopRatio)) || (TestDist > xyStopDistSq))) { RightDone = true; } else { for (i = Start; i < End; i++) { ScanOneGrid(Column, i, ref Data, ref Grid); } } } } if (TopDone && BottomDone && LeftDone && RightDone) { TotalShells += shell; break; } } }