Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMake/External_FFmpeg.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ if(APPLE)
list(APPEND FFMPEG_CONFIGURE_COMMAND --sysroot=${CMAKE_OSX_SYSROOT} --disable-doc)
endif()

if(fletch_BUILD_CXX17)
list(APPEND FFMPEG_CONFIGURE_COMMAND --extra-cxxflags="-std=c++17")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused here - isn't FFmpeg written in C, not C++?

endif()

ExternalProject_Add(FFmpeg
URL ${FFmpeg_file}
DEPENDS ${ffmpeg_DEPENDS}
Expand Down
2 changes: 1 addition & 1 deletion CMake/External_OpenCV.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ if (CMAKE_COMPILER_IS_GNUCC AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
endif()

# OpenCV 3.3.0 has an option to enable C++ 11
if (fletch_BUILD_CXX11)
if (fletch_BUILD_CXX17)
list(APPEND OpenCV_EXTRA_BUILD_FLAGS -DENABLE_CXX11:BOOL=ON)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is -DENABLE_CXX11 still correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On older versions, yes, there is no enable 17 so enable 11 is the closest thing and we still want to enable it when using 17

endif()

Expand Down
1 change: 1 addition & 0 deletions CMake/External_VXL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ if (EXISTS ${VXL_patch})
set(VXL_PATCH_COMMAND ${CMAKE_COMMAND}
-DVXL_PATCH_DIR:PATH=${VXL_patch}
-DVXL_SOURCE_DIR:PATH=${fletch_BUILD_PREFIX}/src/VXL
-Dfletch_BUILD_CXX17:BOOL=${fletch_BUILD_CXX17}
-P ${VXL_patch}/Patch.cmake
)
endif()
Expand Down
1 change: 1 addition & 0 deletions CMake/External_libkml.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ExternalProject_Add(libkml
PATCH_COMMAND ${CMAKE_COMMAND}
-Dlibkml_patch:PATH=${fletch_SOURCE_DIR}/Patches/libkml
-Dlibkml_source:PATH=${fletch_BUILD_PREFIX}/src/libkml
-Dfletch_BUILD_CXX17:BOOL=${fletch_BUILD_CXX17}
-P ${fletch_SOURCE_DIR}/Patches/libkml/Patch.cmake
CMAKE_ARGS
${COMMON_CMAKE_ARGS}
Expand Down
4 changes: 2 additions & 2 deletions CMake/External_pybind11.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
if (NOT fletch_BUILD_CXX11)
message(FATAL_ERROR "CXX11 must be enabled to use pybind11")
if (NOT fletch_BUILD_CXX17)
message(FATAL_ERROR "CXX17 must be enabled to use pybind11")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove this if the default standard is changed from 98 -> 11?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no objections to changing the default to 11 if that doesn't mess up any other projects. I will always use the 17 option so it doesn't matter

endif()

if (fletch_ENABLE_CPython)
Expand Down
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ add_custom_target(fletch-build-install)

# Include CXX11 support
set(fletch_CXX_STANDARD_VERSION "98")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
set(fletch_CXX_STANDARD_VERSION "98")
set(fletch_CXX_STANDARD_VERSION "11")

Does this seem reasonable?

option(fletch_BUILD_CXX11 "" TRUE)
if (fletch_BUILD_CXX11)
set(fletch_CXX_STANDARD_VERSION "11")
option(fletch_BUILD_CXX17 "" TRUE)
if (fletch_BUILD_CXX17)
set(fletch_CXX_STANDARD_VERSION "17")
endif()

#
Expand Down
7 changes: 7 additions & 0 deletions Patches/VXL/Patch.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@ file(COPY ${VXL_PATCH_DIR}/core/vbl/vbl_array_2d.h
file(COPY ${VXL_PATCH_DIR}/v3p/openjpeg2/opj_includes.h
DESTINATION ${VXL_SOURCE_DIR}/v3p/openjpeg2/
)

# Fix C++17 compatibility: replace deprecated std::bind2nd with lambda
if(fletch_BUILD_CXX17)
file(COPY ${VXL_PATCH_DIR}/core/vil/algo/vil_gauss_filter.cxx
DESTINATION ${VXL_SOURCE_DIR}/core/vil/algo/
)
endif()
130 changes: 130 additions & 0 deletions Patches/VXL/core/vil/algo/vil_gauss_filter.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// This is core/vil/algo/vil_gauss_filter.cxx
#include <cmath>
#include <algorithm>
#include <functional>
#include "vil_gauss_filter.h"
//:
// \file
// \brief Functions to smooth an image
// \author Ian Scott

#ifdef _MSC_VER
# include <vcl_msvc_warnings.h>
#endif
#include <cassert>
#include <vnl/vnl_erf.h>
#include <vnl/vnl_double_2.h>
#include <vnl/vnl_real_polynomial.h>

vil_gauss_filter_5tap_params::vil_gauss_filter_5tap_params(double val_sigma)
{
sigma_ = val_sigma;
const double z = 1/(std::sqrt(2.0)*val_sigma);
filt0_ = vnl_erf(0.5 * z) - vnl_erf(-0.5 * z);
filt1_ = vnl_erf(1.5 * z) - vnl_erf(0.5 * z);
filt2_ = vnl_erf(2.5 * z) - vnl_erf(1.5 * z);

double five_tap_total = 2*(filt2_ + filt1_) + filt0_;
// double four_tap_total = filt2_ + 2*(filt1_) + filt0_;
// double three_tap_total = filt2_ + filt1_ + filt0_;

// Calculate 3 tap half Gaussian filter assuming constant edge extension
filt_edge0_ = (filt0_ + filt1_ + filt2_) / five_tap_total;
filt_edge1_ = filt1_ / five_tap_total;
filt_edge2_ = filt2_ / five_tap_total;
#if 0
filt_edge0_ = 1.0;
filt_edge1_ = 0.0;
filt_edge2_ = 0.0;
#endif
// Calculate 4 tap skewed Gaussian filter assuming constant edge extension
filt_pen_edge_n1_ = (filt1_+filt2_) / five_tap_total;
filt_pen_edge0_ = filt0_ / five_tap_total;
filt_pen_edge1_ = filt1_ / five_tap_total;
filt_pen_edge2_ = filt2_ / five_tap_total;

// Calculate 5 tap Gaussian filter
filt0_ = filt0_ / five_tap_total;
filt1_ = filt1_ / five_tap_total;
filt2_ = filt2_ / five_tap_total;

assert(filt_edge0_ >= filt_edge1_);
assert(filt_edge1_ >= filt_edge2_);
}


//: Generate an n-tap FIR filter from a Gaussian function.
// The filter uses the equation $k D^d \exp -\frac{x^2}{2\sigma^2} $,
// where D is the differential operator, and k is a normalising constant.
// \param diff The number of differential operators to apply to the filter.
// If you want just a normal gaussian, set diff to 0.
// \param sd The width of the gaussian.
//
// The taps will be calculated using the integral of the above equation over
// the pixel width. However, aliasing will reduce the meaningfulness of
// your filter when sd << (diff+1). In most applications you will
// want filter.size() ~= sd*7, which will avoid significant truncation,
// without wasting the outer taps on near-zero values.
void vil_gauss_filter_gen_ntap(double sd, unsigned diff,
std::vector<double> &filter)
{
std::size_t centre = filter.size()/2; // or just past centre if even length
double sum=0.0; // area under sampled curve.
double tap; // workspace

if (diff==0)
{
const double z = 1/(std::sqrt(2.0)*sd);
if (filter.size() % 2 == 0) // even length filter - off-centre
{
for (unsigned i=0 ; i<centre; ++i)
{
tap = vnl_erf((i+1.0) * z) - vnl_erf(i * z);
sum += tap;
filter[centre+i] = filter[centre-i-1] = tap;
}
sum *= 2.0;
}
else // odd length filter - centre on zero
{
for (unsigned i=1 ; i<=centre; ++i)
{
tap = vnl_erf((i+0.5) * z) - vnl_erf((i-0.5) * z);
sum += tap;
filter[centre+i] = filter[centre-i] = tap;
}
sum *= 2.0;
tap = vnl_erf(0.5 * z) - vnl_erf(-0.5 * z);
sum += tap;
filter[centre] = tap;
}
}
else
{
const double offset = filter.size() % 2 == 0 ? 0.0 : -0.5;
vnl_real_polynomial poly(1.0);
const double eta = -0.5/(sd*sd);
const vnl_real_polynomial d_gauss(vnl_double_2(eta, 0.0).as_ref());
for (unsigned i=1; i<diff; ++i)
{
// Evaluate d/dx (poly * gauss) where gauss = exp(-0.5*x^2/sd^2)
// n.b. d/dx gauss = d_gauss * gauss
poly = poly * d_gauss + poly.derivative();
}

for (int i=-(int)centre ; i+centre<filter.size(); ++i)
{
tap = poly.evaluate(i+1.0+offset)*std::exp(eta*(i+1.0+offset)*(i+1.0+offset))
- poly.evaluate(i+ offset)*std::exp(eta*(i+ offset)*(i+ offset));
sum += std::abs(tap);
filter[centre+i] = tap;
}
}

// normalise the result
assert(sum >= 0.0);
double norm = 1.0 / sum;
// Use lambda instead of deprecated std::bind2nd for C++17 compatibility
std::transform(filter.begin(), filter.end(), filter.begin(),
[norm](double x) { return x * norm; });
}
8 changes: 8 additions & 0 deletions Patches/libkml/Patch.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ file(COPY
${libkml_patch}/unzip.c
DESTINATION ${libkml_source}/third_party/zlib-1.2.3/contrib/minizip
)

# Fix C++17 compatibility: remove deprecated std::binary_function
if(fletch_BUILD_CXX17)
file(COPY
${libkml_patch}/convenience/feature_list.cc
DESTINATION ${libkml_source}/src/kml/convenience/
)
endif()
158 changes: 158 additions & 0 deletions Patches/libkml/convenience/feature_list.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
// Copyright 2008, Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of Google Inc. nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// This file contains the implementation of the FeatureList class.
// While STL list is not directly exposed the name FeatureList is as such
// to suggest list-like performance.

#include "kml/convenience/feature_list.h"
#include <stdlib.h>
#include <algorithm>
#include <fstream>
#include <list>
#include <sstream>
#include "kml/dom.h"
#include "kml/convenience/convenience.h"
#include "kml/engine.h"

using kmldom::ContainerPtr;
using kmldom::DataPtr;
using kmldom::ExtendedDataPtr;
using kmldom::FeaturePtr;
using kmldom::LatLonAltBoxPtr;
using kmldom::KmlFactory;
using kmldom::RegionPtr;
using kmlengine::Bbox;

namespace kmlconvenience {

static const char* kFeatureScoreName = "kml.FeatureScore";

int GetFeatureScore(FeaturePtr feature) {
string score;
if (GetExtendedDataValue(feature, kFeatureScoreName, &score)) {
return atoi(score.c_str());
}
return 0;
}

void SetFeatureScore(const string& score, FeaturePtr feature) {
SetExtendedDataValue(kFeatureScoreName, score, feature);
}

void FeatureList::PushBack(const FeaturePtr& feature) {
if (feature) {
feature_list_.push_back(feature);
}
}

size_t FeatureList::Save(ContainerPtr container) const {
size_t count = 0;
feature_list_t::const_iterator iter;
for (iter = feature_list_.begin(); iter != feature_list_.end(); ++iter) {
++count;
container->add_feature(*iter);
}
return count;
}

size_t FeatureList::BboxSplit(const Bbox& bbox, size_t max,
FeatureList* output) {
if (max == 0) { // "0" has the special meaning of "all".
max = feature_list_.size();
}
size_t count = 0;
// See Effective STL, by Scott Meyers, Item 9, page 46. A while loop is used
// instead of for to make explicit the advancement of iter within the loop.
// If the item is erased then list.erase() returns the advanced iter,
// else we advance it oursevles.
feature_list_t::iterator iter = feature_list_.begin();
while (iter != feature_list_.end()) {
double lat, lon;
if (kmlengine::GetFeatureLatLon(*iter, &lat, &lon) &&
bbox.Contains(lat,lon)) {
if (output) {
output->PushBack(*iter);
}
iter = feature_list_.erase(iter); // list.erase() advances to next.
++count;
if (--max == 0) { // max guaranteed to be > 0.
break;
}
} else {
++iter; // Not erasing so we advance to next explicitely.
}
}
return count;
}

size_t FeatureList::RegionSplit(const RegionPtr& region, size_t max,
FeatureList* output) {
if (region && region->has_latlonaltbox()) {
LatLonAltBoxPtr llab = region->get_latlonaltbox();
Bbox bbox(llab->get_north(), llab->get_south(),
llab->get_east(), llab->get_west());
return BboxSplit(bbox, max, output);
}
return 0;
}

// This function object is used by STL sort() to order Features
// by score. Results in sort of highest score first.
// Note: std::binary_function was removed in C++17, but it was only used
// for type definitions that are not required for the functor to work.
struct CompareFeatures {
bool operator()(const kmldom::FeaturePtr& a,
const kmldom::FeaturePtr& b) const {
return GetFeatureScore(a) > GetFeatureScore(b);
}
};

// Sort the internal list of features based on score.
void FeatureList::Sort() {
// See Effective STL, by Scott Meyers, Item 44, page 192.
feature_list_.sort(CompareFeatures());
}

// Return the number of features held in the internal list.
size_t FeatureList::Size() const {
return feature_list_.size();
}

// Expand the bounds of the given bbox based on the features in the list.
void FeatureList::ComputeBoundingBox(Bbox* bbox) const {
if (!bbox) {
return;
}
feature_list_t::const_iterator iter;
for (iter = feature_list_.begin(); iter != feature_list_.end(); ++iter) {
double lat, lon;
if (kmlengine::GetFeatureLatLon(*iter, &lat, &lon)) {
bbox->ExpandLatLon(lat, lon);
}
}
}

} // end namespace kmlconvenience
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ want the C++ libraries built.
``fletch_ENABLE_ALL_PACKAGES`` Turn all packages on
(you can turn some back off later)
``fletch_BUILD_WITH_PYTHON`` Build all the packages with Python support
``fletch_BUILD_CXX11`` Build using C++11 compiler options.
``fletch_BUILD_CXX17`` Build using C++17 compiler options.
This is required for KWIVER.
``fletch_DOWNLOAD_DIR`` This is where Fletch will cache downloaded source
source code tarballs (default is ``src/Downloads``)
Expand Down