Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quantized-mesh output support #64

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
987b666
Quantized-mesh output support
ahuarte47 Mar 27, 2018
3a804a9
Fix nodata values
ahuarte47 Mar 27, 2018
358888c
Fix 'Integer Overflow' error when creating tiles of low levels
ahuarte47 Apr 7, 2018
c448bc5
Option to write 'Oct-Encoded Per-Vertex Normals' for Terrain Lighting
ahuarte47 Apr 11, 2018
1f5c1fb
Refactoring of code to easily write new output formats
ahuarte47 May 11, 2018
3471487
Add 'octvertexnormals' entry to layer.json file
ahuarte47 May 17, 2018
2ebd493
Fix available root tiles in layer.json with 'CesiumFriendly' param
ahuarte47 May 17, 2018
4bb78ba
Create missing root tiles from scratch
ahuarte47 May 24, 2018
ce2da57
README adjustments
ahuarte47 Oct 20, 2018
a1a9ce4
Fix visible walls at terrain tiles boundary
ahuarte47 Jul 18, 2019
b5261b0
Speedup of reading in MeshTiler taking care of Neighbours
ahuarte47 Jul 21, 2019
ade3675
Ignore Neighbors that are out of valid tile extent
ahuarte47 Jul 21, 2019
9b1b6ff
Do not share a RasterHeightsCache between tiler threads
ahuarte47 Aug 30, 2019
52d45da
Update define GDAL3x in GDALTiler.cpp
ahuarte47 Oct 8, 2019
3bb824d
Update define GDAL3x in GDALTiler.cpp (2)
ahuarte47 Oct 8, 2019
fac3e39
Revert "Update define GDAL3x in GDALTiler.cpp (2)"
ahuarte47 Nov 26, 2019
82e1537
Revert "Update define GDAL3x in GDALTiler.cpp"
ahuarte47 Nov 26, 2019
84d7d49
Add suppot for GDAL versions >= 2.2.0 and <3.0.0
ahuarte47 Nov 26, 2019
c690929
Disable multi-threaded warping
ahuarte47 Feb 25, 2020
495fac0
Fix raster overview selection
ahuarte47 Feb 25, 2020
08d105f
Make gdaloverviewdataset.cpp up-to-date
koriel-angelswing Jun 5, 2020
9a60f0d
SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER) for all
koriel-angelswing Jun 9, 2020
d304da1
Add preprocessor to check GDAL version > 3
devkoriel Jun 9, 2020
363131a
Merge pull request #1 from angelswing-team/fix-#DPP-26
koriel-angelswing Jun 9, 2020
7b73a36
Merge pull request #4 from angelswing-team/master-quantized-mesh
ahuarte47 Jun 9, 2020
bf5fe56
GdalOverviewDataset 2x and 3x versions
ahuarte47 Jun 9, 2020
428155b
There is no catch of the CTBException* exception type, modified to th…
ShawayL Mar 4, 2023
dd55fc7
fix an index logic error
ShawayL Mar 4, 2023
7006484
Merge pull request #5 from ShawayL/master-quantized-mesh
ahuarte47 Mar 5, 2023
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
36 changes: 20 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,26 @@ Usage: ctb-tile [options] GDAL_DATASOURCE

Options:

