7 #include "GroundGrid.h"
15 #include "UniversalGroundMap.h"
19 #include "Longitude.h"
21 #include "Projection.h"
22 #include "ProjectionFactory.h"
44 unsigned int height) {
47 m_extendGrid = extendGrid;
56 p_gridSize = (
unsigned long)(ceil(width * height / 8.0) + 0.5);
59 p_grid =
new char[p_gridSize];
62 p_latLinesGrid =
new char[p_gridSize];
63 p_lonLinesGrid =
new char[p_gridSize];
66 for (
unsigned long i = 0; i < p_gridSize; i++) {
67 if (p_grid) p_grid[i] = 0;
68 if (p_latLinesGrid) p_latLinesGrid[i] = 0;
69 if (p_lonLinesGrid) p_lonLinesGrid[i] = 0;
73 p_reinitialize =
false;
86 if (p_groundMap->Camera()) {
88 p_groundMap->Camera()->BasicMapping(tmp);
92 *p_mapping = p_groundMap->Projection()->Mapping();
100 if (p_mapping->hasKeyword(
"MinimumLatitude")) {
104 Latitude::AllowPastPole);
110 if (p_mapping->hasKeyword(
"MaximumLatitude")) {
119 if (p_mapping->hasKeyword(
"MinimumLongitude")) {
128 if (p_mapping->hasKeyword(
"MaximumLongitude")) {
137 if (p_minLon->isValid() && p_maxLon->isValid()) {
138 if (*p_minLon > *p_maxLon) {
140 *p_minLon = *p_maxLon;
145 Distance largerRadius = max(radius1, radius2);
149 if (p_groundMap->HasCamera()) {
150 p_defaultResolution =
151 (p_groundMap->Camera()->HighestImageResolution() /
152 largerRadius.
meters()) * 10;
155 p_defaultResolution = (p_groundMap->Resolution() /
156 largerRadius.
meters()) * 10;
159 if (p_defaultResolution < 0) {
160 p_defaultResolution = 10.0 / largerRadius.
meters();
167 GroundGrid::~GroundGrid() {
198 if (p_latLinesGrid) {
199 delete[] p_latLinesGrid;
200 p_latLinesGrid = NULL;
203 if (p_lonLinesGrid) {
204 delete[] p_lonLinesGrid;
205 p_lonLinesGrid = NULL;
223 CreateGrid(baseLat, baseLon, latInc, lonInc, progress,
Angle(),
Angle());
246 if (p_groundMap == NULL ||
247 (p_grid == NULL && p_latLinesGrid == NULL && p_lonLinesGrid == NULL)) {
248 IString msg =
"GroundGrid::CreateGrid missing ground map or grid array";
249 throw IException(IException::Programmer, msg, _FILEINFO_);
252 if (p_reinitialize) {
253 for (
unsigned long i = 0; i < p_gridSize; i++) {
254 if (p_grid) p_grid[i] = 0;
255 if (p_latLinesGrid) p_latLinesGrid[i] = 0;
256 if (p_lonLinesGrid) p_lonLinesGrid[i] = 0;
261 bool badLatLonRange =
false;
263 if (!p_minLat || !p_minLat->isValid()) {
264 badLatLonValues.append(
"MinimumLatitude");
265 badLatLonRange =
true;
268 if (!p_maxLat || !p_maxLat->isValid()) {
269 badLatLonValues.append(
"MaximumLatitude");
270 badLatLonRange =
true;
273 if (!p_minLon || !p_minLon->isValid()) {
274 badLatLonValues.append(
"MinimumLongitude");
275 badLatLonRange =
true;
278 if (!p_maxLon || !p_maxLon->isValid()) {
279 badLatLonValues.append(
"MaximumLongitude");
280 badLatLonRange =
true;
284 if (badLatLonRange) {
285 IString msg =
"Could not determine values for [";
286 for (
int i = 0; i < badLatLonValues.size(); i++) {
290 msg += badLatLonValues[i];
293 msg +=
"], please specify them explicitly";
297 throw IException(IException::Unknown, msg, _FILEINFO_);
301 p_reinitialize =
true;
306 Latitude::AllowPastPole);
310 if (!latRes.
isValid() || latRes <=
Angle(0, Angle::Degrees)) {
311 latRes =
Angle(p_defaultResolution,
315 if (!lonRes.
isValid() || lonRes <=
Angle(0, Angle::Degrees)) {
316 lonRes =
Angle(p_defaultResolution,
320 Latitude endLat =
Latitude((
long)((*p_maxLat - startLat) / latInc) * latInc + startLat,
323 (long)((*p_maxLon - startLon) / lonInc) * lonInc + startLon;
326 double numSteps = (double)((endLat - startLat) / latInc) + 1;
327 numSteps += (double)((endLon - startLon) / lonInc) + 1;
330 IString msg =
"No gridlines would intersect the image";
331 throw IException(IException::Programmer, msg, _FILEINFO_);
342 for (; latStep <= endLat + latInc / 2; latStep += latInc) {
343 unsigned int previousX = 0;
344 unsigned int previousY = 0;
345 bool havePrevious =
false;
347 for (
Longitude lon = *p_minLon; lon <= *p_maxLon; lon += latRes) {
350 bool valid = GetXY(latStep, lon, x, y);
352 if (valid && havePrevious) {
353 if (previousX != x || previousY != y) {
354 DrawLineOnGrid(previousX, previousY, x, y,
true);
358 havePrevious = valid;
368 for (
Longitude lon = startLon; lon <= endLon + lonInc / 2; lon += lonInc) {
369 unsigned int previousX = 0;
370 unsigned int previousY = 0;
371 bool havePrevious =
false;
377 for (; latStep <= *p_maxLat; latStep += lonRes) {
381 bool valid = GetXY(latStep, lon, x, y);
383 if (valid && havePrevious) {
384 if (previousX == x && previousY == y) {
388 DrawLineOnGrid(previousX, previousY, x, y,
false);
391 havePrevious = valid;
413 if (minLat.
isValid()) *p_minLat = minLat;
414 if (maxLat.
isValid()) *p_maxLat = maxLat;
415 if (minLon.
isValid()) *p_minLon = minLon;
416 if (maxLon.
isValid()) *p_maxLon = maxLon;
418 if (p_minLat->isValid() && p_maxLat->isValid() && *p_minLat > *p_maxLat) {
420 *p_minLat = *p_maxLat;
424 if (p_minLon->isValid() && p_maxLon->isValid() && *p_minLon > *p_maxLon) {
426 *p_minLon = *p_maxLon;
434 void GroundGrid::WalkBoundary() {
435 Angle latRes =
Angle(p_defaultResolution, Angle::Degrees);
436 Angle lonRes =
Angle(p_defaultResolution, Angle::Degrees);
448 for (; latStep <= maxLat; latStep += (maxLat - minLat)) {
449 unsigned int previousX = 0;
450 unsigned int previousY = 0;
451 bool havePrevious =
false;
453 for (
Longitude lon = minLon; lon <= maxLon; lon += latRes) {
456 bool valid = GetXY(latStep, lon, x, y);
458 if (valid && havePrevious) {
459 if (previousX != x || previousY != y) {
460 DrawLineOnGrid(previousX, previousY, x, y,
true);
464 havePrevious = valid;
471 for (
Longitude lon = minLon; lon <= maxLon; lon += (maxLon - minLon)) {
472 unsigned int previousX = 0;
473 unsigned int previousY = 0;
474 bool havePrevious =
false;
480 for (; latStep <= maxLat; latStep += lonRes) {
483 bool valid = GetXY(latStep, lon, x, y);
485 if (valid && havePrevious) {
486 if (previousX != x || previousY != y) {
487 DrawLineOnGrid(previousX, previousY, x, y,
false);
491 havePrevious = valid;
510 bool GroundGrid::PixelOnGrid(
int x,
int y,
bool latGrid) {
511 if (x < 0)
return false;
512 if (y < 0)
return false;
514 if (x >= (
int)p_width)
return false;
515 if (y >= (
int)p_height)
return false;
517 return GetGridBit(x, y, latGrid);
529 bool GroundGrid::PixelOnGrid(
int x,
int y) {
530 if (x < 0)
return false;
531 if (y < 0)
return false;
533 if (x >= (
int)p_width)
return false;
534 if (y >= (
int)p_height)
return false;
536 return GetGridBit(x, y,
true);
619 unsigned int &x,
unsigned int &y) {
620 if (!GroundMap())
return false;
622 if (!GroundMap()->SetUnboundGround(lat, lon))
return false;
625 if (!GroundMap()->SetGround(lat, lon))
return false;
627 if (p_groundMap->Sample() < 0.5 || p_groundMap->Line() < 0.5)
return false;
628 if (p_groundMap->Sample() < 0.5 || p_groundMap->Line() < 0.5)
return false;
630 x = (int)(p_groundMap->Sample() - 0.5);
631 y = (int)(p_groundMap->Line() - 0.5);
633 if (x >= p_width || y >= p_height)
return false;
655 void GroundGrid::SetGridBit(
unsigned int x,
unsigned int y,
bool latGrid) {
656 unsigned long bitPosition = (y * p_width) + x;
657 unsigned long byteContainer = bitPosition / 8;
658 unsigned int bitOffset = bitPosition % 8;
660 if (byteContainer > p_gridSize)
return;
663 char &importantByte = p_grid[byteContainer];
664 importantByte |= (1 << bitOffset);
666 else if (latGrid && p_latLinesGrid) {
667 char &importantByte = p_latLinesGrid[byteContainer];
668 importantByte |= (1 << bitOffset);
670 else if (!latGrid && p_lonLinesGrid) {
671 char &importantByte = p_lonLinesGrid[byteContainer];
672 importantByte |= (1 << bitOffset);
675 IString msg =
"GroundGrid::SetGridBit no grids available";
676 throw IException(IException::Programmer, msg, _FILEINFO_);
691 bool GroundGrid::GetGridBit(
unsigned int x,
unsigned int y,
bool latGrid) {
692 unsigned long bitPosition = (y * p_width) + x;
693 unsigned long byteContainer = bitPosition / 8;
694 unsigned int bitOffset = bitPosition % 8;
696 if (byteContainer > p_gridSize)
return false;
701 char &importantByte = p_grid[byteContainer];
702 result = (importantByte >> bitOffset) & 1;
704 else if (latGrid && p_latLinesGrid) {
705 char &importantByte = p_latLinesGrid[byteContainer];
706 result = (importantByte >> bitOffset) & 1;
708 else if (!latGrid && p_lonLinesGrid) {
709 char &importantByte = p_lonLinesGrid[byteContainer];
710 result = (importantByte >> bitOffset) & 1;
713 IString msg =
"GroundGrid::GetGridBit no grids available";
714 throw IException(IException::Programmer, msg, _FILEINFO_);
730 void GroundGrid::DrawLineOnGrid(
unsigned int x1,
unsigned int y1,
731 unsigned int x2,
unsigned int y2,
736 SetGridBit(x1, y1, isLatLine);
739 double m = (double)dy / (
double)dx;
740 double b = y1 - m * x1;
742 dx = (x2 > x1) ? 1 : -1;
745 y1 = (int)(m * x1 + b + 0.5);
746 SetGridBit(x1, y1, isLatLine);