Skip to content

Commit

Permalink
autoconf/nmake: Add support for external libqhull_r (refs #4040)
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Dec 23, 2021
1 parent 06ab0b9 commit 00c1542
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 35 deletions.
1 change: 1 addition & 0 deletions GDALmake.opt.in
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ SFCGAL_CFLAGS = @SFCGAL_CFLAGS@

QHULL_SETTING = @QHULL_SETTING@
QHULL_INCLUDE_SUBDIR_IS_LIBQHULL = @QHULL_INCLUDE_SUBDIR_IS_LIBQHULL@
QHULL_IS_LIBQHULL_R = @QHULL_IS_LIBQHULL_R@

# GRASS Support

Expand Down
4 changes: 4 additions & 0 deletions alg/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ CPPFLAGS := -DHAVE_ARMADILLO $(CPPFLAGS)
endif

ifeq ($(QHULL_SETTING),external)
ifeq ($(QHULL_IS_LIBQHULL_R),1)
CPPFLAGS := -DEXTERNAL_QHULL -DQHULL_IS_LIBQHULL_R=1 $(CPPFLAGS)
else
CPPFLAGS := -DEXTERNAL_QHULL -DQHULL_INCLUDE_SUBDIR_IS_LIBQHULL=$(QHULL_INCLUDE_SUBDIR_IS_LIBQHULL) $(CPPFLAGS)
endif
endif
ifeq ($(QHULL_SETTING),internal)
CPPFLAGS := -DINTERNAL_QHULL $(CPPFLAGS)
endif
Expand Down
67 changes: 49 additions & 18 deletions alg/delaunay.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ CPL_CVSID("$Id$")

#else /* INTERNAL_QHULL */

#if !defined(QHULL_INCLUDE_SUBDIR_IS_LIBQHULL)
#if defined(QHULL_IS_LIBQHULL_R)
#include "libqhull_r/libqhull_r.h"
#include "libqhull_r/qset_r.h"
#elif !defined(QHULL_INCLUDE_SUBDIR_IS_LIBQHULL)
#include "libqhull.h"
#include "qset.h"
#elif QHULL_INCLUDE_SUBDIR_IS_LIBQHULL
Expand All @@ -79,8 +82,10 @@ CPL_CVSID("$Id$")


#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
#if !defined(QHULL_IS_LIBQHULL_R)
static CPLMutex* hMutex = NULL;
#endif
#endif

/************************************************************************/
/* GDALHasTriangulation() */
Expand All @@ -101,6 +106,14 @@ int GDALHasTriangulation()
#endif
}

#if defined(QHULL_IS_LIBQHULL_R)
#define QH_MEMBER(qh, member) qh->member
#define QH_ARG qh,
#else
#define QH_MEMBER(qh, member) qh member
#define QH_ARG
#endif

/************************************************************************/
/* GDALTriangulationCreateDelaunay() */
/************************************************************************/
Expand Down Expand Up @@ -128,6 +141,12 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
int* panMapQHFacetIdToFacetIdx; /* map from QHull facet ID to the index of our GDALTriFacet* array */
int curlong, totlong; /* memory remaining after qh_memfreeshort */

#if defined(QHULL_IS_LIBQHULL_R)
qhT qh_qh;
qhT *qh= &qh_qh;

QHULL_LIB_CHECK /* Check for compatible library */
#else
/* QHull is not thread safe, so we need to protect all operations with a mutex */
CPLCreateOrAcquireMutex(&hMutex, 1000);

Expand All @@ -140,12 +159,15 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
CPLReleaseMutex(hMutex);
return NULL;
}
#endif
#endif

points = (coordT*)VSI_MALLOC2_VERBOSE(sizeof(double)*2, nPoints);
if( points == NULL )
{
#if !defined(QHULL_IS_LIBQHULL_R)
CPLReleaseMutex(hMutex);
#endif
return NULL;
}
for(i=0;i<nPoints;i++)
Expand All @@ -154,13 +176,18 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
points[2*i+1] = padfY[i];
}

#if defined(QHULL_IS_LIBQHULL_R)
qh_meminit(qh, NULL);
#endif

