Skip to content
Merged
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
15 changes: 14 additions & 1 deletion .github/workflows/build_win.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ jobs:
name: proj-windows
path: proj-windows.zip

- name: Build sample app
run: build_sample.bat

- name: Package sample app artifact
run: |
tar -a -c -f sample-app-windows.zip build_sample\proj_sample.exe install_proj\bin\*.dll

- name: Upload sample app artifact
uses: actions/upload-artifact@v4
with:
name: sample-app-windows
path: sample-app-windows.zip

- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v2
Expand All @@ -70,4 +83,4 @@ jobs:
proj-windows.zip.sha256
sample-app-windows.zip.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 changes: 17 additions & 1 deletion build_proj.bat
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ cmake --fresh -S zlib -B build_zlib -G Ninja ^
cmake --build build_zlib
cmake --install build_zlib

set ZLIB_ROOT=%CD%\install_zlib
set ZLIB_DIR=%CD%\install_zlib

echo === Building libtiff (minimal static, no extra codecs) ===
cmake --fresh -S libtiff -B build_tiff -G Ninja ^
-DCMAKE_BUILD_TYPE=Release ^
Expand All @@ -44,6 +47,7 @@ cmake --fresh -S libtiff -B build_tiff -G Ninja ^
-Dtiff-tools=OFF ^
-Dtiff-tests=OFF ^
-Dtiff_static=ON ^
-Dzlib=ON ^
-Djpeg=OFF ^
-Dwebp=OFF ^
-Dzstd=OFF ^
Expand Down Expand Up @@ -71,9 +75,17 @@ if %errorlevel% neq 0 exit /b 1
lib sqlite3.obj /OUT:sqlite3.lib
popd

echo ==== Patch PROJ ==============================
cd proj
git apply ..\proj.patch
if %errorlevel% neq 0 (
echo WARNING: Patch may already be applied or failed, continuing...
)
cd ..

echo === Configure PROJ (Ninja + CMake 4.x fix) ===
cmake --fresh -S PROJ -B build_proj -G Ninja ^
-DCMAKE_PREFIX_PATH=%CD%\install_tiff;%CD%\install_zlib\lib\cmake\zlib ^
-DCMAKE_PREFIX_PATH="%CD%\install_zlib;%CD%\install_tiff;" ^
-DCMAKE_INSTALL_PREFIX=%CD%\install_proj ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
Expand All @@ -96,10 +108,14 @@ cmake --build build_proj
if %errorlevel% neq 0 exit /b 1



echo ==== Instal PROJ ===============
cmake --install build_proj
if %errorlevel% neq 0 exit /b 1

echo ==== COPY z.dll to PROJ install folder ===============
copy /Y install_zlib\bin\z.dll install_proj\bin\

@REM echo === Verifying dependencies of proj.dll ===
@REM if exist install_proj\bin\proj_9_3.dll (
@REM dumpbin /dependents install_proj\bin\proj_9_3.dll
Expand Down
56 changes: 56 additions & 0 deletions build_sample.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
@echo off
setlocal ENABLEDELAYEDEXPANSION

echo === Building sample app ===

echo === Configure sample app ===
cmake --fresh -S sample_app -B build_sample -G Ninja ^
-DCMAKE_PREFIX_PATH=%CD%\install_proj ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL

if %errorlevel% neq 0 (
echo ERROR: Sample app configure failed
exit /b 1
)

echo === Build sample app ===
cmake --build build_sample

if %errorlevel% neq 0 (
echo ERROR: Sample app build failed
exit /b 1
)

echo === Install sample app ===
cmake --install build_sample --prefix install_sample

if %errorlevel% neq 0 (
echo ERROR: Sample app install failed
exit /b 1
)

echo === Test sample app ===
REM Copy PROJ DLL to sample app directory for testing
copy install_proj\bin\*.dll build_sample\ >nul 2>&1

REM Run the sample app
cd build_sample

proj_sample.exe

if %errorlevel% neq 0 (
echo ERROR: Sample app test failed
exit /b 1
)

REM Run the sample app

grid_transform.exe

if %errorlevel% neq 0 (
echo ERROR: grid_transform app test failed
exit /b 1
)

echo === Sample app build complete ===
13 changes: 13 additions & 0 deletions proj.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index df42815b..0c9d8dc0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,7 +18,7 @@ project(PROJ

# Only interpret if() arguments as variables or keywords when unquoted
cmake_policy(SET CMP0054 NEW)
-
+find_package(ZLIB)
# Set C++ version
# Make CMAKE_CXX_STANDARD available as cache option overridable by user
set(CMAKE_CXX_STANDARD 11
53 changes: 53 additions & 0 deletions sample_app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
cmake_minimum_required(VERSION 3.10)
project(proj_sample_app)

# Find PROJ library
add_library(proj SHARED IMPORTED)

set_target_properties(proj PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/../install_proj/bin/proj_9_3.dll"
IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/../install_proj/lib/proj.lib"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/../install_proj/include"
)

# Create executable
add_executable(proj_sample simple_transform.cpp)
target_link_libraries(proj_sample PRIVATE proj)
target_compile_features(proj_sample PRIVATE cxx_std_11)


add_executable(grid_transform grid_transform.cpp)
target_link_libraries(grid_transform PRIVATE proj)
target_compile_features(grid_transform PRIVATE cxx_std_11)



add_custom_command(TARGET proj_sample POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:proj>
$<TARGET_FILE_DIR:proj_sample>
)

add_custom_command(TARGET proj_sample POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_SOURCE_DIR}/../install_proj/share/proj/proj.db"
$<TARGET_FILE_DIR:proj_sample>
)

add_custom_command(TARGET grid_transform POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:proj>
$<TARGET_FILE_DIR:proj_sample>
)

add_custom_command(TARGET grid_transform POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_SOURCE_DIR}/../install_proj/bin/z.dll"
$<TARGET_FILE_DIR:proj_sample>
)

add_custom_command(TARGET grid_transform POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_SOURCE_DIR}/us_nga_egm08_25.tif"
$<TARGET_FILE_DIR:proj_sample>
)
80 changes: 80 additions & 0 deletions sample_app/grid_transform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include <proj.h>
#include <iostream>
#include <iomanip>
#include <cmath>