-V, --version output program version
-h, --help output help information
-o, --output-dir <dir> specify the output directory for the tiles (defaults to working directory)
-f, --output-format <format> specify the output format for the tiles. This is either `Terrain` (the default) or any format listed by `gdalinfo --formats`
-p, --profile <profile> specify the TMS profile for the tiles. This is either `geodetic` (the default) or `mercator`
-c, --thread-count <count> specify the number of threads to use for tile generation. On multicore machines this defaults to the number of CPUs
-t, --tile-size <size> specify the size of the tiles in pixels. This defaults to 65 for terrain tiles and 256 for other GDAL formats
-s, --start-zoom <zoom> specify the zoom level to start at. This should be greater than the end zoom level
-e, --end-zoom <zoom> specify the zoom level to end at. This should be less than the start zoom level and >= 0
-r, --resampling-method <algorithm> specify the raster resampling algorithm. One of: nearest; bilinear; cubic; cubicspline; lanczos; average; mode; max; min; med; q1; q3. Defaults to average.
-n, --creation-option <option> specify a GDAL creation option for the output dataset in the form NAME=VALUE. Can be specified multiple times. Not valid for Terrain tiles.
-z, --error-threshold <threshold> specify the error threshold in pixel units for transformation approximation. Larger values should mean faster transforms. Defaults to 0.125
-m, --warp-memory <bytes> The memory limit in bytes used for warp operations. Higher settings should be faster. Defaults to a conservative GDAL internal setting.
-R, --resume Do not overwrite existing files
-q, --quiet only output errors
-v, --verbose be more noisy
-V, --version output program version
-h, --help output help information
-o --output-dir <dir> specify the output directory for the tiles (defaults to working directory)
-f --output-format <format> specify the output format for the tiles. This is either `Terrain` (the default), `Mesh` (Chunked LOD mesh), or any format listed by `gdalinfo --formats`
-p --profile <profile> specify the TMS profile for the tiles. This is either `geodetic` (the default) or `mercator`
-c --thread-count <count> specify the number of threads to use for tile generation. On multicore machines this defaults to the number of CPUs
-t --tile-size <size> specify the size of the tiles in pixels. This defaults to 65 for terrain tiles and 256 for other GDAL formats
-s --start-zoom <zoom> specify the zoom level to start at. This should be greater than the end zoom level
-e --end-zoom <zoom> specify the zoom level to end at. This should be less than the start zoom level and >= 0
-r --resampling-method <algorithm> specify the raster resampling algorithm. One of: nearest; bilinear; cubic; cubicspline; lanczos; average; mode; max; min; med; q1; q3. Defaults to average.
-n --creation-option <option> specify a GDAL creation option for the output dataset in the form NAME=VALUE. Can be specified multiple times. Not valid for Terrain tiles.
-z --error-threshold <threshold> specify the error threshold in pixel units for transformation approximation. Larger values should mean faster transforms. Defaults to 0.125
-m --warp-memory <bytes> specify the memory limit in bytes used for warp operations. Higher settings should be faster. Defaults to a conservative GDAL internal setting.
-R --resume flag do not overwrite existing files
-g --mesh-qfactor <factor> specify the factor to multiply the estimated geometric error to convert heightmaps to irregular meshes. Larger values should mean minor quality. Defaults to 1.0
-l --layer flag only outputs the layer.json metadata file
-C --cesium-friendly flag forces the creation of missing root tiles to be CesiumJS-friendly
-N --vertex-normals flag writes 'Oct-Encoded Per-Vertex Normals' for Terrain Lighting, only for `Mesh` format
-q --quiet flag outputs only errors
-v --verbose flag outputs more noisy
```

#### Recommendations
Expand Down
184 changes: 184 additions & 0 deletions src/BoundingSphere.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#ifndef BBSPHERE_HPP
#define BBSPHERE_HPP

/*******************************************************************************
* Copyright 2018 GeoData <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*******************************************************************************/

/**
* @file BoundingSphere.hpp
* @brief This declares and defines the `BoundingSphere` class
* @author Alvaro Huarte <[email protected]>
*/

#include <vector>
#include <limits>

#include "Coordinate3D.hpp"
#include "types.hpp"

namespace ctb {
template <class T> class BoundingSphere;
template <class T> class BoundingBox;
}

/// A spherical bounding region which is defined by a center point and a radius
template <class T>
class ctb::BoundingSphere {
public:
Coordinate3D<T> center; ///< The center of the BoundingSphere
double radius; ///< The radius of the BoundingSphere

/// Create an empty BoundingSphere
BoundingSphere() {
}
/// Create a BoundingSphere from the specified point stream
BoundingSphere(const std::vector<Coordinate3D<T>> &points) {
fromPoints(points);
}

/// Calculate the center and radius from the specified point stream
/// Based on Ritter's algorithm
void fromPoints(const std::vector<Coordinate3D<T>> &points) {
const T MAX = std::numeric_limits<T>::infinity();
const T MIN = -std::numeric_limits<T>::infinity();

Coordinate3D<T> minPointX(MAX, MAX, MAX);
Coordinate3D<T> minPointY(MAX, MAX, MAX);
Coordinate3D<T> minPointZ(MAX, MAX, MAX);
Coordinate3D<T> maxPointX(MIN, MIN, MIN);
Coordinate3D<T> maxPointY(MIN, MIN, MIN);
Coordinate3D<T> maxPointZ(MIN, MIN, MIN);

// Store the points containing the smallest and largest component
// Used for the naive approach
for (int i = 0, icount = points.size(); i < icount; i++) {
const Coordinate3D<T> &point = points[i];

if (point.x < minPointX.x) minPointX = point;
if (point.y < minPointY.y) minPointY = point;
if (point.z < minPointZ.z) minPointZ = point;
if (point.x > maxPointX.x) maxPointX = point;
if (point.y > maxPointY.y) maxPointY = point;
if (point.z > maxPointZ.z) maxPointZ = point;
}

// Squared distance between each component min and max
T xSpan = (maxPointX - minPointX).magnitudeSquared();
T ySpan = (maxPointY - minPointY).magnitudeSquared();
T zSpan = (maxPointZ - minPointZ).magnitudeSquared();

Coordinate3D<T> diameter1 = minPointX;
Coordinate3D<T> diameter2 = maxPointX;
T maxSpan = xSpan;
if (ySpan > maxSpan) {
diameter1 = minPointY;
diameter2 = maxPointY;
maxSpan = ySpan;
}
if (zSpan > maxSpan) {
diameter1 = minPointZ;
diameter2 = maxPointZ;
maxSpan = zSpan;
}

Coordinate3D<T> ritterCenter = Coordinate3D<T>(
(diameter1.x + diameter2.x) * 0.5,
(diameter1.y + diameter2.y) * 0.5,
(diameter1.z + diameter2.z) * 0.5
);
T radiusSquared = (diameter2 - ritterCenter).magnitudeSquared();
T ritterRadius = std::sqrt(radiusSquared);

// Initial center and radius (naive) get min and max box
Coordinate3D<T> minBoxPt(minPointX.x, minPointY.y, minPointZ.z);
Coordinate3D<T> maxBoxPt(maxPointX.x, maxPointY.y, maxPointZ.z);
Coordinate3D<T> naiveCenter = (minBoxPt + maxBoxPt) * 0.5;
T naiveRadius = 0;

for (int i = 0, icount = points.size(); i < icount; i++) {
const Coordinate3D<T> &point = points[i];

// Find the furthest point from the naive center to calculate the naive radius.
T r = (point - naiveCenter).magnitude();
if (r > naiveRadius) naiveRadius = r;

// Make adjustments to the Ritter Sphere to include all points.
T oldCenterToPointSquared = (point - ritterCenter).magnitudeSquared();

if (oldCenterToPointSquared > radiusSquared) {
T oldCenterToPoint = std::sqrt(oldCenterToPointSquared);
ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;

// Calculate center of new Ritter sphere
T oldToNew = oldCenterToPoint - ritterRadius;
ritterCenter.x = (ritterRadius * ritterCenter.x + oldToNew * point.x) / oldCenterToPoint;
ritterCenter.y = (ritterRadius * ritterCenter.y + oldToNew * point.y) / oldCenterToPoint;
ritterCenter.z = (ritterRadius * ritterCenter.z + oldToNew * point.z) / oldCenterToPoint;
}
}

// Keep the naive sphere if smaller
if (naiveRadius < ritterRadius) {
center = ritterCenter;
radius = ritterRadius;
}
else {
center = naiveCenter;
radius = naiveRadius;
}
}
};

/// A bounding box which is defined by a pair of minimum and maximum coordinates
template <class T>
class ctb::BoundingBox {
public:
Coordinate3D<T> min; ///< The min coordinate of the BoundingBox
Coordinate3D<T> max; ///< The max coordinate of the BoundingBox

/// Create an empty BoundingBox
BoundingBox() {
}
/// Create a BoundingBox from the specified point stream
BoundingBox(const std::vector<Coordinate3D<T>> &points) {
fromPoints(points);
}

/// Calculate the BBOX from the specified point stream
void fromPoints(const std::vector<Coordinate3D<T>> &points) {
const T MAX = std::numeric_limits<T>::infinity();
const T MIN = -std::numeric_limits<T>::infinity();
min.x = MAX;
min.y = MAX;
min.z = MAX;
max.x = MIN;
max.y = MIN;
max.z = MIN;

for (int i = 0, icount = points.size(); i < icount; i++) {
const Coordinate3D<T> &point = points[i];

if (point.x < min.x) min.x = point.x;
if (point.y < min.y) min.y = point.y;
if (point.z < min.z) min.z = point.z;
if (point.x > max.x) max.x = point.x;
if (point.y > max.y) max.y = point.y;
if (point.z > max.z) max.z = point.z;
}
}
};

#endif /* BBSPHERE_HPP */
21 changes: 21 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,47 @@ include_directories(${ZLIB_INCLUDE_DIRS})
add_library(ctb SHARED
GDALTile.cpp
GDALTiler.cpp
GDALDatasetReader.cpp
CTBFileTileSerializer.cpp
CTBFileOutputStream.cpp
CTBZOutputStream.cpp
TerrainTiler.cpp
TerrainTile.cpp
MeshTiler.cpp
MeshTile.cpp
GlobalMercator.cpp
GlobalGeodetic.cpp)
target_link_libraries(ctb ${GDAL_LIBRARIES} ${ZLIB_LIBRARIES})

# Install libctb
set(HEADERS
Bounds.hpp
BoundingSphere.hpp
Coordinate.hpp
Coordinate3D.hpp
GDALSerializer.hpp
GDALTile.hpp
GDALTiler.hpp
GDALDatasetReader.hpp
CTBFileTileSerializer.hpp
CTBFileOutputStream.hpp
CTBOutputStream.hpp
CTBZOutputStream.hpp
GlobalGeodetic.hpp
GlobalMercator.hpp
Grid.hpp
GridIterator.hpp
HeightFieldChunker.hpp
Mesh.hpp
MeshIterator.hpp
MeshSerializer.hpp
MeshTile.hpp
MeshTiler.hpp
RasterIterator.hpp
RasterTiler.hpp
CTBException.hpp
TerrainIterator.hpp
TerrainSerializer.hpp
TerrainTile.hpp
TerrainTiler.hpp
Tile.hpp
Expand Down
43 changes: 43 additions & 0 deletions src/CTBFileOutputStream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright 2018 GeoData <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*******************************************************************************/

/**
* @file CTBFileOutputStream.cpp
* @brief This defines the `CTBFileOutputStream` class
*/

#include "CTBFileOutputStream.hpp"

using namespace ctb;

/**
* @details
* Writes a sequence of memory pointed by ptr into the FILE*.
*/
uint32_t
ctb::CTBFileOutputStream::write(const void *ptr, uint32_t size) {
return (uint32_t)fwrite(ptr, size, 1, fp);
}

/**
* @details
* Writes a sequence of memory pointed by ptr into the ostream.
*/
uint32_t
ctb::CTBStdOutputStream::write(const void *ptr, uint32_t size) {
mstream.write((const char *)ptr, size);
return size;
}
60 changes: 60 additions & 0 deletions src/CTBFileOutputStream.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef CTBFILEOUTPUTSTREAM_HPP
#define CTBFILEOUTPUTSTREAM_HPP

/*******************************************************************************
* Copyright 2018 GeoData <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*******************************************************************************/

/**
* @file CTBFileOutputStream.hpp
* @brief This declares and defines the `CTBFileOutputStream` and `CTBStdOutputStream` classes
*/

#include <stdio.h>
#include <ostream>
#include "CTBOutputStream.hpp"

namespace ctb {
class CTBFileOutputStream;
class CTBStdOutputStream;
}

/// Implements CTBOutputStream for `FILE*` objects
class CTB_DLL ctb::CTBFileOutputStream : public ctb::CTBOutputStream {
public:
CTBFileOutputStream(FILE *fptr): fp(fptr) {}

/// Writes a sequence of memory pointed by ptr into the stream
virtual uint32_t write(const void *ptr, uint32_t size);

protected:
/// The underlying FILE*
FILE *fp;
};

/// Implements CTBOutputStream for `std::ostream` objects
class CTB_DLL ctb::CTBStdOutputStream : public ctb::CTBOutputStream {
public:
CTBStdOutputStream(std::ostream &stream): mstream(stream) {}

/// Writes a sequence of memory pointed by ptr into the stream
virtual uint32_t write(const void *ptr, uint32_t size);

protected:
/// The underlying std::ostream
std::ostream &mstream;
};

#endif /* CTBFILEOUTPUTSTREAM_HPP */
Loading