/* d: Delaunay */
/* Qbb: scale last coordinate to [0,m] for Delaunay */
/* Qc: keep coplanar points with nearest facet */
/* Qz: add a point-at-infinity for Delaunay triangulation */
/* Qt: triangulated output */
if( qh_new_qhull(2, nPoints, points, FALSE /* ismalloc */,
"qhull d Qbb Qc Qz Qt", NULL, stderr) != 0 )
if( qh_new_qhull(QH_ARG
2, nPoints, points, FALSE /* ismalloc */,
"qhull d Qbb Qc Qz Qt", NULL, stderr) != 0 )
{
VSIFree(points);
CPLError(CE_Failure, CPLE_AppDefined, "Delaunay triangulation failed");
Expand All @@ -179,31 +206,31 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
#endif

/* Establish a map from QHull facet id to the index in our array of sequential facets */
panMapQHFacetIdToFacetIdx = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), qh facet_id);
panMapQHFacetIdToFacetIdx = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), QH_MEMBER(qh, facet_id));
if( panMapQHFacetIdToFacetIdx == NULL )
{
goto end;
}
memset(panMapQHFacetIdToFacetIdx, 0xFF, sizeof(int) * qh facet_id);
memset(panMapQHFacetIdToFacetIdx, 0xFF, sizeof(int) * QH_MEMBER(qh, facet_id));

for(j = 0, facet = qh facet_list;
for(j = 0, facet = QH_MEMBER(qh, facet_list);
facet != NULL && facet->next != NULL;
facet = facet->next)
{
if( facet->upperdelaunay != qh UPPERdelaunay )
if( facet->upperdelaunay != QH_MEMBER(qh, UPPERdelaunay) )
continue;

if( qh_setsize(facet->vertices) != 3 ||
qh_setsize(facet->neighbors) != 3 )
if( qh_setsize(QH_ARG facet->vertices) != 3 ||
qh_setsize(QH_ARG facet->neighbors) != 3 )
{
CPLError(CE_Failure, CPLE_AppDefined,
"Triangulation resulted in non triangular facet %d: vertices=%d",
facet->id, qh_setsize(facet->vertices));
facet->id, qh_setsize(QH_ARG facet->vertices));
VSIFree(panMapQHFacetIdToFacetIdx);
goto end;
}

CPLAssert(facet->id < qh facet_id);
CPLAssert(facet->id < QH_MEMBER(qh, facet_id));
panMapQHFacetIdToFacetIdx[facet->id] = j++;
}

Expand All @@ -219,20 +246,20 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
psDT->pasFacets = pasFacets;

