#region License Information
/* HeuristicLab
* Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace HeuristicLab.Analysis.AlgorithmBehavior.Analyzers {
public static class QhullWrapper {
[System.Runtime.InteropServices.DllImportAttribute("HeuristicLab.qhull.dll", EntryPoint = "qhull_volume", CallingConvention = CallingConvention.Cdecl)]
public static extern double qhull_volume(int dim, int numpoints, [In]double[] data);
[System.Runtime.InteropServices.DllImportAttribute("HeuristicLab.qhull.dll", EntryPoint = "qhull_convex_hull", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern IntPtr qhull_convex_hull(int dim, int numpoints, [In]double[] data, [Out] Int32* retCode, [Out] Int32* nrOfFacets);
[System.Runtime.InteropServices.DllImportAttribute("HeuristicLab.qhull.dll", EntryPoint = "qhull_free", CallingConvention = CallingConvention.Cdecl)]
public static extern void qhull_free(IntPtr data);
public static double CalculateVolume(List points) {
double result = 0.0;
int dimension = points.First().Length;
int numPoints = points.Count();
double[] data = new double[dimension * numPoints];
for (int i = 0; i < numPoints; i++) {
for (int j = 0; j < dimension; j++) {
data[i * dimension + j] = points[i][j];
}
}
result = qhull_volume(dimension, numPoints, data);
return result;
}
public unsafe static List CalculateConvexHullIndices(List points) {
int dimension = points.First().Length;
int numPoints = points.Count();
List convexHullIndices = new List();
double[] data = new double[dimension * numPoints];
for (int i = 0; i < numPoints; i++) {
for (int j = 0; j < dimension; j++) {
data[i * dimension + j] = points[i][j];
}
}
IntPtr result = IntPtr.Zero;
Int32 nrOfFacets = -1;
Int32 retCode = 0;
result = qhull_convex_hull(dimension, numPoints, data, &retCode, &nrOfFacets);
if (result != IntPtr.Zero && retCode == 0) {
try {
var faces = new int[nrOfFacets * dimension];
Marshal.Copy(result, faces, 0, nrOfFacets * dimension);
convexHullIndices.AddRange(faces.Distinct());
}
finally {
qhull_free(result);
}
}
return convexHullIndices;
}
public static List Calculate(List points) {
var ret = new List();
List indices = CalculateConvexHullIndices(points);
foreach (var d in indices) {
ret.Add(points[d]);
}
return ret;
}
}
}