Commit v1.0 of openGJK

fixes-turtlebasket
Mattia Montanari 2018-11-13 22:17:15 +00:00
parent f0faa98e03
commit bcc7cc6e2a
19 changed files with 10369 additions and 2 deletions

76
CMakeLists.txt Normal file
View File

@ -0,0 +1,76 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# ##### # # # #
# #### ##### ###### # # # # # # # #
# # # # # # ## # # # # # #
# # # # # ##### # # # # #### # ### #
# # # ##### # # # # # # # # # # #
# # # # # # ## # # # # # # #
# #### # ###### # # ##### ##### # # #
# #
# Mattia Montanari | University of Oxford 2018 #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
cmake_minimum_required(VERSION 3.5)
project(openGJK)
set(CMAKE_C_STANDARD 11)
message("[${CMAKE_PROJECT_NAME}] Welcome, please change user options if needed.")
# APPLY DEFAULT SETTINGS
if(NOT CMAKE_BUILD_TYPE)
message("[${CMAKE_PROJECT_NAME}] Use default CMAKE_BUILD_TYPE")
set(CMAKE_BUILD_TYPE Release)
endif()
# PLATFORM-SPECIFIC SETTING
if (UNIX)
find_library(M_LIB m)
set(CMAKE_C_FLAGS "-lm")
set(CMAKE_CXX_FLAGS "-lm")
else ()
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif ()
# COMPILER SETTING
IF(CMAKE_BUILD_TYPE MATCHES Release)
set(CMAKE_BUILD_TYPE Release)
ELSEIF(CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_BUILD_TYPE Debug)
ENDIF()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# using GCC
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -finline-functions")
set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Werror")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -finline-functions")
set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG")
set(CMAKE_C_FLAGS_RELEASE "-O3 -Werror")
add_compile_options(-static-libgcc -static-libstdc++ )
add_definitions(-DMT)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# using Visual Studio C++
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /WX /wd4131 /wd4701 /wd4255 /wd4710 /wd4820 /wd4711")
set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1")
set(CMAKE_CXX_FLAGS_RELEASE "/Ox")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall /WX /wd4131 /wd4701 /wd4255 /wd4710 /wd4820 /wd4711")
set(CMAKE_C_FLAGS_DEBUG "-DDEBUG /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1")
set(CMAKE_C_FLAGS_RELEASE "/Ox")
set(CMAKE_SUPPRESS_REGENERATION true)
endif()
# DEBUG FLAGS
IF(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-DDEBUG)
ENDIF()
# INCLUDE LIBRARY AND EXAMPLE DIR
add_subdirectory(lib)
add_subdirectory(example1_c)

232
README.md
View File

