35 static const string MASK_EXCLUDE_KW =
"exclude_regions";
36 static const string MASK_INCLUDE_KW =
"include_regions";
37 static const string SLOPE_OUTPUT_FILE_KW =
"slope_output_file";
38 static const string POINT_CLOUD_FILE_KW =
"point_clouds";
39 static const string HLZ_CODING_KW =
"hlz_coding";
40 static const string LZ_MIN_RADIUS_KW =
"min_lz_radius";
41 static const string ROUGHNESS_THRESHOLD_KW =
"max_roughness";
42 static const string SLOPE_THRESHOLD_KW =
"max_slope";
45 "Computes bitmap of helicopter landing zones given ROI and DEM.";
50 : m_slopeThreshold(7.0),
51 m_roughnessThreshold(0.5),
55 m_marginalLzValue(128),
57 m_useLsFitMethod(
true),
75 usageString +=
" hlz [options] <output-image>";
80 "List of raster image(s) representing mask files that defines regions to be excluded from " 81 "HLZ solutions. Any non-zero pixel is excluded Multiple filenames must be comma-separated.");
83 "Specifies the pixel values (0-255) for the output product corresponding to bad, marginal, " 84 "and good landing zones, respectively. Defaults to bad=255 (null), marginal=128, and " 87 "List of raster image(s) representing mask files that defines regions where the HLZs ." 88 "identified must overlap. Any non-zero pixel represents an inclusion zone. Multiple " 89 "filenames must be comma-separated.");
91 "Generates a slope byproduct image (floating point degrees) to the specified filename. " 92 "Only valid if normal-vector method used (i.e., --ls-fit option NOT specified)");
94 "Specifies ancillary point-cloud data file(s) for level-2 search for obstructions. " 95 "Must be comma-separated file names.");
97 "Specifies minimum radius of landing zone. Defaults to 25 m. ");
99 "Specifies the terrain roughness threshold (meters). This is the maximum deviation from a " 100 "flat plane permitted. Defaults to 0.5 m. Valid only with --ls-fit specified.");
102 "Threshold for acceptable landing zone terrain slope. Defaults to 7 deg.");
104 "Number of threads. Defaults to use single core. For engineering/debug purposes.");
106 "Slope is computed from the normal vector using neighboring posts instead of " 107 "least-squares fit to a plane (prefered). For engineering/debug purposes.");
125 vector<ossimString> maskFnames;
126 ap.
read(
"--exclude-regions", maskFnames);
129 key = MASK_EXCLUDE_KW;
134 if (ap.
read(
"--hlz-coding", sp1, sp2, sp3) || ap.
read(
"--values", sp1, sp2, sp3))
137 value<<ts1<<
" "<<ts2<<
" "<<ts3;
142 ap.
read(
"--include-regions", maskFnames);
145 key = MASK_INCLUDE_KW;
150 if ( ap.
read(
"--output-slope", sp1))
153 vector<ossimString> pcFnames;
154 ap.
read(
"--point-clouds", pcFnames);
157 key = POINT_CLOUD_FILE_KW;
162 if (ap.
read(
"--min-lz-radius", sp1) || ap.
read(
"--rlz", sp1))
165 if (ap.
read(
"--max-roughness", sp1) || ap.
read(
"--roughness", sp1))
168 if (ap.
read(
"--max-slope", sp1) || ap.
read(
"--slope", sp1))
171 if (ap.
read(
"--threads", sp1))
177 if (ap.
read(
"--use_slope"))
205 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" The HLZ minimum radius is too small.";
220 vector<ossimString> values = value.
split(
" ");
221 if (values.size() == 3)
229 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Unexpected number of values encountered for keyword <" 230 <<HLZ_CODING_KW<<
">.";
244 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Encountered NaNs in AOI."<<ends;
265 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Error encountered allocating output image buffer.";
302 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Invalid GSD: "<<
m_gsd;
310 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" The DEM provided does not have sufficient" 311 " resolution to determine HLZs.";
327 key = POINT_CLOUD_FILE_KW;
334 if (!pc_handler.
valid())
336 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Error loading point cloud file <"<<pc_file<<
">.";
349 <<
"ossimHLZUtil::loadPcFile() WARNING: point-cloud file <" << pc_file <<
"> " 350 <<
"does not overlap the output ROI." << endl;
365 key = MASK_EXCLUDE_KW;
368 if (mask_file.
empty())
371 MaskSource mask_image (
this, mask_file,
true);
379 key = MASK_INCLUDE_KW;
382 if (mask_file.
empty())
386 MaskSource mask_image (
this, mask_file,
false);
435 xmsg<<
"ossimHlzUtil:"<<__LINE__<<
" Error encountered allocating output image buffer.";
456 const double CHIP_STEP_FACTOR = 0.25;
469 for (chip_origin.
y = min_y; chip_origin.
y <= max_y; chip_origin.
y += dem_step)
471 for (chip_origin.
x = min_x; chip_origin.
x <= max_x; chip_origin.
x += dem_step)
473 std::shared_ptr<ossimHlzTool::PatchProcessorJob> job = 0;
475 job = std::make_shared<ossimHlzTool::LsFitPatchProcessorJob>(
this, chip_origin, chipId++);
477 job = std::make_shared<ossimHlzTool::NormPatchProcessorJob>(
this, chip_origin, chipId++);
489 std::shared_ptr<ossimJobMultiThreadQueue> jobMtQueue =
490 std::make_shared<ossimJobMultiThreadQueue>(
nullptr,
m_numThreads);
491 std::shared_ptr<ossimJobQueue> jobQueue = jobMtQueue->getJobQueue();
498 for (chip_origin.
y = min_y; chip_origin.
y <= max_y; ++chip_origin.
y)
500 for (chip_origin.
x = min_x; chip_origin.
x <= max_x; ++chip_origin.
x)
503 std::shared_ptr<ossimHlzTool::PatchProcessorJob> job = 0;
505 job = std::make_shared<ossimHlzTool::LsFitPatchProcessorJob>(
this, chip_origin, chipId++);
507 job = std::make_shared<ossimHlzTool::NormPatchProcessorJob>(
this, chip_origin, chipId++);
508 jobQueue->add(job,
false);
510 qsize = jobQueue->size();
516 while (jobMtQueue->hasJobsToProcess() || jobMtQueue->numberOfBusyThreads())
518 qsize = jobMtQueue->getJobQueue()->size();
544 "writing slope image to <"<<
m_slopeFile<<
">."<<endl;
552 : m_hlzUtil (hlzUtil),
553 m_demPatchUL (origin),
555 m_nullValue (hlzUtil->m_demBuffer->getNullPix(0))
563 bool passed = level1Test() && level2Test() && maskTest();
566 std::lock_guard<std::mutex> lock (m_bufMutex);
567 for (p.
y = m_demPatchUL.y; p.
y < m_demPatchLR.y; ++p.
y)
569 for (p.
x = m_demPatchUL.x; p.
x < m_demPatchLR.x; ++p.
x)
571 if (passed && (m_status == 2))
572 m_hlzUtil->m_outBuffer->setValue(p.
x, p.
y, m_hlzUtil->m_goodLzValue);
573 else if (passed && (m_status == 1))
574 m_hlzUtil->m_outBuffer->setValue(p.
x, p.
y, m_hlzUtil->m_marginalLzValue);
576 m_hlzUtil->m_outBuffer->setValue(p.
x, p.
y, m_hlzUtil->m_badLzValue);
587 for (p.
y = m_demPatchUL.y; p.
y < m_demPatchLR.y; ++p.
y)
589 y_meters = p.
y*m_hlzUtil->m_gsd.y;
590 for (p.
x = m_demPatchUL.x; p.
x < m_demPatchLR.x; ++p.
x)
592 z = m_hlzUtil->m_demBuffer->getPix(p, 0);
595 m_plane->addSample(p.
x*m_hlzUtil->m_gsd.x, y_meters, z);
598 if (!m_plane->solveLS())
604 m_plane->getLSParms(a, b, c);
605 double z_proj = 1.0 / sqrt(a*a + b*b + 1.0);
607 if (theta > m_hlzUtil->m_slopeThreshold)
612 for (p.
y = m_demPatchUL.y; (p.
y < m_demPatchLR.y); ++p.
y)
614 for (p.
x = m_demPatchUL.x; (p.
x < m_demPatchLR.x); ++p.
x)
616 z = m_hlzUtil->m_demBuffer->getPix(p, 0);
617 distance = fabs(z_proj * (a*p.
x + b*p.
y + c - z));
618 if (
distance > m_hlzUtil->m_roughnessThreshold)
633 for (p.
y = m_demPatchUL.y; p.
y < m_demPatchLR.y; ++p.
y)
635 for (p.
x = m_demPatchUL.x; p.
x < m_demPatchLR.x; ++p.
x)
637 theta = m_hlzUtil->m_demBuffer->getPix(p, 0);
638 if ((theta == m_nullValue) ||
ossim::isnan(theta) || (theta > m_hlzUtil->m_slopeThreshold))
650 if (m_hlzUtil->m_pcSources.empty())
658 m_hlzUtil->m_geom->localToWorld(
ossimDpt(m_demPatchUL), chipUlGpt);
659 m_hlzUtil->m_geom->localToWorld(
ossimDpt(m_demPatchLR), chipLrGpt);
677 if (pc_block.
empty())
680 bool found_obstruction =
false;
686 for (
ossim_uint32 i=0; (i<numPoints) && !found_obstruction; ++i)
692 found_obstruction =
true;
697 if (!found_obstruction)
706 if (m_hlzUtil->m_maskSources.empty())
709 ossimIrect chipRect (m_demPatchUL, m_demPatchLR);
710 vector<MaskSource>::iterator mask_source = m_hlzUtil->m_maskSources.begin();
711 bool test_passed =
true;
715 while ((mask_source != m_hlzUtil->m_maskSources.end()) && test_passed)
718 for (p.
y = m_demPatchUL.y; (p.
y < m_demPatchLR.y) && test_passed; ++p.
y)
720 for (p.
x = m_demPatchUL.x; (p.
x < m_demPatchLR.x) && test_passed; ++p.
x)
722 mask_value = mask_data->
getPix(p);
723 if (( mask_value && mask_source->exclude) || (!mask_value && !mask_source->exclude))
736 : exclude (exclusion)
void fill(ossim_uint32 band, ossim_float64 value)
will fill the entire band with the value.
std::string getApplicationName() const
return the application name, as specified by argv[0]
void addCommandLineOption(const ossimString &option, const ossimString &explanation)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
Within the image chain will pass the head of the list.
std::basic_ostringstream< char > ostringstream
Class for char output memory streams.
virtual void setImageRectangle(const ossimIrect &rect)
Filter class for computing the slope image of the input image connection.
Represents serializable keyword/value map.
const std::string & findKey(const std::string &key) const
Find methods that take std::string(s).
const char * find(const char *key) const
bool read(const std::string &str)
search for an occurance of a string in the argument list, on sucess remove that occurance from the li...
double nan()
Method to return ieee floating point double precision NAN.
ossim_uint32 height() const
void addList(const ossimKeywordlist &src, bool overwrite=true)
static ossimString toString(bool aValue)
Numeric to string methods.
void setImage(ossimRefPtr< ossimImageData > image)
virtual void setPercentComplete(double percentComplete)
const ossimIpt & ul() const
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual void getBounds(ossimGrect &bounds) const
void addPair(const std::string &key, const std::string &value, bool overwrite=true)
ossim_float64 hgt
Height in meters above the ellipsiod.
ossim_uint32 toUInt32() const
void setCommandLineUsage(const ossimString &explanation)
virtual ossim_float64 getPix(const ossimIpt &position, ossim_uint32 band=0) const
Will return the pixel at location position.
ossimApplicationUsage * getApplicationUsage()
void setImageSize(const ossimIpt &size)
static void sleepInMicroSeconds(ossim_uint64 micros)
Utility method to allow one to sleep in microseconds.
virtual void initialize()
Initialize the data buffer.
OSSIM_DLL ossim_uint32 getNumberOfThreads()
Get the number threads to use from ossimPreferences or ossim::Thread.
virtual ossimPointCloudHandler * open(const ossimFilename &fileName) const
static ossimImageDataFactory * instance()
virtual void setGeotiffFlag(bool flag)
bool localToWorld(const ossimDpt &local_pt, ossimGpt &world_pt) const
Exposes the 3D projection from image to world coordinates.
unsigned int ossim_uint32
const char * chars() const
For backward compatibility.
virtual void setImageGeometry(ossimImageGeometry *geom)
Default implementation sets geometry of the first input to the geometry specified.
const ossimIpt & lr() const
virtual bool add(ossimConnectableObject *source)
Will return true or false if an image source was added to the chain.
virtual ossim_int32 connectMyInputTo(ossimConnectableObject *inputObject, bool makeOutputConnection=true, bool createEventFlag=true)
Will try to connect this objects input to the passed in object.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
virtual ossim_uint32 size() const
Returns allocated size.
void setSlopeType(SlopeType t)
static ossimPointCloudHandlerRegistry * instance()
virtual void setFilename(const ossimFilename &file)
virtual void getBlock(const ossimGrect &bounds, ossimPointBlock &block) const
Fetches the block of points inside the block bounds.
virtual void setAreaOfInterest(const ossimIrect &inputRect)
virtual void initialize()=0
Base class for all point-cloud file readers.
float distance(double lat1, double lon1, double lat2, double lon2, int units)
bool intersects(const ossimGrect &rect) const
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool execute()
Calls: writeFile() writeMetaDataFiles()
const std::string & string() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.