// Store vertex and neighbor information for each triangle.
for(facet = qh facet_list;
for(facet = QH_MEMBER(qh, facet_list);
facet != NULL && facet->next != NULL;
facet = facet->next)
{
int k;
if( facet->upperdelaunay != qh UPPERdelaunay )
if( facet->upperdelaunay != QH_MEMBER(qh, UPPERdelaunay) )
continue;
k = panMapQHFacetIdToFacetIdx[facet->id];
pasFacets[k].anVertexIdx[0] =
qh_pointid(((vertexT*) facet->vertices->e[0].p)->point);
qh_pointid(QH_ARG ((vertexT*) facet->vertices->e[0].p)->point);
pasFacets[k].anVertexIdx[1] =
qh_pointid(((vertexT*) facet->vertices->e[1].p)->point);
qh_pointid(QH_ARG ((vertexT*) facet->vertices->e[1].p)->point);
pasFacets[k].anVertexIdx[2] =
qh_pointid(((vertexT*) facet->vertices->e[2].p)->point);
qh_pointid(QH_ARG ((vertexT*) facet->vertices->e[2].p)->point);
pasFacets[k].anNeighborIdx[0] =
panMapQHFacetIdToFacetIdx[((facetT*) facet->neighbors->e[0].p)->id];
pasFacets[k].anNeighborIdx[1] =
Expand All @@ -244,10 +271,12 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
VSIFree(panMapQHFacetIdToFacetIdx);

end:
qh_freeqhull(!qh_ALL);
qh_memfreeshort(&curlong, &totlong);
qh_freeqhull(QH_ARG !qh_ALL);
qh_memfreeshort(QH_ARG &curlong, &totlong);

#if !defined(QHULL_IS_LIBQHULL_R)
CPLReleaseMutex(hMutex);
#endif

return psDT;
#else /* HAVE_INTERNAL_OR_EXTERNAL_QHULL */
Expand Down Expand Up @@ -634,10 +663,12 @@ int GDALTriangulationFindFacetDirected(const GDALTriangulation* psDT,
void GDALTriangulationTerminate()
{
#if HAVE_INTERNAL_OR_EXTERNAL_QHULL
#if !defined(QHULL_IS_LIBQHULL_R)
if( hMutex != NULL )
{
CPLDestroyMutex(hMutex);
hMutex = NULL;
}
#endif
#endif
}
3 changes: 3 additions & 0 deletions alg/makefile.vc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ EXTRAFLAGS = $(EXTRAFLAGS) -DINTERNAL_QHULL
!ELSE
!IF "$(QHULL_SETTING)" == "EXTERNAL"
EXTRAFLAGS = $(EXTRAFLAGS) -DEXTERNAL_QHULL $(QHULL_INC)
!IF "$(QHULL_IS_LIBQHULL_R)" == "1"
EXTRAFLAGS = $(EXTRAFLAGS) -DQHULL_IS_LIBQHULL_R=1
!ENDIF
!ENDIF
!ENDIF
!ENDIF
Expand Down
42 changes: 27 additions & 15 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -4677,24 +4677,35 @@ if test "$with_qhull" = "no" ; then

elif test "$with_qhull" = "yes" -o "$with_qhull" = "" ; then

# Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
# qhull/qhull.h
AC_CHECK_HEADERS([qhull/libqhull.h])
if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
AC_CHECK_HEADERS([libqhull_r/libqhull_r.h])
if test "$ac_cv_header_libqhull_r_libqhull_r_h" = "yes"; then
AC_CHECK_LIB(qhull_r,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
if test "$QHULL_SETTING" = "yes"; then
QHULL_SETTING=external
QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=0
LIBS="-lqhull $LIBS"
QHULL_IS_LIBQHULL_R=1
LIBS="-lqhull_r $LIBS"
fi
fi
AC_CHECK_HEADERS([libqhull/libqhull.h])
if test "$ac_cv_header_libqhull_libqhull_h" = "yes"; then
AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
if test "$QHULL_SETTING" = "yes"; then
QHULL_SETTING=external
QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
LIBS="-lqhull $LIBS"
else
# Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
# qhull/qhull.h
AC_CHECK_HEADERS([qhull/libqhull.h])
if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
if test "$QHULL_SETTING" = "yes"; then
QHULL_SETTING=external
QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=0
LIBS="-lqhull $LIBS"
fi
fi

AC_CHECK_HEADERS([libqhull/libqhull.h])
if test "$ac_cv_header_libqhull_libqhull_h" = "yes"; then
AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
if test "$QHULL_SETTING" = "yes"; then
QHULL_SETTING=external
QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
LIBS="-lqhull $LIBS"
fi
fi
fi

Expand All @@ -4713,6 +4724,7 @@ fi

AC_SUBST([QHULL_SETTING],$QHULL_SETTING)
AC_SUBST([QHULL_INCLUDE_SUBDIR_IS_LIBQHULL],$QHULL_INCLUDE_SUBDIR_IS_LIBQHULL)
AC_SUBST([QHULL_IS_LIBQHULL_R],$QHULL_IS_LIBQHULL_R)

dnl ---------------------------------------------------------------------------
dnl Check if opencl library is available.
Expand Down
8 changes: 6 additions & 2 deletions nmake.opt
Original file line number Diff line number Diff line change
Expand Up @@ -890,12 +890,16 @@ OCI_INCLUDE = -I$(ORACLE_HOME)\oci\include

# QHull configuration. By default use internal libqhull.
# QHULL_SETTING can be set to INTERNAL, EXTERNAL or NO
# For external qhull, use qhull 2012
# For external qhull, use qhull 2012 or later
!IFNDEF QHULL_SETTING
QHULL_SETTING = INTERNAL
!ENDIF
# To be defined if QHULL_SETTING=EXTERNAL
# QHULL_INC = -I....
# To be defined if QHULL_SETTING=EXTERNAL and re-entrant qhull (qhull_r)
# QHULL_IS_LIBQHULL_R = 1
# To be defined if QHULL_SETTING=EXTERNAL
# QHULL_LIB = path_to_libqhull.lib

# Cryptopp stuff.
# Make sure cryptopp is compiled with /MD ( Properties | Configuration properties | C/C++ | Code Generation | Runtime Library: Multi-threaded DLL (/MD))
Expand Down Expand Up @@ -1185,5 +1189,5 @@ EXTERNAL_LIBS = $(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(PDF_LIB_LINK) $(LZMA_LIBS) $(ZSTD_LIBS) $(BLOSC_LIBS) $(LZ4_LIBS) \
$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(TILEDB_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS) \
$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(PCRE2_LIB) $(MONGODB_LIB_LINK) $(MONGODBV3_LIB_LINK) $(CRYPTOPP_LIB) $(OPENSSL_LIB) $(CHARLS_LIB) ws2_32.lib \
$(RDB_LIB) $(CRUNCH_LIB) $(OPENEXR_LIB) $(HEIF_LIB) $(LERC_LIB) $(JXL_LIB) $(BROTLI_LIB) $(BRUNSLI_LIB)\
$(RDB_LIB) $(CRUNCH_LIB) $(OPENEXR_LIB) $(HEIF_LIB) $(LERC_LIB) $(JXL_LIB) $(BROTLI_LIB) $(BRUNSLI_LIB) $(QHULL_LIB) \
kernel32.lib psapi.lib wbemuuid.lib

0 comments on commit 00c1542

Please sign in to comment.