@ -1,2 +1,230 @@
# openGJK
Fast and reliable implementation of the Gilbert-Johnson-Keerthi (GJK) algorithm for C, C# and Matlab
openGJK {#mainpage}
=======
The openGJK library uses the Gilbert-Johnson-Keerthi (GJK) algorithm to
compute the minimum distance between convex polytopes. The
implementation follows the description presented in
"[Improving the GJK Algorithm for Faster and More Reliable Distance
Queries Between Convex Objects. ACM Trans. on Graph. 2017](https://dl.acm.org/citation.cfm?id=3083724)" and has been tested
on Unix and Windows systems for C, C# and Matlab programs.
This library offers researchers a tool that works
out of the box: you can import it in your program and use it to measure
the distance between two convex polytopes in 3D. All it needs are the
coordinates of the vertices describing the two bodies.
This library is not optimised for production, but it does provide a comprehensive and robust implementation. It is sufficiently fast for
most applications, and you can also build from here to suite your own
application. For instance, openGJK is not for incremental and is not
for NURBS, but it offers a good starting point for such specific
applications.
## Getting Started
Using openGJK is very simple. This guide will help you getting
started compiling and using openGJK.
### When should I use openGJK?
OpenGJK is designed with accuracy and robustness in mind and is
suitable for engineering simulations. Good use of this library
include the finite element method (FEM) and discrete element method (DEM).
Basically, openGJK can measure the distance between **any convex polytope**. For example:
- line segments
- triangles
- tetrahedrons
- cubes.
### Installing the openGJK library
#### Prerequisites
1. A compiler (gnu or Microsoft Visual Studio for C)
2. CMake version 3.5 or above
3. Only for the Matlab interface you will need to build mex files (find out the requisites from [Mathworks documentation](https://uk.mathworks.com/help/matlab/matlab_external/what-you-need-to-build-mex-files.html)).
4. Only for the C# interface on Unix you will need [mono](http://www.mono-project.com/) and Microsoft Visual Studio toolchain for C# on Windows.
### Installation
There are CMake files for compiling openGJK in the usual
way:
1. Create a new folder in the folder containing this readme file.
2. Move into that folder and type `cmake -G <duild-system> ..`. For example,
on Windows you can type `cmake -G "Visual Studio 15 2017 Win64" ..`, on Unix `cmake -G "Unix Makefiles" ..`.
3. Use the files generated by Cmake to build the library. Whether you compile
with `make` or an IDE, you will build a shared library and an executable
for the C example. For Matlab and C# applications, see sections below.
To install the library you should copy the header file openGJK.h and the binaries in a folder accessible in the search path by all users (on Unix this would normally be /usr/local).
### Automated documentation
The folder `doc` contains a Doxygen file for generating the documentation of the whole
library. To build the documentation cd into `doc` and call Doxygen from the command line simply by typing `doxygen`. If correctly installed, Doxygen will create html documentation with graphs illustrating the call stack of the functions of the library.
## API user reference
```double gjk( struct bodyA, struct bodyB, struct simplex)```
### Parameters
* **bodyA** The first body.
* **bodyB** The second body.
* **simplex** The simplex used the GJK algorithm at the first iteration.
### Returns
* **double** the minimum distance between bodyA and bodyB.
### Description
The function `gjk` computes the minimum Euclidean distance between two bodies using the
GJK algorithm. Note that the simplex used at the first iteration may be initialised by the user, but this is not necessary.
## Configuration
openGJK comes in two flavours: *accurate* and *fast* (default). You can
change before compiling by editing the main 'lib\CMakeLists.txt' file
(in the folder `lib`). Set the option `VERSION_ACCURATE` to `ON` and
run CMake. You can verify what version is being compiled from the terminal,
if you do not see "Version: Accurate" when calling CMake, you have to clean
the CMake cache.
## Examples
This section presents three examples on how to use openGJK with C, C# and Matlab.
All the examples have been tested both Linux and Windows; the former used `make` and `gcc`,
the latter using `Visual studio 2017` and its compiler. Only x64 systems have been tested.
### C
This example illustrates how to include openGJK in an existing C
program.
All files for the example are in the `example1_c` folder. The executable built with
CMake reads the coordinates of two polytopes from the input files,
respectively userP.dat and userQ.dat, and computes the minimum distance
between them.
Notice that the input files must be in the folder from which the executable
is launched, otherwise an error is returned.
You can edit the coordinates in the input file to test different
polytopes; just remember to edit also the first number in the files
that corresponds to the numbers of vertices that the program will read.
### Matlab
This example illustrates how to invoke openGJK as a regular built-in
Matlab function.
Open Matlab and cd into the `example2_mex` folder. By running the
script `runme.m`, Matlab will first compile a mex file (telling you
about the name of the mex file generated) and will call the script
`main.m`. This invokes openGJK within Matlab and illustrates the
result.
The mex file may be copied and called from any other Matlab project.
### C# #
This example illustrates how to invoke openGJK in an applications written in C#.
The only file required is in the `example3_csharp` folder. This can be compiled in Unix
with mono, or in Windows using Visual Studio. Notice that, however, the openGJK library
is compiled for a specific architecture (usually x64), and this breaks the portability
of the .NET application compiled in this example.
Below are the steps for compiling the C# application on Windows and Linux. Both
procedures assume the dynamic library of openGJK has been already compiled.
#### Compile on Windows
1. Move into the folder `example3_csharp` and create a new folder `example3`.
2. Copy into this folder the openGJK library or make it available in any directory.
3. Open Visual Studio and create a new project. As project type select **Console App (.NET Framework)**.
4. Add to this project the `main.cs` file
5. Set x64 as the target platform, compile the application and run it.
#### Compile on Linux
1. Move into the folder `example3_csharp` and create a new folder `example3`.
2. Copy into this folder the openGJK library or install is so that is available in any directory.
3. Move into that new folder and open a terminal.
4. Type `mcs -out:example3demo -d:UNIX ../main.cs`
5. Run the example by typing `mono example3demo`
## Repository content
This repository contains the following files and folders:
```
│ CMakeLists.txt
│ README.md
├───doc
│ openGJKcustomfooter.html
│ openGJKcustomheader.html
│ openGJKcustomstyle.css
│ Doxyfile
│ oxfordLogo.jpg
├───example1_c
│ CMakeLists.txt
│ main.c
│ userP.dat
│ userQ.dat
├───example2_mex
│ main.m
│ runme.m
├───example3_csharp
│ main.cs
└───lib
│ CMakeLists.txt
├───ext
│ predicates.c
│ predicates.h
├───include
│ └───openGJK
│ openGJK.h
└───src
openGJK.c
```
## Where to go next?
A clear presentation of the GJK algorithm can be found in the
book by **Van der Bergen** *Collision Detection in Interactive 3D
Environments*, edited by Elsevier.
More details about the GJK algorithm can be found in the original paper
from Gilbert, Johnson and Keerthi [A fast procedure for computing the distance between complex objects in three-dimensional space](http://ieeexplore.ieee.org/document/2083/?arnumber=2083).
OpenGJK implements the GJK algorithm as described in: [Improving the GJK Algorithm for Faster and More Reliable Distance
Queries Between Convex Objects. ACM Trans. on Graph. 2017 ](https://dl.acm.org/citation.cfm?id=3083724). Refer to this papar for further details on the method.
## Licence
This open-source edition of openGJK is released under the terms of
[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) License.
This means that any software created with this library you must comply
with the terms of this licence. If you are seeking another licence please
contact the author at the address at the end of this file.
openGJK may use the geometric predicates from *Routines for Arbitrary
Precision Floating-point Arithmetic*, by Jonathan Richard Shewchuk,
whose source code is included in the file predicates.c of this
repository for convenience.
------------------------------------------------------------------------
openGJK, Copyright (c) 2018
Impact Engineering Laboratory
Department of Engineering Science
University of Oxford
Parks Road, Oxford, OX1 3PJ
mattia.montanari@eng.ox.ac.uk
------------------------------------------------------------------------

2476
doc/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
<!-- HTML footer for doxygen 1.8.14-->
<!-- start footer part -->
<!--BEGIN GENERATE_TREEVIEW-->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/><address class="footer"><small>
$generatedby &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
</a> $doxygenversion
</small></address>
<!--END !GENERATE_TREEVIEW-->
</body>
</html>

View File

@ -0,0 +1,34 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>openGJK: Main Page</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="openGJKcustomstyle.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="oxforduni.jpg" height="100px"/></td>
<td id="projectalign" style="padding-left: 2.5em;">
<div id="projectname">openGJK
&#160;<span id="projectnumber">v 1.0</span>
</div>
<div id="projectbrief">Fast and reliable distance queries in 3D between convex polytopes.</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->

1598
doc/openGJKcustomstyle.css Normal file

File diff suppressed because it is too large Load Diff

BIN
doc/oxfordLogo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

28
example1_c/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# ##### # # # #
# #### ##### ###### # # # # # # # #
# # # # # # ## # # # # # #
# # # # # ##### # # # # #### # ### #
# # # ##### # # # # # # # # # # #
# # # # # # ## # # # # # # #
# #### # ###### # # ##### ##### # # #
# #
# Mattia Montanari | University of Oxford 2018 #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
project(openGJKdemo)
message( "[${CMAKE_PROJECT_NAME}] Compiling the executable ..")
# Set source file
set(SOURCE_FILES main.c )
# Create the executable
add_executable(demo ${SOURCE_FILES})
# Link to openGJK
target_link_libraries(demo openGJKlib )
# Report
message( ".. executable DONE!")

159
example1_c/main.c Normal file
View File

@ -0,0 +1,159 @@
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* ##### # # # *
* #### ##### ###### # # # # # # # *
* # # # # # ## # # # # # *
* # # # # ##### # # # # #### # ### *
* # # ##### # # # # # # # # # # *
* # # # # # ## # # # # # # *
* #### # ###### # # ##### ##### # # *
* *
* Mattia Montanari | University of Oxford 2018 *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* *
* This file runs an example to illustrate how to invoke the openGJK lib *
* within a C program. An executable called 'demo' can be compiled with *
* CMake. This reads the coordinates of two polytopes from the input *
* files userP.dat and userQ.dat, respectively, and returns the minimum *
* distance between them computed using the openGJK library. *
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
* @file main.c
* @author Mattia Montanari
* @date April 2018
* @brief File illustrating an application that invokes openGJK.
*
*/
#include <stdio.h>
/* For importing openGJK this is Step 1: include header in subfolder. */
#include "openGJK/openGJK.h"
#ifndef WIN32
#define fscanf_s fscanf
#endif
/**
* @brief Function for reading input file with body's coordinates.
*
*/
int readinput ( const char *inputfile, double ***pts, int * out ) {
int npoints = 0;
int idx = 0;
FILE *fp;
/* Open file. */
#ifdef WIN32
errno_t err;
if ((err = fopen_s(&fp, inputfile, "r")) != 0) {
#else
if ((fp = fopen(inputfile, "r")) == NULL) {
#endif
fprintf(stdout, "ERROR: input file %s not found!\n", inputfile);
fprintf(stdout, " -> The file must be in the folder from which this program is launched\n\n");
return 1;
}
/* Read number of input vertices. */
if (fscanf_s(fp, "%1d", &npoints) != 1)
return 1;
/* Allocate memory. */
double **arr = (double **)malloc(npoints * sizeof(double *));
for (int i=0; i<npoints; i++)
arr[i] = (double *)malloc(3 * sizeof(double));
/* Read and store vertices' coordinates. */
for (idx = 0; idx < npoints; idx++)
{
if (fscanf_s(fp, "%lf %lf %lf\n", &arr[idx][0], &arr[idx][1], &arr[idx][2]) != 3 )
return 1;
}
/* Close file. */
fclose(fp);
/* Pass pointers. */
*pts = arr;
*out = idx;
return (0);
}
/**
* @brief Main program of example1_c (described in Section 3.1 of the paper).
*
*/
int main() {
/* Squared distance computed by openGJK. */
double dd;
/* Structure of simplex used by openGJK. */
struct simplex s;
/* Number of vertices defining body 1 and body 2, respectively. */
int nvrtx1,
nvrtx2;
/* Structures of body 1 and body 2, respectively. */
struct bd bd1;
struct bd bd2;
/* Specify name of input files for body 1 and body 2, respectively. */
char inputfileA[40] = "userP.dat",
inputfileB[40] = "userQ.dat";
/* Pointers to vertices' coordinates of body 1 and body 2, respectively. */
double (**vrtx1) = NULL,
(**vrtx2) = NULL;
/* For importing openGJK this is Step 2: adapt the data structure for the
* two bodies that will be passed to the GJK procedure. */
/* Import coordinates of object 1. */
if (readinput ( inputfileA, &vrtx1, &nvrtx1 ))
return (1);
bd1.coord = vrtx1;
bd1.numpoints = nvrtx1;
/* Import coordinates of object 2. */
if (readinput ( inputfileB, &vrtx2, &nvrtx2 ))
return (1);
bd2.coord = vrtx2;
bd2.numpoints = nvrtx2;
/* Initialise simplex as empty */
s.nvrtx = 0;
#ifdef DEBUG
/* Verify input of body A. */
for (int i = 0; i < bd1.numpoints; ++i) {
printf ( "%.2f ", vrtx1[i][0]);
printf ( "%.2f ", vrtx1[i][1]);
printf ( "%.2f\n", bd1.coord[i][2]);
}
/* Verify input of body B. */
for (int i = 0; i < bd2.numpoints; ++i) {
printf ( "%.2f ", bd2.coord[i][0]);
printf ( "%.2f ", bd2.coord[i][1]);
printf ( "%.2f\n", bd2.coord[i][2]);
}
#endif
/* For importing openGJK this is Step 3: invoke the GJK procedure. */
/* Compute squared distance using GJK algorithm. */
dd = gjk (bd1, bd2, &s);
/* Print distance between objects. */
printf ("Distance between bodies %f\n", dd);
/* Free memory */
for (int i=0; i<bd1.numpoints; i++)
free(bd1.coord[i]);
free(bd1.coord);
for (int i=0; i<bd2.numpoints; i++)
free(bd2.coord[i]);
free(bd2.coord);
return (0);
}

10
example1_c/userP.dat Normal file
View File

@ -0,0 +1,10 @@
9
0.0 5.5 0.0
2.3 1.0 -2.0
8.1 4.0 2.4
4.3 5.0 2.2
2.5 1.0 2.3
7.1 1.0 2.4
1.0 1.5 0.3
3.3 0.5 0.3
6.0 1.4 0.2

10
example1_c/userQ.dat Normal file
View File

@ -0,0 +1,10 @@
9
-0.0 -5.5 0.0
-2.3 -1.0 2.0
-8.1 -4.0 -2.4
-4.3 -5.0 -2.2
-2.5 -1.0 -2.3
-7.1 -1.0 -2.4
-1.0 -1.5 -0.3
-3.3 -0.5 -0.3
-6.0 -1.4 -0.2

60
example2_mex/main.m Normal file
View File

@ -0,0 +1,60 @@
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% ##### # # # %
% #### ##### ###### # # # # # # # %
% # # # # # ## # # # # # %
% # # # # ##### # # # # #### # ### %
% # # ##### # # # # # # # # # # %
% # # # # # ## # # # # # # %
% #### # ###### # # ##### ##### # # %
% %
% Mattia Montanari | University of Oxford 2018 %
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% %
% This file runs an example to illustrate how to invoke the openGJK lib %
% withing Matlab. It that assumes a mex file openGJK is availalbe, see %
% the runme.m script for information on how to compile it. %
% The example computes the minimum distance between two polytopes in 3D, %
% A and B, both defined as a list of points. %
% %
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% DEFINE BODY A AS 3xN MATRIX, WHERE N IS THE NUMBER OF VERTICES OF BODY A
A = [ 0.0 2.3 8.1 4.3 2.5 7.1 1.0 3.3 6.0
5.5 1.0 4.0 5.0 1.0 1.0 1.5 0.5 1.4
0.0 -2.0 2.4 2.2 2.3 2.4 0.3 0.3 0.2];
% DEFINE BODY B IN THE OPPOSITE QUADRANT OF BODY A
B = -A;
% COMPUTE MINIMUM DISTANCE AND RETURN VALUE
dist = openGJK( A, B );
fprintf('The minimum distance between A and B is %.2f\n',dist);
% VISUALISE RESULTS
% .. create new figure
figure('units','centimeters', 'WindowStyle','normal', 'color','w',...
'Position',[0 8.5 9 6],'defaultAxesColorOrder',parula,...
'Renderer','opengl')
% .. adjust properties
axis equal tight off; hold all;
% .. display body A
DT = delaunayTriangulation(A');
[K,~] = convexHull(DT);
trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
'EdgeColor','none','FaceColor',[.4 1 .9 ],...
'FaceLighting','flat' )
% .. display body B
DT = delaunayTriangulation(B');
[K,~] = convexHull(DT);
trisurf(K,DT.Points(:,1),DT.Points(:,2),DT.Points(:,3),...
'EdgeColor','none','FaceColor',[.4 1 .8 ],...
'FaceLighting','flat' )
% .. represent the computed distance as a sphere
[x,y,z] = sphere(100);
surf(x.*dist/2,y.*dist/2,z.*dist/2,'facecolor',[.9 .9 .9],...
'EdgeColor','none','FaceLighting','flat','SpecularColorReflectance',0,...
'SpecularStrength',1,'SpecularExponent',10,'facealpha',.7)
% ... adjust point of view
view(42,21)
% ... add light
light('Position',[5 -10 20],'Style','local');

61
example2_mex/runme.m Normal file
View File

@ -0,0 +1,61 @@
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% ##### # # # %
% #### ##### ###### # # # # # # # %
% # # # # # ## # # # # # %
% # # # # ##### # # # # #### # ### %
% # # ##### # # # # # # # # # # %
% # # # # # ## # # # # # # %
% #### # ###### # # ##### ##### # # %
% %
% Mattia Montanari | University of Oxford 2018 %
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% %
% This file compiles a mex function from the openGJK library and runs an %
% example. If the mex function cannot be compiled an error is returned. %
% %
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %
% CLEAR ALL VARIABLES
clearvars
% SELECT OPTIMISATION FLAG - FASTER BUT NOT SUITABLE FOR DEBUGGING
if 0
optflug = '-g'; %#ok<*UNRCH>
else
optflug = '-O';
end
% SELECT SILET COMPILATION MODE.
if 1
silflag = '-silent';
else
silflag = '-v';
end
% TRY COMPILING MEX FILE
fprintf('Compiling mex function... ')
try
mex('../lib/src/openGJK.c',... % Source of openGJK
'-largeArrayDims', ... % Support large arrays
optflug, ... % Compiler flag for debug/optimisation
'-I../lib/include',... % Folder to header files
'-outdir', pwd,... % Ouput directory for writing mex function
'-output', 'openGJK',... % Name of ouput mex file
'-DMATLABDOESMEXSTUFF',... % Define variable for mex function in source files
silflag ) % Silent/verbose flag
% File compiled without errors. Return path and name of mex file
fprintf('completed!\n')
fprintf('The following mex file has been generated:')
fprintf('\t%s\n',[pwd,filesep,'openGJK.',mexext])
catch
% Build failed, refer to documentation
fprintf('\n\n ERROR DETECTED! Mex file cannot be compiled.\n')
fprintf('\tFor more information, see ')
fprintf('<a href="http://www.mathworks.com/help/matlab/ref/mex.html">this documentation page</a>.\n\n')
return
end
% RUN EXAMPLE
fprintf('Running example... ')
main
fprintf('completed!\n')

37
example3_csharp/main.cs Normal file
View File

@ -0,0 +1,37 @@
using System;
using System.Runtime.InteropServices;
public class Tester
{
#if UNIX
[DllImport("libopenGJKlib.so", EntryPoint="csFunction", CallingConvention = CallingConvention.StdCall)]
#else
[DllImport("openGJKlib", EntryPoint = "csFunction", CallingConvention = CallingConvention.StdCall)]
#endif
static extern double gjk(int na, double [,] ia, int nb, double [,] ib);
public static void Main(string[] args)
{
double dist;
// Define array A with coordinates
int nCoordsA = 9;
var inCoordsA = new double[3,9] { {0.0 , 2.3 , 8.1 , 4.3 ,2.5 , 7.1 , 1.0 , 3.3 , 6.0} , { 5.5 , 1.0 , 4.0 , 5.0 ,1.0, 1.0, 1.5, 0.5 , 1.4} ,{ 0.0 , -2.0, 2.4, 2.2, 2.3 , 2.4 , 0.3 , 0.3 , 0.2} };
// Define array B with coordinates
int nCoordsB = 9;
var inCoordsB = new double[3,9] { {-0.0 , -2.3 , -8.1 , -4.3 ,-2.5 , -7.1 , -1.0 , -3.3 , -6.0} , { -5.5 , -1.0 ,- 4.0 ,- 5.0 ,-1.0, -1.0, -1.5, -0.5 , -1.4} ,{ -0.0 , 2.0, -2.4, -2.2, -2.3 , -2.4 , -0.3 , -0.3 , -0.2} };
// Invoke GJK to compute distance
dist = gjk( nCoordsA, inCoordsA, nCoordsB, inCoordsB );
// Output results
var s = string.Format("{0:0.##}", dist);
var message = string.Format("The distance between {0} is {1}","A and B",s);
Console.WriteLine(message);
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}

63
lib/CMakeLists.txt Normal file
View File

@ -0,0 +1,63 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# ##### # # # #
# #### ##### ###### # # # # # # # #
# # # # # # ## # # # # # #
# # # # # ##### # # # # #### # ### #
# # # ##### # # # # # # # # # # #
# # # # # # ## # # # # # # #
# #### # ###### # # ##### ##### # # #
# #
# Mattia Montanari | University of Oxford 2018 #
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
project (openGJKlib)
set(CMAKE_C_STANDARD 11)
# SELECT USER OPTIONS
option(VERSION_ACCURATE "Reduce speed to maximise accuracy (OFF)"
OFF )
# APPLY USER OPTIONS
IF(VERSION_ACCURATE)
set(USE_PREDICATES ON)
set(openGJK_VERSION "Accurate")
ELSE()
set(USE_PREDICATES OFF)
set(openGJK_VERSION "Fast")
ENDIF()
# COMPILE
message( "[${CMAKE_PROJECT_NAME}] Compiling ..")
message(STATUS "Version (Accurate,Fast): " ${openGJK_VERSION} )
message(STATUS "Build type (Debug,Release): " ${CMAKE_BUILD_TYPE} )
# Select source files
set( SOURCE_FILES src/openGJK.c )
set( SOURCE_HEADS include/openGJK/openGJK.h)
IF(USE_PREDICATES)
# for adpative floating-point artim.
set( SOURCE_FILES ${SOURCE_FILES} ext/predicates.c)
set( SOURCE_HEADS ${SOURCE_HEADS} ext/predicates.h)
# Add flag for adpative floating-point artim.
add_definitions(-DADAPTIVEFP)
ENDIF()
# Create the (dynamic) library
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${SOURCE_HEADS})
add_definitions(-DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=TRUE -DBUILD_SHARED_LIBS=TRUE)
# Link include file
target_include_directories( ${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
IF(USE_PREDICATES)
# for adpative floating-point artim.
target_include_directories( ${PROJECT_NAME}
PUBLIC ${PROJECT_SOURCE_DIR}/ext
)
ENDIF()
# Report
message( ".. DONE!")

4271
lib/ext/predicates.c Normal file

File diff suppressed because it is too large Load Diff

26
lib/ext/predicates.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by mmontanari on 29/06/16.
//
#include <stdio.h>
#include <stdlib.h>
#ifndef CGJK_PREDICATES_H
#define CGJK_PREDICATES_H
#endif //CGJK_PREDICATES_H
extern double orient3d(
double *pa,
double *pb,
double *pc,
double *pd
);
extern double orient2d(
double *pa,
double *pb,
double *pc
);
extern void exactinit();

View File

@ -0,0 +1,63 @@
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* ##### # # # *
* #### ##### ###### # # # # # # # *
* # # # # # ## # # # # # *
* # # # # ##### # # # # #### # ### *
* # # ##### # # # # # # # # # # *
* # # # # # ## # # # # # # *
* #### # ###### # # ##### ##### # # *
* *
* Mattia Montanari | University of Oxford 2018 *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
* *
* This is the header file for the openGJK.c file. It defines the openGJK *
* function and it two important structures: bd and simplex. *
* *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef __OPENGJK_H__
#define __OPENGJK_H__
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
/**
* @brief Macro that implements the CompareSign function (see paper).
*/
#define SAMESIGN( a, b ) ( (a>0) == (b>0) )
/**
* @brief Structure of a body.
*/
struct bd {
int numpoints; /**< Number of points defining the body. */
double **coord; /**< Pointer to pointer to the points' coordinates. */
double s [3]; /**< Support mapping computed last. */
};
/**
* @brief Structure for a simplex.
*/
struct simplex {
int nvrtx ; /**< Number of simplex's vertices. */
double vrtx [4][3]; /**< Coordinates of simplex's vertices. */
int wids [4]; /**< Label of the simplex's vertices. */
double lambdas [4]; /**< Barycentric coordiantes for each vertex. */
};
/**
* @brief The GJK algorithm which returns the minimum distance between
* two bodies.
*/
extern double gjk( struct bd, struct bd, struct simplex * ) ;
#endif

1146
lib/src/openGJK.c Normal file

File diff suppressed because it is too large Load Diff