int main()
{
std::cout << "=== WGS84 ellipsoidal → Geoid height (EGM2008) ===\n";

PJ_CONTEXT* ctx = proj_context_create();
if (!ctx) {
std::cerr << "Failed to create PROJ context\n";
return 1;
}

// WGS84 3D → EGM2008 geoid height
PJ* P = proj_create_crs_to_crs(
ctx,
"EPSG:4979", // WGS84 lat, lon, ellipsoidal height
"EPSG:3855", // EGM2008 height
nullptr
);

if (!P) {
std::cerr << "Failed to create transformation (missing geoid grid?)\n";
proj_context_destroy(ctx);
return 1;
}

PJ* P_norm = proj_normalize_for_visualization(ctx, P);
proj_destroy(P);
P = P_norm;

if (!P) {
std::cerr << "Failed to normalize transformation\n";
proj_context_destroy(ctx);
return 1;
}

// Example: Berlin
double lat = 52.5200;
double lon = 13.4050;
double h_ellipsoid = 100.0; // 100 m ellipsoidal height

std::cout << std::fixed << std::setprecision(4);
std::cout << "Input:\n";
std::cout << " Lat: " << lat << "\n";
std::cout << " Lon: " << lon << "\n";
std::cout << " Ellipsoidal height: " << h_ellipsoid << " m\n\n";

PJ_COORD in = proj_coord(lon, lat, h_ellipsoid, 0);
PJ_COORD out = proj_trans(P, PJ_FWD, in);

if (out.xyz.z == HUGE_VAL) {
std::cerr << "ERROR: Transformation failed (geoid grid missing?)\n";
proj_destroy(P);
proj_context_destroy(ctx);
return 1;
}

std::cout << "Output:\n";
std::cout << " Orthometric height (EGM2008): "
<< out.xyz.z << " m\n";

double geoid_undulation = h_ellipsoid - out.xyz.z;

std::cout << "\nComputed geoid undulation: "
<< geoid_undulation << " m\n";

if (std::fabs(geoid_undulation) > 0.01) {
std::cout << "\nSUCCESS: Geoid correction applied (GeoTIFF working)\n";
} else {
std::cout << "\nWARNING: No geoid correction detected\n";
}

proj_destroy(P);
proj_context_destroy(ctx);

return 0;
}
83 changes: 83 additions & 0 deletions sample_app/simple_transform.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Sample application to test PROJ library installation
// Converts WGS84 coordinates to UTM projection

#include <proj.h>
#include <iostream>
#include <iomanip>

int main() {
std::cout << "hello" << std::endl;
// Create PROJ context
PJ_CONTEXT *ctx = proj_context_create();

// Define transformation: WGS84 (EPSG:4326) to UTM Zone 33N (EPSG:32633)
// Example: Berlin, Germany coordinates
PJ *P = proj_create_crs_to_crs(ctx,
"EPSG:4326", // WGS84
"EPSG:32633", // UTM Zone 33N
NULL);

if (P == NULL) {
std::cerr << "Failed to create transformation" << std::endl;
proj_context_destroy(ctx);
return 1;
}

// Normalize for input/output in radians for geographic, meters for projected
PJ* P_norm = proj_normalize_for_visualization(ctx, P);
if (P_norm == NULL) {
std::cerr << "Failed to normalize transformation" << std::endl;
proj_destroy(P);
proj_context_destroy(ctx);
return 1;
}
proj_destroy(P);
P = P_norm;

// Test coordinates: Berlin, Germany (latitude, longitude in degrees)
double lat = 52.5200; // degrees N
double lon = 13.4050; // degrees E

std::cout << "Testing PROJ library installation" << std::endl;
std::cout << "===================================" << std::endl;
std::cout << std::fixed << std::setprecision(6);
std::cout << "Input (WGS84):" << std::endl;
std::cout << " Latitude: " << lat << " degrees" << std::endl;
std::cout << " Longitude: " << lon << " degrees" << std::endl;
std::cout << std::endl;

// Create coordinate structure
PJ_COORD c_in, c_out;
c_in = proj_coord(lon, lat, 0, 0);

// Transform
c_out = proj_trans(P, PJ_FWD, c_in);

std::cout << "Output (UTM Zone 33N):" << std::endl;
std::cout << " Easting: " << c_out.xy.x << " meters" << std::endl;
std::cout << " Northing: " << c_out.xy.y << " meters" << std::endl;
std::cout << std::endl;

// Verify transformation was successful
if (c_out.xy.x == HUGE_VAL || c_out.xy.y == HUGE_VAL) {
std::cerr << "ERROR: Transformation failed!" << std::endl;
proj_destroy(P);
proj_context_destroy(ctx);
return 1;
}

// Expected values for Berlin (approximate)
// UTM Zone 33N: E~391000, N~5820000
if (c_out.xy.x > 390000 && c_out.xy.x < 392000 &&
c_out.xy.y > 5819000 && c_out.xy.y < 5821000) {
std::cout << "SUCCESS: Transformation result is within expected range!" << std::endl;
} else {
std::cout << "WARNING: Result outside expected range" << std::endl;
}

// Cleanup
proj_destroy(P);
proj_context_destroy(ctx);

return 0;
}
Binary file added sample_app/us_nga_egm08_25.tif
Binary file not shown.