summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PKG-INFO2
-rw-r--r--PyMca/ClassMcaTheory.py31
-rw-r--r--PyMca/FastXRFLinearFit.py469
-rw-r--r--PyMca/FastXRFLinearFitWindow.py154
-rw-r--r--PyMca/Gefit.py3
-rw-r--r--PyMca/HDF5Stack1D.py48
-rw-r--r--PyMca/ImageRegistration.py79
-rw-r--r--PyMca/Lanczos.py17
-rw-r--r--PyMca/MEDFile.py2
-rw-r--r--PyMca/MRCMap.py183
-rw-r--r--PyMca/McaAdvancedFitBatch.py10
-rw-r--r--PyMca/NNMAModule.py1
-rw-r--r--PyMca/Object3D/Object3DQhull/Announce.txt51
-rw-r--r--PyMca/Object3D/Object3DQhull/COPYING.txt38
-rw-r--r--PyMca/Object3D/Object3DQhull/Object3DQhull.c (renamed from PyMca/Object3D/Object3DQhull/src/Object3DQhull.c)0
-rw-r--r--PyMca/Object3D/Object3DQhull/REGISTER.txt32
-rw-r--r--PyMca/Object3D/Object3DQhull/src/geom.c1234
-rw-r--r--PyMca/Object3D/Object3DQhull/src/geom.h176
-rw-r--r--PyMca/Object3D/Object3DQhull/src/geom2.c2081
-rw-r--r--PyMca/Object3D/Object3DQhull/src/global.c2127
-rw-r--r--PyMca/Object3D/Object3DQhull/src/io.c4060
-rw-r--r--PyMca/Object3D/Object3DQhull/src/io.h159
-rw-r--r--PyMca/Object3D/Object3DQhull/src/libqhull.c1401
-rw-r--r--PyMca/Object3D/Object3DQhull/src/libqhull.h1100
-rw-r--r--PyMca/Object3D/Object3DQhull/src/mem.c543
-rw-r--r--PyMca/Object3D/Object3DQhull/src/mem.h219
-rw-r--r--PyMca/Object3D/Object3DQhull/src/merge.c3623
-rw-r--r--PyMca/Object3D/Object3DQhull/src/merge.h178
-rw-r--r--PyMca/Object3D/Object3DQhull/src/poly.c1199
-rw-r--r--PyMca/Object3D/Object3DQhull/src/poly.h295
-rw-r--r--PyMca/Object3D/Object3DQhull/src/poly2.c3154
-rw-r--r--PyMca/Object3D/Object3DQhull/src/qhull_a.h151
-rw-r--r--PyMca/Object3D/Object3DQhull/src/qset.c1339
-rw-r--r--PyMca/Object3D/Object3DQhull/src/qset.h488
-rw-r--r--PyMca/Object3D/Object3DQhull/src/random.c243
-rw-r--r--PyMca/Object3D/Object3DQhull/src/random.h34
-rw-r--r--PyMca/Object3D/Object3DQhull/src/stat.c714
-rw-r--r--PyMca/Object3D/Object3DQhull/src/stat.h541
-rw-r--r--PyMca/Object3D/Object3DQhull/src/user.c527
-rw-r--r--PyMca/Object3D/Object3DQhull/src/user.h858
-rw-r--r--PyMca/Object3D/Object3DQhull/src/usermem.c64
-rw-r--r--PyMca/Object3D/Object3DQhull/src/userprintf.c63
-rw-r--r--PyMca/OmnicMap.py2
-rw-r--r--PyMca/PhysicalMemory.py189
-rw-r--r--PyMca/Plot1D.py65
-rw-r--r--PyMca/Plot1DBase.py101
-rw-r--r--PyMca/PyMcaData/HTML/AdvancedAlignmentScanPlugin.html246
-rw-r--r--PyMca/PyMcaData/HTML/XMCDInfotext.html702
-rw-r--r--PyMca/PyMcaIOHelper/PyMcaIOHelper.c18
-rw-r--r--PyMca/PyMcaIOHelper/setup.py36
-rw-r--r--PyMca/PyMcaMain.py2
-rw-r--r--PyMca/PyMcaPlugins/AdvancedAlignmentScanPlugin.py1075
-rw-r--r--PyMca/PyMcaPlugins/FastXRFLinearFitStackPlugin.py263
-rw-r--r--PyMca/PyMcaPlugins/ImageAlignmentStackPlugin.py177
-rw-r--r--PyMca/PyMcaPlugins/MotorInfoPlugin.py26
-rw-r--r--PyMca/PyMcaPlugins/MotorInfoWindow.py26
-rw-r--r--PyMca/PyMcaPlugins/StackAxesPlugin.py58
-rw-r--r--PyMca/PyMcaPlugins/StackScanWindowPlugin.py26
-rw-r--r--PyMca/PyMcaPlugins/XMCDPlugin.py28
-rw-r--r--PyMca/PyMcaSciPy/signal/mediantools.c79
-rw-r--r--PyMca/PyMcaSciPy/signal/setup.py19
-rw-r--r--PyMca/QHDF5StackWizard.py8
-rw-r--r--PyMca/QStackWidget.py4
-rw-r--r--PyMca/SGModule.py24
-rw-r--r--PyMca/ScanWindow.py8
-rw-r--r--PyMca/SixCircle.py397
-rw-r--r--PyMca/StackSelector.py14
-rw-r--r--PyMca/XMCDWindow.py847
-rw-r--r--PyMca/XRFMC/XMSOParser.py26
-rw-r--r--PyMca/XRFMC/XRFMCHelper.py26
-rw-r--r--PyMca/XRFMC/XRFMCPyMca.py27
-rw-r--r--PyMca/linalg.py326
-rw-r--r--PyMca/specfile/src/specfile_py.c23
-rw-r--r--PyMca/specfile/src/specfile_py3.c37
-rw-r--r--PyMca/specfit/SpecfitFuns.c920
-rw-r--r--PyMca/specfit/setup.py2
-rw-r--r--PyMca/specfit/snip1d.c292
-rw-r--r--PyMca/sps/Src/sps_py.c3
-rw-r--r--PyMca/sps/Src/spslut_py.c31
-rw-r--r--changelog.txt14
-rw-r--r--cx_setup.py20
-rwxr-xr-xpy2app_setup.py19
-rw-r--r--scripts/pymca_win_post_install.py29
-rw-r--r--setup.py76
84 files changed, 5936 insertions, 28066 deletions
diff --git a/PKG-INFO b/PKG-INFO
index 510466a..c1fcaac 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: PyMca
-Version: 4.7.0
+Version: 4.7.1
Summary: Mapping and X-Ray Fluorescence Analysis
Home-page: http://pymca.sourceforge.net
Author: V. Armando Sole
diff --git a/PyMca/ClassMcaTheory.py b/PyMca/ClassMcaTheory.py
index 619f9c3..58211e3 100644
--- a/PyMca/ClassMcaTheory.py
+++ b/PyMca/ClassMcaTheory.py
@@ -1,5 +1,5 @@
#/*##########################################################################
-# Copyright (C) 2004-2012 European Synchrotron Radiation Facility
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
@@ -39,8 +39,8 @@ DEBUG = 0
CONTINUUM_LIST = [None,'Constant','Linear','Parabolic','Linear Polynomial','Exp. Polynomial']
OLDESCAPE = 0
MAX_ATTENUATION = 1.0E-300
-class McaTheory:
- def __init__(self,initdict=None,filelist=None,**kw):
+class McaTheory(object):
+ def __init__(self, initdict=None, filelist=None, **kw):
self.ydata0 = None
self.xdata0 = None
self.sigmay0 = None
@@ -117,8 +117,10 @@ class McaTheory:
return self.configure()
def configure(self,newdict=None):
- if newdict is None:return copy.deepcopy(self.config)
- if newdict == {} :return copy.deepcopy(self.config)
+ if newdict is None:
+ return copy.deepcopy(self.config)
+ if newdict == {}:
+ return copy.deepcopy(self.config)
self.config.update(newdict)
self.__configure()
return copy.deepcopy(self.config)
@@ -959,14 +961,20 @@ class McaTheory:
if not self.config['fit']['use_limit']:
if 'xmin' in kw:
xmin=kw['xmin']
- self.config['fit']['xmin'] = xmin
+ if xmin is not None:
+ self.config['fit']['xmin'] = xmin
+ else:
+ xmin=min(self.xdata)
elif len(self.xdata):
xmin=min(self.xdata)
xmax = self.config['fit']['xmax']
if not self.config['fit']['use_limit']:
if 'xmax' in kw:
xmax=kw['xmax']
- self.config['fit']['xmax'] = xmax
+ if xmax is not None:
+ self.config['fit']['xmax'] = xmax
+ else:
+ xmax=max(self.xdata)
elif len(self.xdata):
xmax=max(self.xdata)
@@ -1250,8 +1258,7 @@ class McaTheory:
matrix[:,i] = result[:,0]
return matrix
- def linearMcaTheory(self,param0,t0,hypermet=None,
- continuum=None,summing=None):
+ def linearMcaTheory(self, param0, t0, hypermet=None, continuum=None, summing=None):
if continuum is None:
continuum = self.__CONTINUUM
if hypermet is None:
@@ -1463,7 +1470,7 @@ class McaTheory:
def linearMcaTheoryDerivative(self,param0,index,t0):
NGLOBAL = self.NGLOBAL
if index > NGLOBAL-1:
- return self.linearMatrix[:,index-NGLOBAL]
+ return self.linearMatrix[:, index-NGLOBAL]
PARAMETERS = self.PARAMETERS
if self.__CONTINUUM and (PARAMETERS[index] == 'Constant'):
return numpy.ones(len(t0)).astype(numpy.float)
@@ -1659,7 +1666,7 @@ class McaTheory:
return (f1-f2) / (2.0 * delta)
def estimate(self):
- self.parameters,self.codes = self.specfitestimate(self.xdata, self.ydata,self.zz)
+ self.parameters, self.codes = self.specfitestimate(self.xdata, self.ydata,self.zz)
#self.estimatelinpoly(self.xdata, self.ydata,self.zz)
#self.estimateexppoly(self.xdata, self.ydata,self.zz)
#print self.codes[:,3]
@@ -1984,7 +1991,7 @@ class McaTheory:
#print "Elapsed = ",time.time() - e0
if self._batchFlag and self.linearMatrix is None:
self.linearMatrix = self.getPeakMatrixContribution(newpar)
- return newpar,codes
+ return newpar, codes
def startfit(self,digest=0, linear=None):
if linear is None:
diff --git a/PyMca/FastXRFLinearFit.py b/PyMca/FastXRFLinearFit.py
new file mode 100644
index 0000000..47c7e0c
--- /dev/null
+++ b/PyMca/FastXRFLinearFit.py
@@ -0,0 +1,469 @@
+#/*##########################################################################
+# Copyright (C) 2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This file 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 Lesser General Public License for more
+# details.
+#
+#############################################################################*/
+__author__ = "V.A. Sole - ESRF Data Analysis"
+__license__ = "LGPL"
+import numpy
+from PyMca.linalg import lstsq
+from PyMca import ClassMcaTheory
+from PyMca import Gefit
+from PyMca import ConcentrationsTool
+from PyMca import SpecfitFuns
+from PyMca import ConfigDict
+
+DEBUG = 0
+
+class FastXRFLinearFit(object):
+ def __init__(self, mcafit=None):
+ self._config = None
+ if mcafit is None:
+ self._mcaTheory = ClassMcaTheory.McaTheory()
+ else:
+ self._mcaTheory = mcafit
+
+ def setFitConfiguration(self, configuration):
+ self._mcaTheory.setConfiguration(configuration)
+
+ def setFitConfigurationFile(self, ffile):
+ configuration = ConfigDict.ConfigDict()
+ configuration.read(ffile)
+ self.setFitConfiguration(configuration)
+
+ def fitMultipleSpectra(self, x=None, y=None, xmin=None, xmax=None,
+ configuration=None, concentrations=False,
+ ysum=None):
+ if y is None:
+ raise RuntimeError("y keyword argument is mandatory!")
+
+ #if concentrations:
+ # txt = "Fast concentration calculation not implemented yet"
+ # raise NotImplemented(txt)
+
+ if configuration is not None:
+ self._mcaTheory.setConfiguration(configuration)
+
+ # read the current configuration
+ config = self._mcaTheory.getConfiguration()
+
+ #make sure we force a linear fit
+ config['fit']['linearfitflag'] = 1
+ weight = config['fit']['fitweight']
+
+ # background
+ if config['fit']['stripflag']:
+ if config['fit']['stripalgorithm'] == 1:
+ if DEBUG:
+ print("SNIP")
+ else:
+ raise RuntimeError("Please use the faster SNIP background")
+
+ # and now configure the fit
+ self._mcaTheory.setConfiguration(config)
+
+ if hasattr(y, "info") and hasattr(y, "data"):
+ data = y.data
+ mcaIndex = y.info.get("McaIndex", -1)
+ else:
+ data = y
+ mcaIndex = -1
+
+ if len(data.shape) != 3:
+ txt = "For the time being only three dimensional arrays supported"
+ raise IndexError(txt)
+ elif mcaIndex not in [-1, 2]:
+ txt = "For the time being only mca arrays supported"
+ raise IndexError(txt)
+ else:
+ # if the cumulated spectrum is present it should be better
+ nRows = data.shape[0]
+ nColumns = data.shape[1]
+ nPixels = nRows * nColumns
+ if ysum is not None:
+ firstSpectrum = ysum
+ elif not concentrations:
+ # just one spectrum is enough for the setup
+ firstSpectrum = data[0, 0, :]
+ else:
+ firstSpectrum = data[0, :, :].sum(axis=0, dtype=numpy.float)
+
+ # make sure we calculate the matrix of the contributions
+ self._mcaTheory.enableOptimizedLinearFit()
+
+ # initialize the fit
+ # print("xmin = ", xmin)
+ # print("xmax = ", xmax)
+ # print("firstShape = ", firstSpectrum.shape)
+ self._mcaTheory.setData(x=x, y=firstSpectrum, xmin=xmin, xmax=xmax)
+
+ #loop for anchors
+ if config['fit']['stripflag']:
+ anchorslist = []
+ if config['fit']['stripanchorsflag']:
+ if config['fit']['stripanchorslist'] is not None:
+ ravelled = numpy.ravel(self._mcaTheory.xdata)
+ for channel in config['fit']['stripanchorslist']:
+ if channel <= ravelled[0]:
+ continue
+ index = numpy.nonzero(ravelled >= channel)[0]
+ if len(index):
+ index = min(index)
+ if index > 0:
+ anchorslist.append(index)
+ if len(anchorslist) == 0:
+ anchorlist = [0, self._mcaTheory.ydata.size - 1]
+ anchorslist.sort()
+
+ # and initialize the derivatives
+ self._mcaTheory.estimate()
+
+ # now we can get the derivatives respect to the free parameters
+ # These are the "derivatives" respect to the peaks
+ # linearMatrix = self._mcaTheory.linearMatrix
+
+ # but we are still missing the derivatives from the background
+ nFree = 0
+ freeNames = []
+ nFreeBackgroundParameters = 0
+ for i, param in enumerate(self._mcaTheory.PARAMETERS):
+ if self._mcaTheory.codes[0][i] != ClassMcaTheory.Gefit.CFIXED:
+ nFree += 1
+ freeNames.append(param)
+ if i < self._mcaTheory.NGLOBAL:
+ nFreeBackgroundParameters += 1
+
+ #build the matrix of derivatives
+ derivatives = None
+ idx = 0
+ for i, param in enumerate(self._mcaTheory.PARAMETERS):
+ if self._mcaTheory.codes[0][i] == ClassMcaTheory.Gefit.CFIXED:
+ continue
+ deriv= self._mcaTheory.linearMcaTheoryDerivative(self._mcaTheory.parameters[i],
+ i,
+ self._mcaTheory.xdata)
+ if derivatives is None:
+ derivatives = numpy.zeros((deriv.shape[0], nFree), numpy.float)
+ derivatives[:, idx] = deriv
+ idx += 1
+
+
+ #loop for anchors
+ xdata = self._mcaTheory.xdata
+
+ if config['fit']['stripflag']:
+ anchorslist = []
+ if config['fit']['stripanchorsflag']:
+ if config['fit']['stripanchorslist'] is not None:
+ ravelled = numpy.ravel(xdata)
+ for channel in config['fit']['stripanchorslist']:
+ if channel <= ravelled[0]:continue
+ index = numpy.nonzero(ravelled >= channel)[0]
+ if len(index):
+ index = min(index)
+ if index > 0:
+ anchorslist.append(index)
+ if len(anchorslist) == 0:
+ anchorlist = [0, self._mcaTheory.ydata.size - 1]
+ anchorslist.sort()
+
+ # find the indices to be used for selecting the appropriate data
+ # if the original x data were nor ordered we have a problem
+ # TODO: check for original ordering.
+ if x is None:
+ # we have an enumerated channels axis
+ iXMin = xdata[0]
+ iXMax = xdata[-1]
+ else:
+ iXMin = numpy.nonzero(x <= xdata[0])[0][0]
+ iXMax = numpy.nonzero(x >= xdata[-1])[0][0]
+
+ dummySpectrum = firstSpectrum[iXMin:iXMax+1].reshape(-1, 1)
+ # print("dummy = ", dummySpectrum.shape)
+
+ # allocate the output buffer
+ results = numpy.zeros((nFree, nRows, nColumns), numpy.float32)
+ uncertainties = numpy.zeros((nFree, nRows, nColumns), numpy.float32)
+
+ #perform the inital fit
+ for i in range(data.shape[0]):
+ #chunks of nColumns spectra
+ if i == 0:
+ chunk = numpy.zeros((dummySpectrum.shape[0], data.shape[1]),
+ numpy.float)
+
+ chunk[:,:] = data[i, :, iXMin:iXMax+1].T
+ if config['fit']['stripflag']:
+ for k in range(chunk.shape[0]):
+ # obtain the smoothed spectrum
+ background=SpecfitFuns.SavitskyGolay(chunk[k],
+ config['fit']['stripfilterwidth'])
+ lastAnchor = 0
+ for anchor in anchorslist:
+ if (anchor > lastAnchor) and (anchor < background.size):
+ background[lastAnchor:anchor] =\
+ SpecfitFuns.snip1d(background[lastAnchor:anchor],
+ config['fit']['snipwidth'],
+ 0)
+ lastAnchor = anchor
+ if lastAnchor < background.size:
+ background[lastAnchor:] =\
+ SpecfitFuns.snip1d(background[lastAnchor:],
+ config['fit']['snipwidth'],
+ 0)
+ chunk[k] -= background
+
+ # perform the multiple fit to all the spectra in the chunk
+ # print("SHAPES")
+ # print(derivatives.shape)
+ # print(chunk.shape)
+ ddict=lstsq(derivatives, chunk, weight=weight, digested_output=True)
+ parameters = ddict['parameters']
+ results[:, i, :] = parameters
+ uncertainties[:, i, :] = ddict['uncertainties']
+
+ # cleanup zeros
+ # start with the parameter with the largest amount of negative values
+ negativePresent = True
+ nFits = 0
+ while negativePresent:
+ zeroList = []
+ for i in range(nFree):
+ #we have to skip the background parameters
+ if i >= nFreeBackgroundParameters:
+ t = results[i] < 0
+ if t.sum() > 0:
+ zeroList.append((t.sum(), i, t))
+
+ if len(zeroList) == 0:
+ negativePresent = False
+ continue
+
+ if nFits > (2 * (nFree - nFreeBackgroundParameters)):
+ # we are probably in an endless loop
+ # force negative pixels
+ for item in zeroList:
+ i = item[1]
+ badMask = item[2]
+ results[i][badMask] = 0.0
+ print("WARNING: %d pixels of parameter %s set to zero" % (item[0], freeNames[i]))
+ continue
+ zeroList.sort()
+ zeroList.reverse()
+
+ badParameters = []
+ badParameters.append(zeroList[0][1])
+ badMask = zeroList[0][2]
+ if 1:
+ # prevent and endless loop if two or more parameters have common pixels where they are
+ # negative and one of them remains negative when forcing other one to zero
+ for i, item in enumerate(zeroList):
+ if item[1] not in badParameters:
+ if item[0] > 0:
+ #check if they have common negative pixels
+ t = badMask * item[-1]
+ if t.sum() > 0:
+ badParameters.append(item[1])
+ badMask = t
+ if badMask.sum() < (0.0025 * nPixels):
+ # fit not worth
+ for i in badParameters:
+ results[i][badMask] = 0.0
+ uncertainties[i][badMask] = 0.0
+ if DEBUG:
+ print("WARNING: %d pixels of parameter %s set to zero" % (badMask.sum(),
+ freeNames[i]))
+ else:
+ if DEBUG:
+ print("Number of secondary fits = %d" % (nFits + 1))
+ nFits += 1
+ A = derivatives[:, [i for i in range(nFree) if i not in badParameters]]
+ #assume we'll not have too many spectra
+ spectra = data[badMask, iXMin:iXMax+1]
+ spectra.shape = badMask.sum(), -1
+ spectra = spectra.T
+ #
+ if config['fit']['stripflag']:
+ for k in range(spectra.shape[0]):
+ # obtain the smoothed spectrum
+ background=SpecfitFuns.SavitskyGolay(spectra[k],
+ config['fit']['stripfilterwidth'])
+ lastAnchor = 0
+ for anchor in anchorslist:
+ if (anchor > lastAnchor) and (anchor < background.size):
+ background[lastAnchor:anchor] =\
+ SpecfitFuns.snip1d(background[lastAnchor:anchor],
+ config['fit']['snipwidth'],
+ 0)
+ lastAnchor = anchor
+ if lastAnchor < background.size:
+ background[lastAnchor:] =\
+ SpecfitFuns.snip1d(background[lastAnchor:],
+ config['fit']['snipwidth'],
+ 0)
+ spectra[k] -= background
+ ddict = lstsq(A, spectra, weight=weight, digested_output=True)
+ idx = 0
+ for i in range(nFree):
+ if i in badParameters:
+ results[i][badMask] = 0.0
+ uncertainties[i][badMask] = 0.0
+ else:
+ results[i][badMask] = ddict['parameters'][idx]
+ uncertainties[i][badMask] = ddict['uncertainties'][idx]
+ idx += 1
+ outputDict = {'parameters':results, 'uncertainties':uncertainties, 'names':freeNames}
+
+ if concentrations:
+ # check if an internal reference is used and if it is set to auto
+ ####################################################
+ # CONCENTRATIONS
+ cTool = ConcentrationsTool.ConcentrationsTool()
+ cToolConf = cTool.configure()
+ cToolConf.update(config['concentrations'])
+
+ fitFirstSpectrum = False
+ if config['concentrations']['usematrix']:
+ if DEBUG:
+ print("USING MATRIX")
+ if config['concentrations']['reference'].upper() == "AUTO":
+ fitFirstSpectrum = True
+
+ fitresult = {}
+ if fitFirstSpectrum:
+ # we have to fit the "reference" spectrum just to get the reference element
+ mcafitresult = self._mcaTheory.startfit(digest=0, linear=True)
+ # if one of the elements has zero area this cannot be made directly
+ fitresult['result'] = self._mcaTheory.imagingDigestResult()
+ fitresult['result']['config'] = config
+ concentrationsResult, addInfo = cTool.processFitResult(config=cToolConf,
+ fitresult=fitresult,
+ elementsfrommatrix=False,
+ fluorates=self._mcaTheory._fluoRates,
+ addinfo=True)
+ # and we have to make sure that all the areas are positive
+ for group in fitresult['result']['groups']:
+ if fitresult['result'][group]['fitarea'] <= 0.0:
+ # give a tiny area
+ fitresult['result'][group]['fitarea'] = 1.0e-6
+ config['concentrations']['reference'] = addInfo['ReferenceElement']
+ else:
+ fitresult['result'] = {}
+ fitresult['result']['config'] = config
+ fitresult['result']['groups'] = []
+ idx = 0
+ for i, param in enumerate(self._mcaTheory.PARAMETERS):
+ if self._mcaTheory.codes[0][i] == Gefit.CFIXED:
+ continue
+ if i < self._mcaTheory.NGLOBAL:
+ # background
+ pass
+ else:
+ fitresult['result']['groups'].append(param)
+ fitresult['result'][param] = {}
+ # we are just interested on the factor to be applied to the area to get the
+ # concentrations
+ fitresult['result'][param]['fitarea'] = 1.0
+ fitresult['result'][param]['sigmaarea'] = 1.0
+ idx += 1
+ concentrationsResult, addInfo = cTool.processFitResult(config=cToolConf,
+ fitresult=fitresult,
+ elementsfrommatrix=False,
+ fluorates=self._mcaTheory._fluoRates,
+ addinfo=True)
+ nValues = 1
+ if len(concentrationsResult['layerlist']) > 1:
+ nValues += len(concentrationsResult['layerlist'])
+ massFractions = numpy.zeros((nValues * (nFree - nFreeBackgroundParameters), nRows, nColumns),
+ numpy.float32)
+
+
+ referenceElement = addInfo['ReferenceElement']
+ referenceTransitions = addInfo['ReferenceTransitions']
+ if DEBUG:
+ print("Reference <%s> transition <%s>" % (referenceElement, referenceTransitions))
+ if referenceElement in ["", None, "None"]:
+ if DEBUG:
+ print("No reference")
+ counter = 0
+ for i, group in enumerate(fitresult['result']['groups']):
+ outputDict['names'].append("C(%s)" % group)
+ massFractions[counter] = results[nFreeBackgroundParameters+i] *\
+ (concentrationsResult['mass fraction'][group]/fitresult['result'][param]['fitarea'])
+ if len(concentrationsResult['layerlist']) > 1:
+ for layer in concentrationsResult['layerlist']:
+ outputDict['names'].append("C(%s)-%s" % (group, layer))
+ massFractions[counter] = results[nFreeBackgroundParameters+i] *\
+ (concentrationsResult[layer]['mass fraction'][group]/fitresult['result'][param]['fitarea'])
+ counter += 1
+ counter += 1
+ else:
+ if DEBUG:
+ print("With reference")
+ idx = None
+ testGroup = referenceElement+ " " + referenceTransitions.split()[0]
+ for i, group in enumerate(fitresult['result']['groups']):
+ if group == testGroup:
+ idx = i
+ if idx is None:
+ raise ValueError("Invalid reference: <%s> <%s>" %\
+ (referenceElement, referenceTransitions))
+
+ group = fitresult['result']['groups'][idx]
+ referenceArea = fitresult['result'][group]['fitarea']
+ referenceConcentrations = concentrationsResult['mass fraction'][group]
+ goodIdx = results[nFreeBackgroundParameters+idx] > 0
+ massFractions[idx] = referenceConcentrations
+ counter = 0
+ for i, group in enumerate(fitresult['result']['groups']):
+ outputDict['names'].append("C(%s)" % group)
+ if i == idx:
+ continue
+ goodI = results[nFreeBackgroundParameters+i] > 0
+ tmp = results[nFreeBackgroundParameters+idx][goodI]
+ massFractions[i][goodI] = (results[nFreeBackgroundParameters+i][goodI]/(tmp + (tmp == 0))) *\
+ ((referenceArea/fitresult['result'][group]['fitarea']) *\
+ (concentrationsResult['mass fraction'][group]))
+ if len(concentrationsResult['layerlist']) > 1:
+ for layer in concentrationsResult['layerlist']:
+ outputDict['names'].append("C(%s)-%s" % (group, layer))
+ massFractions[i][goodI] = (results[nFreeBackgroundParameters+i][goodI]/(tmp + (tmp == 0))) *\
+ ((referenceArea/fitresult['result'][group]['fitarea']) *\
+ (concentrationsResult[layer]['mass fraction'][group]))
+ counter += 1
+ counter += 1
+ outputDict['concentrations'] = massFractions
+ ####################################################
+ return outputDict
+
+if __name__ == "__main__":
+ import time
+ import glob
+ from PyMca import EDFStack
+ if 1:
+ configurationFile = "E:\DATA\COTTE\CH1777\G4-4720eV-NOWEIGHT-NO_Constant-batch.cfg"
+ fileList = glob.glob("E:\DATA\COTTE\CH1777\G4_mca_0012_0000_0*.edf")
+ else:
+ configurationFile = "E2_line.cfg"
+ fileList = glob.glob("E:\DATA\PyMca-Training\FDM55\AS_EDF\E2_line*.edf")
+ dataStack = EDFStack.EDFStack(filelist=fileList)
+
+ t0 = time.time()
+ fastFit = FastXRFLinearFit()
+ fastFit.setFitConfigurationFile(configurationFile)
+ print("Configuring Elapsed = % s " % (time.time() - t0))
+ results = fastFit.fitMultipleSpectra(y=dataStack, concentrations=True)
+ print("Total Elapsed = % s " % (time.time() - t0))
+
diff --git a/PyMca/FastXRFLinearFitWindow.py b/PyMca/FastXRFLinearFitWindow.py
new file mode 100644
index 0000000..4030d88
--- /dev/null
+++ b/PyMca/FastXRFLinearFitWindow.py
@@ -0,0 +1,154 @@
+#/*##########################################################################
+# Copyright (C) 2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+__author__ = "V.A. Sole - ESRF Data Analysis"
+import sys
+import numpy
+from PyMca import PyMcaQt as qt
+from PyMca.PyMca_Icons import IconDict
+from PyMca import PyMcaFileDialogs
+
+DEBUG = 0
+
+class FastXRFLinearFitWindow(qt.QWidget):
+ def __init__(self, parent=None):
+ qt.QWidget.__init__(self, parent)
+ self.setWindowTitle("FastXRFLinearFitWindow")
+ self.setWindowIcon(qt.QIcon(qt.QPixmap(IconDict['gioconda16'])))
+ self.mainLayout = qt.QGridLayout(self)
+ self.mainLayout.setContentsMargins(0, 0, 0, 0)
+
+ # configuration file
+ configLabel = qt.QLabel(self)
+ configLabel.setText("Fit Configuration File:")
+ self._configLine = qt.QLineEdit(self)
+ self._configLine.setReadOnly(True)
+
+ self._configButton = qt.QPushButton(self)
+ self._configButton.setText("Browse")
+ self._configButton.setAutoDefault(False)
+ self._configButton.clicked.connect(self.browseConfigurationFile)
+
+ # output directory
+ outLabel = qt.QLabel(self)
+ outLabel.setText("Output dir:")
+ self._outLine = qt.QLineEdit(self)
+ self._outLine.setReadOnly(True)
+
+ self._outButton = qt.QPushButton(self)
+ self._outButton.setText('Browse')
+ self._outButton.setAutoDefault(False)
+ self._outButton.clicked.connect(self.browseOutputDir)
+
+ # output file name
+ fileLabel = qt.QLabel(self)
+ fileLabel.setText("Output file root:")
+ self._fileLine = qt.QLineEdit(self)
+ self._fileLine.setReadOnly(False)
+ self._fileLine.setText("images")
+
+ # concentrations
+ self._concentrationsBox = qt.QCheckBox(self)
+ self._concentrationsBox.setText("calculate concentrations")
+ self._concentrationsBox.setChecked(False)
+ self._concentrationsBox.setEnabled(True)
+
+
+ self.mainLayout.addWidget(configLabel, 0, 0)
+ self.mainLayout.addWidget(self._configLine, 0, 1)
+ self.mainLayout.addWidget(self._configButton, 0, 2)
+ self.mainLayout.addWidget(outLabel, 1, 0)
+ self.mainLayout.addWidget(self._outLine, 1, 1)
+ self.mainLayout.addWidget(self._outButton, 1, 2)
+ self.mainLayout.addWidget(fileLabel, 2, 0)
+ self.mainLayout.addWidget(self._fileLine, 2, 1)
+ self.mainLayout.addWidget(self._concentrationsBox, 3, 0, 1, 2)
+
+ def sizeHint(self):
+ return qt.QSize(int(1.8 * qt.QWidget.sizeHint(self).width()),
+ qt.QWidget.sizeHint(self).height())
+
+ def browseConfigurationFile(self):
+ f = PyMcaFileDialogs.getFileList(parent=self,
+ filetypelist=["Configuration files (*.cfg)"],
+ message="Open a new fit config file",
+ mode="OPEN",
+ single=True)
+ if len(f):
+ self._configLine.setText(f[0])
+
+ def browseOutputDir(self):
+ f = PyMcaFileDialogs.getExistingDirectory(parent=self,
+ message="Please select output directory",
+ mode="OPEN")
+ if len(f):
+ self._outLine.setText(f)
+
+ def getParameters(self):
+ ddict = {}
+ ddict['configuration'] = qt.safe_str(self._configLine.text())
+ ddict['output_dir'] = qt.safe_str(self._outLine.text())
+ ddict['file_root'] = qt.safe_str(self._fileLine.text())
+ if self._concentrationsBox.isChecked():
+ ddict['concentrations'] = 1
+ else:
+ ddict['concentrations'] = 0
+ return ddict
+
+class FastXRFLinearFitDialog(qt.QDialog):
+ def __init__(self, parent=None):
+ qt.QDialog.__init__(self, parent)
+ self.setWindowTitle("Fast XRF Linear Fit Dialog")
+ self.setWindowIcon(qt.QIcon(qt.QPixmap(IconDict['gioconda16'])))
+ self.mainLayout = qt.QGridLayout(self)
+ self.mainLayout.setContentsMargins(10, 10, 10, 10)
+ self.parametersWidget = FastXRFLinearFitWindow(self)
+
+ self.rejectButton= qt.QPushButton(self)
+ self.rejectButton.setAutoDefault(False)
+ self.rejectButton.setText("Cancel")
+
+ self.acceptButton= qt.QPushButton(self)
+ self.acceptButton.setAutoDefault(False)
+ self.acceptButton.setText("OK")
+
+ self.rejectButton.clicked.connect(self.reject)
+ self.acceptButton.clicked.connect(self.accept)
+
+ self.mainLayout.addWidget(self.parametersWidget, 0, 0, 5, 5)
+ self.mainLayout.addWidget(self.rejectButton, 6, 1)
+ self.mainLayout.addWidget(self.acceptButton, 6, 2)
+
+ def getParameters(self):
+ return self.parametersWidget.getParameters()
+
+if __name__ == "__main__":
+ app = qt.QApplication([])
+ w = FastXRFLinearFitDialog()
+ ret = w.exec_()
+ if ret:
+ print(w.getParameters())
+ #app.exec_()
diff --git a/PyMca/Gefit.py b/PyMca/Gefit.py
index 10f8fe5..4d43af0 100644
--- a/PyMca/Gefit.py
+++ b/PyMca/Gefit.py
@@ -14,8 +14,11 @@
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
#############################################################################*/
__author__ = "V.A. Sole - ESRF Software Group"
+__license__ = "LGPL"
import numpy
from numpy.linalg import inv
import time
diff --git a/PyMca/HDF5Stack1D.py b/PyMca/HDF5Stack1D.py
index 44ade89..179149a 100644
--- a/PyMca/HDF5Stack1D.py
+++ b/PyMca/HDF5Stack1D.py
@@ -40,7 +40,7 @@ except ImportError:
print("HDF5Stack1D importing NexusDataSource from local directory!")
import NexusDataSource
-DEBUG = 0
+DEBUG = 0
SOURCE_TYPE = "HDF5Stack1D"
class HDF5Stack1D(DataObject.DataObject):
@@ -74,6 +74,10 @@ class HDF5Stack1D(DataObject.DataObject):
That means scanlist = ["/whatever1"]
and selection['y'] = "/whatever2/counts"
"""
+ if DEBUG:
+ print("filelist = ", filelist)
+ print("selection = ", selection)
+ print("scanlist = ", scanlist)
# all the files in the same source
hdfStack = NexusDataSource.NexusDataSource(filelist)
@@ -86,7 +90,7 @@ class HDF5Stack1D(DataObject.DataObject):
entryNames.append(key)
# built the selection in terms of HDF terms
- # for the time being, the only the firs item in x selection used
+ # for the time being, only the first item in x selection used
xSelection = selection['x']
if type(xSelection) == type([]):
if len(xSelection):
@@ -110,6 +114,7 @@ class HDF5Stack1D(DataObject.DataObject):
else:
mSelection = None
+ USE_JUST_KEYS = False
# deal with the pathological case where the scanlist corresponds
# to a selected top level dataset
if len(entryNames) == 0:
@@ -117,8 +122,13 @@ class HDF5Stack1D(DataObject.DataObject):
if len(scanlist) == 1:
if scanlist[0] == ySelection:
scanlist = None
-
- if scanlist in [None, []]:
+ elif len(entryNames) == 1:
+ # deal with the SOLEIL case of one entry but with different name
+ # in different files
+ USE_JUST_KEYS = True
+ elif scanlist in [None, []]:
+ USE_JUST_KEYS = True
+ if USE_JUST_KEYS:
#if the scanlist is None, it is assumed we are interested on all
#the scans containing the selection, not that all the scans
#contain the selection.
@@ -126,6 +136,7 @@ class HDF5Stack1D(DataObject.DataObject):
if 0:
JUST_KEYS = False
#expect same entry names in the files
+ #Unfortunately this does not work for SOLEIL
for entry in entryNames:
path = "/"+entry + ySelection
dirname = posixpath.dirname(path)
@@ -137,19 +148,18 @@ class HDF5Stack1D(DataObject.DataObject):
pass
else:
JUST_KEYS = True
- #expect same structure in the files
+ #expect same structure in the files even if the
+ #names are different (SOLEIL ...)
if len(entryNames):
i = 0
for entry in entryNames:
- i += 1
path = "/"+entry + ySelection
dirname = posixpath.dirname(path)
base = posixpath.basename(path)
- try:
- if base in tmpHdf[dirname].keys():
+ if hasattr(tmpHdf[dirname], "keys"):
+ i += 1
+ if base in tmpHdf[dirname].keys():
scanlist.append("1.%d" % i)
- except:
- pass
if not len(scanlist):
path = "/" + ySelection
dirname = posixpath.dirname(path)
@@ -185,6 +195,10 @@ class HDF5Stack1D(DataObject.DataObject):
if not nScans:
raise IOError("No entry contains the required data")
+ if DEBUG:
+ print("Retained number of files = %d" % nFiles)
+ print("Retained number of scans = %d" % nScans)
+
#Now is to decide the number of mca ...
#I assume all the scans contain the same number of mca
if JUST_KEYS:
@@ -214,6 +228,8 @@ class HDF5Stack1D(DataObject.DataObject):
mcaIndex = selection.get('index', len(shape)-1)
if mcaIndex == -1:
mcaIndex = len(shape) - 1
+ if DEBUG:
+ print("mcaIndex = %d" % mcaIndex)
considerAsImages = False
dim0, dim1, mcaDim = self.getDimensions(nFiles, nScans, shape,
index=mcaIndex)
@@ -227,7 +243,7 @@ class HDF5Stack1D(DataObject.DataObject):
else:
bytefactor = 8
- neededMegaBytes = nFiles * dim0 * dim1 * mcaDim * bytefactor/(1024*1024.)
+ neededMegaBytes = nFiles * dim0 * dim1 * (mcaDim * bytefactor/(1024*1024.))
physicalMemory = PhysicalMemory.getPhysicalMemoryOrNone()
if physicalMemory is None:
# 5 Gigabytes should be a good compromise
@@ -283,9 +299,14 @@ class HDF5Stack1D(DataObject.DataObject):
self.incrProgressBar=0
for hdf in hdfStack._sourceObjectList:
entryNames = list(hdf["/"].keys())
+ goodEntryNames = []
+ for entry in entryNames:
+ tmpPath = "/" + entry
+ if hasattr(hdf[tmpPath], "keys"):
+ goodEntryNames.append(entry)
for scan in scanlist:
if JUST_KEYS:
- entryName = entryNames[int(scan.split(".")[-1])-1]
+ entryName = goodEntryNames[int(scan.split(".")[-1])-1]
path = entryName + ySelection
if mSelection is not None:
mpath = entryName + mSelection
@@ -456,8 +477,7 @@ class HDF5Stack1D(DataObject.DataObject):
elif not DONE:
# data into memory but as images
self.info["McaIndex"] = mcaIndex
- if 1:#for hdf in hdfStack._sourceObjectList:
- hdf = hdfStack._sourceObjectList[0]
+ for hdf in hdfStack._sourceObjectList:
entryNames = list(hdf["/"].keys())
for scan in scanlist:
if JUST_KEYS:
diff --git a/PyMca/ImageRegistration.py b/PyMca/ImageRegistration.py
index 6ef1bc3..2a82919 100644
--- a/PyMca/ImageRegistration.py
+++ b/PyMca/ImageRegistration.py
@@ -1,5 +1,4 @@
# coding: utf8
-#
#/*********************************************************************************************
#
# Copyright (c) 2013 J. Kieffer and V.A. Sole, European Synchrotron Radiation Facility (ESRF)
@@ -23,13 +22,12 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#********************************************************************************************/
-
_author__ = "Jérôme Kieffer and V.Armando Solé"
__contact__ = "sole@esrf.fr"
__license__ = "MIT"
__copyright__ = "2013, ESRF, Grenoble"
__date__ = "20131028"
-__doc__ = "This is a python module to measure image offsets using fftpack"
+__doc__ = "This is a python module to measure image offsets"
import os, time
import numpy
@@ -48,11 +46,10 @@ except ImportError:
def shiftFFT(img, shift):
"""
- Do shift using FFTs
- Shift an array like scipy.ndimage.interpolation.shift(input, shift, mode="wrap", order="infinity")
- @param input: 2d numpy array
- @param shift: 2-tuple of float
- @return: shifted image
+ Shift an array using FFTs
+ :param input: 2d numpy array
+ :param shift: 2-tuple of float
+ :return: shifted image
"""
d0, d1 = img.shape
@@ -67,6 +64,13 @@ def shiftFFT(img, shift):
return abs(out)
def shiftBilinear(img, shift):
+ """
+ Shift an array like scipy.ndimage.interpolation.shift(input, shift, mode="wrap", order="infinity")
+ :param input: 2d numpy array
+ :param shift: 2-tuple of float
+ :return: shifted image
+
+ """
shape = img.shape
x = numpy.zeros((shape[0] * shape[1], 2), numpy.float)
x[:,0] = shift[0] + numpy.outer(numpy.arange(shape[1]), numpy.ones(shape[0])).reshape(-1)
@@ -77,6 +81,14 @@ def shiftBilinear(img, shift):
return shifted
def shiftImage(img, shift, method=None):
+ """
+ Shift an array like scipy.ndimage.interpolation.shift(input, shift, mode="wrap", order="infinity")
+ :param input: 2d numpy array
+ :param shift: 2-tuple of float
+ :param method: string set to PYMCA, SCIPY or FFT. Default is to try the first of those that is possible.
+ :return: shifted image
+
+ """
if method is None:
if PYMCA:
return shiftBilinear(img, shift)
@@ -95,10 +107,10 @@ def measure_offset(img1, img2, method="fft", withLog=False):
"""
Measure the actual offset between 2 images. The first one is the reference. That means, if
the image to be shifted is the second one, the shift has to be multiplied byt -1.
- @param img1: ndarray, first image
- @param img2: ndarray, second image, same shape as img1
- @param withLog: shall we return logs as well ? boolean
- @return: tuple of floats with the offsets of the second respect to the first
+ :param img1: ndarray, first image
+ :param img2: ndarray, second image, same shape as img1
+ :param withLog: shall we return logs as well ? boolean
+ :return: tuple of floats with the offsets of the second respect to the first
"""
method = str(method)
shape = img1.shape
@@ -114,12 +126,40 @@ def measure_offset(img1, img2, method="fft", withLog=False):
return measure_offset_from_ffts(i1f, i2f, withLog=withLog)
def measure_offset_from_ffts(img0_fft2, img1_fft2, withLog=False):
+ """
+ Convenience method to measure the actual offset between 2 images taing their FFTs as inpuy
+ The first FFT one is the one of the reference. That means, if the image to be shifted is the
+ second one, the shift has to be multiplied byt -1.
+ :param img1: ndarray, FFT of first image
+ :param img2: ndarray, FFT of the second image, same shape as img1
+ :param withLog: shall we return logs as well ? boolean
+ :return: tuple of floats with the offsets of the second respect to the first
+ """
shape = img0_fft2.shape
logs = []
f0 = img0_fft2
f1 = img1_fft2
t0 = time.time()
- res = abs(fftshift(ifft2((f0 * f1.conjugate()) / (abs(f0) * abs(f1)))))
+ absf0 = abs(f0)
+ absf1 = abs(f1)
+ if 0:
+ # one way to deal with zeros
+ if (absf0 < 1.0e-20).any() or (absf1 < 1.0e-20).any():
+ ofsset = [0.0, 0.0]
+ logs.append("MeasureOffset: empty or uniform image?")
+ if withLog:
+ return offset, logs
+ else:
+ return offset
+ else:
+ # this one seems better because numerator is expected to be zero
+ idx = absf0 < 1.0e-20
+ if idx.any():
+ absf0[idx] = 1.0
+ idx = absf1 < 1.0e-20
+ if idx.any():
+ absf1[idx] = 1.0
+ res = abs(fftshift(ifft2((f0 * f1.conjugate()) / (absf0 * absf1))))
t1 = time.time()
a0, a1 = numpy.unravel_index(numpy.argmax(res), shape)
resmax = res[a0, a1]
@@ -131,8 +171,12 @@ def measure_offset_from_ffts(img0_fft2, img1_fft2, withLog=False):
x0 = 0.0
x1 = 0.0
total = 0.0
- for i in range(a0-w, a0+w+1):
- for j in range(a1-w, a1 + w + 1):
+ a00 = int(max(a0-w, 0))
+ a01 = int(min(a0+w+1, shape[0]))
+ a10 = int(max(a1-w, 0))
+ a11 = int(min(a1+w+1, shape[1]))
+ for i in range(a00, a01):
+ for j in range(a10, a11):
if res[i, j] > 0.1 * resmax:
tmp = res[i, j]
x0 += i * tmp
@@ -148,6 +192,11 @@ def measure_offset_from_ffts(img0_fft2, img1_fft2, withLog=False):
return offset
def get_crop_indices(shape, shifts0, shifts1):
+ """
+ Get the indices of the valid region to be used when aligning a set of images
+ :param shitfs0: Shifts applied to the first dimension
+ :param shitfs1: Shifts applied to the second dimension
+ """
shifts0_min = numpy.min(shifts0)
shifts0_max = numpy.max(shifts0)
shifts1_min = numpy.min(shifts1)
diff --git a/PyMca/Lanczos.py b/PyMca/Lanczos.py
index 2196789..9a2a991 100644
--- a/PyMca/Lanczos.py
+++ b/PyMca/Lanczos.py
@@ -1,18 +1,18 @@
## /************************************************************************
-
+##
## Copyright
## Alessandro MIRONE
## mirone@esrf.fr
-
+##
## Copyright 2002 by European Synchrotron Radiation Facility, Grenoble,
## France
-
+##
## ----------
-
+##
## All Rights Reserved
-
+##
## ----------
-
+##
## Permission to use, copy, modify, and distribute this software and its
## documentation for any purpose and without fee is hereby granted,
## provided that the above copyright notice appear in all copies and that
@@ -21,7 +21,7 @@
## Radiation Facility or ESRF or SCISOFT not be used in advertising or
## publicity pertaining to distribution of the software without specific,
## written prior permission.
-
+##
## EUROPEAN SYNCHROTRON RADIATION FACILITY DISCLAIMS ALL WARRANTIES WITH
## REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL EUROPEAN SYNCHROTRON
@@ -30,9 +30,10 @@
## DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
## TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
## PERFORMANCE OF THIS SOFTWARE.
-
+##
## **************************************************************************/
__author__ = "A. Mirone - ESRF SciSoft Group"
+__license__ = "BSD"
import math
sparsamodulo=0
PARALLEL=0
diff --git a/PyMca/MEDFile.py b/PyMca/MEDFile.py
index b99b507..a0a92f6 100644
--- a/PyMca/MEDFile.py
+++ b/PyMca/MEDFile.py
@@ -18,6 +18,8 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THIS SOFTWARE.
#
+__license__ = "BSD"
+__author__ = "M. Newville - The University of Chicago"
"""
Simple interface to M. River's Multi-Element MCA Data Format
diff --git a/PyMca/MRCMap.py b/PyMca/MRCMap.py
new file mode 100644
index 0000000..62971ed
--- /dev/null
+++ b/PyMca/MRCMap.py
@@ -0,0 +1,183 @@
+#/*##########################################################################
+# Copyright (C) 2008-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# PyMca 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 Lesser General Public License for more
+# details.
+#
+#############################################################################*/
+import os
+import sys
+import re
+import struct
+import numpy
+import copy
+from PyMca import DataObject
+
+if sys.version < '2.6':
+ def bytes(x):
+ return str(x)
+
+DEBUG = 0
+SOURCE_TYPE = "EdfFileStack"
+
+class MRCMap(DataObject.DataObject):
+ '''
+ Class to read MRC files
+
+ It reads the spectra into a DataObject instance.
+ This class info member contains all the parsed information.
+ This class data member contains the map itself as a 3D array.
+ '''
+ def __init__(self, filename):
+ '''
+ Parameters:
+ -----------
+ filename : str
+ Name of the input file.
+ It is expected to work with files generated at BESSY with raw2mrc
+ '''
+ DataObject.DataObject.__init__(self)
+ try:
+ fid = open(filename, 'rb')
+ header = fid.read(1024)
+ fid.close()
+ except:
+ fid.close()
+ raise
+
+ if not _isMRCHeader(header):
+ raise IOError("File does not seem to be an MRC file")
+
+ self.sourceName = filename
+
+ # check endianness
+ flag = struct.unpack("4B", header[212:216])[0]
+ if flag in [17, 18]:
+ # high endian (Motorola)
+ endianness = ">"
+ else:
+ # little endian (Intel)
+ endianness = "<"
+
+ fmt = endianness + "10i"
+ tenIntegers = struct.unpack(fmt, header[0:40])
+ nColumns, nRows, nImages, mode = tenIntegers[0:4]
+
+
+ fmt = endianness + "6f"
+ sixFloats = struct.unpack(fmt, header[40:64])
+ fmt = endianness + "3i"
+ threeIntegers = struct.unpack(fmt, header[64:76])
+ fmt = endianness + "3f"
+ threeFloats = struct.unpack(fmt, header[76:88])
+
+ # number of bytes in extended header
+ fmt = endianness + "i"
+ offset = struct.unpack(fmt, header[92:96])[0]
+
+ fmt = endianness + "ii"
+ imodStamp, imodFlags = struct.unpack(fmt, header[152:160])
+
+ if mode == 0:
+ # bytes
+ dataFormat = endianness + "%dB" % (nRows * nColumns)
+ elif mode == 1:
+ # signed short integers (16 bit)
+ dataFormat = endianness + "%dh" % (nRows * nColumns)
+ elif mode == 2:
+ # float
+ dataFormat = endianness + "%df" % (nRows * nColumns)
+ elif mode == 3:
+ # two shorts, complex data
+ dataFormat = endianness + "%dh" % (2 * nRows * nColumns)
+ elif mode == 4:
+ # two floats, complex data
+ dataFormat = endianness + "%df" % (2 * nRows * nColumns)
+ elif mode == 6:
+ # unsigned 16 bit integers (non-standard)
+ dataFormat = endianness + "%dH" % (nRows * nColumns)
+ elif mode == 16:
+ # unsigned char * 3(rgb data, non-standard)
+ dataFormat = endianness + "%dB" % (3 * nRows * nColumns)
+ else:
+ raise IOError("Data format not undestood")
+
+ if imodFlags == 1:
+ # bytes stored as signed
+ dataFormat = dataFormat.lower()
+
+
+ data = numpy.zeros((nImages, nRows * nColumns), numpy.float)
+ fid = open(filename, 'rb')
+ fileOffset = 1024 + offset
+ fid.seek(fileOffset)
+ dataSize= struct.calcsize(dataFormat)
+ try:
+ for i in range(nImages):
+ tmpData = fid.read(dataSize)
+ data[i] = struct.unpack(dataFormat, tmpData)
+ fid.close()
+ except:
+ fid.close()
+ raise
+
+ data.shape = nImages, nRows, nColumns
+ self.data = data
+
+ self.info = {}
+ self.info["SourceType"] = SOURCE_TYPE
+ self.info["SourceName"] = self.sourceName
+ shape = self.data.shape
+ for i in range(len(shape)):
+ key = 'Dim_%d' % (i + 1,)
+ self.info[key] = shape[i]
+ self.info["NumberOfFiles"] = 1
+ self.info["McaIndex"] = 0
+ self.info["McaCalib"] = [0.0, 1.0, 0.0]
+ self.info["Channel0"] = 0.0
+
+def _isMRCHeader(header):
+ if sys.version < '3.0':
+ test = "MAP "
+ else:
+ test = bytes("MAP ", "utf-8")
+ if struct.unpack("4s", header[208:212])[0] == test:
+ return True
+ else:
+ return False
+
+def isMRCFile(filename):
+ try:
+ fid = open(filename, 'rb')
+ header = fid.read(1024)
+ fid.close()
+ except:
+ fid.close()
+ return False
+ nColumns, nRows, nImages = struct.unpack("iii", header[0:12])
+ imodStamp, imodFlags = struct.unpack("ii", header[152:160])
+ #print(imodStamp, imodFlags)
+
+ # system byte order
+ #print("system ",sys.byteorder)
+
+ return _isMRCHeader(header)
+
+if __name__ == "__main__":
+ filename = None
+ if len(sys.argv) > 1:
+ filename = sys.argv[1]
+ print("is MRC File?", isMRCFile(filename))
+ instance = MRCMap(filename)
+ print(instance.info)
+ print(instance.data)
diff --git a/PyMca/McaAdvancedFitBatch.py b/PyMca/McaAdvancedFitBatch.py
index d335191..e161863 100644
--- a/PyMca/McaAdvancedFitBatch.py
+++ b/PyMca/McaAdvancedFitBatch.py
@@ -1,5 +1,5 @@
#/*##########################################################################
-# Copyright (C) 2004-2012 European Synchrotron Radiation Facility
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
@@ -157,7 +157,7 @@ class McaAdvancedFitBatch(object):
self.mcafit = ClassMcaTheory.McaTheory(self.__configList[i])
self.mcafit.enableOptimizedLinearFit()
inputfile = self._filelist[i]
- self.__row += 1
+ self.__row += 1 #should be plus fileStep?
self.onNewFile(inputfile, self._filelist)
self.file = self.getFileHandle(inputfile)
if self.pleaseBreak: break
@@ -170,6 +170,9 @@ class McaAdvancedFitBatch(object):
self.__stack = True
if self.__stack:
self.__processStack()
+ if self._HDF5:
+ # The complete stack has been analyzed
+ break
else:
self.__processOneFile()
if self.counter:
@@ -188,7 +191,8 @@ class McaAdvancedFitBatch(object):
if h5py.is_hdf5(inputfile):
self._HDF5 = True
try:
- return HDF5Stack1D.HDF5Stack1D([inputfile], self.selection)
+ return HDF5Stack1D.HDF5Stack1D(self._filelist,
+ self.selection)
except:
raise
ffile = self.__tryEdf(inputfile)
diff --git a/PyMca/NNMAModule.py b/PyMca/NNMAModule.py
index 6ece00f..4bdb2c2 100644
--- a/PyMca/NNMAModule.py
+++ b/PyMca/NNMAModule.py
@@ -1,4 +1,5 @@
__author__ = "Uwe Schmitt uschmitt@mineway.de, wrapped by V.A. Sole - ESRF"
+__license__ = "BSD"
__doc__ = """
This module is a simple wrapper to the py_nnma module of Uwe Schmitt (uschmitt@mineway.de)
in order to integrate it into PyMca. What follows is the documentation of py_nnma
diff --git a/PyMca/Object3D/Object3DQhull/Announce.txt b/PyMca/Object3D/Object3DQhull/Announce.txt
deleted file mode 100644
index ac8e052..0000000
--- a/PyMca/Object3D/Object3DQhull/Announce.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-
- Qhull 2012.1 2012/02/18
-
- http://www.qhull.org
- git@gitorious.org:qhull/qhull.git
- http://packages.debian.org/sid/libqhull5 [out-of-date]
- http://www6.uniovi.es/ftp/pub/mirrors/geom.umn.edu/software/ghindex.html
- http://www.geomview.org
- http://www.geom.uiuc.edu
-
-Qhull computes convex hulls, Delaunay triangulations, Voronoi diagrams,
-furthest-site Voronoi diagrams, and halfspace intersections about a point.
-It runs in 2-d, 3-d, 4-d, or higher. It implements the Quickhull algorithm
-for computing convex hulls. Qhull handles round-off errors from floating
-point arithmetic. It can approximate a convex hull.
-
-The program includes options for hull volume, facet area, partial hulls,
-input transformations, randomization, tracing, multiple output formats, and
-execution statistics. The program can be called from within your application.
-You can view the results in 2-d, 3-d and 4-d with Geomview.
-
-To download Qhull:
- http://www.qhull.org/download
- git@gitorious.org:qhull/qhull.git
- http://packages.debian.org/sid/libqhull5 [out-of-date]
-
-Download qhull-96.ps for:
-
- Barber, C. B., D.P. Dobkin, and H.T. Huhdanpaa, "The
- Quickhull Algorithm for Convex Hulls," ACM Trans. on
- Mathematical Software, 22(4):469-483, Dec. 1996.
- http://www.acm.org/pubs/citations/journals/toms/1996-22-4/p469-barber/
- http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.117.405
-
-Abstract:
-
-The convex hull of a set of points is the smallest convex set that contains
-the points. This article presents a practical convex hull algorithm that
-combines the two-dimensional Quickhull Algorithm with the general dimension
-Beneath-Beyond Algorithm. It is similar to the randomized, incremental
-algorithms for convex hull and Delaunay triangulation. We provide empirical
-evidence that the algorithm runs faster when the input contains non-extreme
-points, and that it uses less memory.
-
-Computational geometry algorithms have traditionally assumed that input sets
-are well behaved. When an algorithm is implemented with floating point
-arithmetic, this assumption can lead to serious errors. We briefly describe
-a solution to this problem when computing the convex hull in two, three, or
-four dimensions. The output is a set of "thick" facets that contain all
-possible exact convex hulls of the input. A variation is effective in five
-or more dimensions.
diff --git a/PyMca/Object3D/Object3DQhull/COPYING.txt b/PyMca/Object3D/Object3DQhull/COPYING.txt
deleted file mode 100644
index 7a73d9f..0000000
--- a/PyMca/Object3D/Object3DQhull/COPYING.txt
+++ /dev/null
@@ -1,38 +0,0 @@
- Qhull, Copyright (c) 1993-2012
-
- C.B. Barber
- Arlington, MA
-
- and
-
- The National Science and Technology Research Center for
- Computation and Visualization of Geometric Structures
- (The Geometry Center)
- University of Minnesota
-
- email: qhull@qhull.org
-
-This software includes Qhull from C.B. Barber and The Geometry Center.
-Qhull is copyrighted as noted above. Qhull is free software and may
-be obtained via http from www.qhull.org. It may be freely copied, modified,
-and redistributed under the following conditions:
-
-1. All copyright notices must remain intact in all files.
-
-2. A copy of this text file must be distributed along with any copies
- of Qhull that you redistribute; this includes copies that you have
- modified, or copies of programs or other software products that
- include Qhull.
-
-3. If you modify Qhull, you must include a notice giving the
- name of the person performing the modification, the date of
- modification, and the reason for such modification.
-
-4. When distributing modified versions of Qhull, or other software
- products that include Qhull, you must provide notice that the original
- source code may be obtained as noted above.
-
-5. There is no warranty or other guarantee of fitness for Qhull, it is
- provided solely "as is". Bug reports or fixes may be sent to
- qhull_bug@qhull.org; the authors may or may not act on them as
- they desire.
diff --git a/PyMca/Object3D/Object3DQhull/src/Object3DQhull.c b/PyMca/Object3D/Object3DQhull/Object3DQhull.c
index 7595c4f..7595c4f 100644
--- a/PyMca/Object3D/Object3DQhull/src/Object3DQhull.c
+++ b/PyMca/Object3D/Object3DQhull/Object3DQhull.c
diff --git a/PyMca/Object3D/Object3DQhull/REGISTER.txt b/PyMca/Object3D/Object3DQhull/REGISTER.txt
deleted file mode 100644
index 16ccb1a..0000000
--- a/PyMca/Object3D/Object3DQhull/REGISTER.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Dear Qhull User
-
-We would like to find out how you are using our software. Think of
-Qhull as a new kind of shareware: you share your science and successes
-with us, and we share our software and support with you.
-
-If you use Qhull, please send us a note telling
-us what you are doing with it.
-
-We need to know:
-
- (1) What you are working on - an abstract of your work would be
- fine.
-
- (2) How Qhull has helped you, for example, by increasing your
- productivity or allowing you to do things you could not do
- before. If Qhull had a direct bearing on your work, please
- tell us about this.
-
-We encourage you to cite Qhull in your publications.
-
-To cite Qhull, please use
-
- Barber, C.B., Dobkin, D.P., and Huhdanpaa, H.T., "The Quickhull
- algorithm for convex hulls," ACM Trans. on Mathematical Software,
- 22(4):469-483, Dec 1996, http://www.qhull.org.
-
-Please send e-mail to
-
- bradb@shore.net
-
-Thank you!
diff --git a/PyMca/Object3D/Object3DQhull/src/geom.c b/PyMca/Object3D/Object3DQhull/src/geom.c
deleted file mode 100644
index 0f3b9d9..0000000
--- a/PyMca/Object3D/Object3DQhull/src/geom.c
+++ /dev/null
@@ -1,1234 +0,0 @@
-/*<html><pre> -<a href="qh-geom.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- geom.c
- geometric routines of qhull
-
- see qh-geom.htm and geom.h
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/geom.c#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
- infrequent code goes into geom2.c
-*/
-
-#include "qhull_a.h"
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="distplane">-</a>
-
- qh_distplane( point, facet, dist )
- return distance from point to facet
-
- returns:
- dist
- if qh.RANDOMdist, joggles result
-
- notes:
- dist > 0 if point is above facet (i.e., outside)
- does not error (for qh_sortfacets, qh_outerinner)
-
- see:
- qh_distnorm in geom2.c
- qh_distplane [geom.c], QhullFacet::distance, and QhullHyperplane::distance are copies
-*/
-void qh_distplane(pointT *point, facetT *facet, realT *dist) {
- coordT *normal= facet->normal, *coordp, randr;
- int k;
-
- switch (qh hull_dim){
- case 2:
- *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1];
- break;
- case 3:
- *dist= facet->offset + point[0] * normal[0] + point[1] * normal[1] + point[2] * normal[2];
- break;
- case 4:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3];
- break;
- case 5:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4];
- break;
- case 6:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5];
- break;
- case 7:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6];
- break;
- case 8:
- *dist= facet->offset+point[0]*normal[0]+point[1]*normal[1]+point[2]*normal[2]+point[3]*normal[3]+point[4]*normal[4]+point[5]*normal[5]+point[6]*normal[6]+point[7]*normal[7];
- break;
- default:
- *dist= facet->offset;
- coordp= point;
- for (k=qh hull_dim; k--; )
- *dist += *coordp++ * *normal++;
- break;
- }
- zinc_(Zdistplane);
- if (!qh RANDOMdist && qh IStracing < 4)
- return;
- if (qh RANDOMdist) {
- randr= qh_RANDOMint;
- *dist += (2.0 * randr / qh_RANDOMmax - 1.0) *
- qh RANDOMfactor * qh MAXabs_coord;
- }
- if (qh IStracing >= 4) {
- qh_fprintf(qh ferr, 8001, "qh_distplane: ");
- qh_fprintf(qh ferr, 8002, qh_REAL_1, *dist);
- qh_fprintf(qh ferr, 8003, "from p%d to f%d\n", qh_pointid(point), facet->id);
- }
- return;
-} /* distplane */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbest">-</a>
-
- qh_findbest( point, startfacet, bestoutside, qh_ISnewfacets, qh_NOupper, dist, isoutside, numpart )
- find facet that is furthest below a point
- for upperDelaunay facets
- returns facet only if !qh_NOupper and clearly above
-
- input:
- starts search at 'startfacet' (can not be flipped)
- if !bestoutside(qh_ALL), stops at qh.MINoutside
-
- returns:
- best facet (reports error if NULL)
- early out if isoutside defined and bestdist > qh.MINoutside
- dist is distance to facet
- isoutside is true if point is outside of facet
- numpart counts the number of distance tests
-
- see also:
- qh_findbestnew()
-
- notes:
- If merging (testhorizon), searches horizon facets of coplanar best facets because
- after qh_distplane, this and qh_partitionpoint are the most expensive in 3-d
- avoid calls to distplane, function calls, and real number operations.
- caller traces result
- Optimized for outside points. Tried recording a search set for qh_findhorizon.
- Made code more complicated.
-
- when called by qh_partitionvisible():
- indicated by qh_ISnewfacets
- qh.newfacet_list is list of simplicial, new facets
- qh_findbestnew set if qh_sharpnewfacets returns True (to use qh_findbestnew)
- qh.bestfacet_notsharp set if qh_sharpnewfacets returns False
-
- when called by qh_findfacet(), qh_partitionpoint(), qh_partitioncoplanar(),
- qh_check_bestdist(), qh_addpoint()
- indicated by !qh_ISnewfacets
- returns best facet in neighborhood of given facet
- this is best facet overall if dist > - qh.MAXcoplanar
- or hull has at least a "spherical" curvature
-
- design:
- initialize and test for early exit
- repeat while there are better facets
- for each neighbor of facet
- exit if outside facet found
- test for better facet
- if point is inside and partitioning
- test for new facets with a "sharp" intersection
- if so, future calls go to qh_findbestnew()
- test horizon facets
-*/
-facetT *qh_findbest(pointT *point, facetT *startfacet,
- boolT bestoutside, boolT isnewfacets, boolT noupper,
- realT *dist, boolT *isoutside, int *numpart) {
- realT bestdist= -REALmax/2 /* avoid underflow */;
- facetT *facet, *neighbor, **neighborp;
- facetT *bestfacet= NULL, *lastfacet= NULL;
- int oldtrace= qh IStracing;
- unsigned int visitid= ++qh visit_id;
- int numpartnew=0;
- boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
- zinc_(Zfindbest);
- if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
- if (qh TRACElevel > qh IStracing)
- qh IStracing= qh TRACElevel;
- qh_fprintf(qh ferr, 8004, "qh_findbest: point p%d starting at f%d isnewfacets? %d, unless %d exit if > %2.2g\n",
- qh_pointid(point), startfacet->id, isnewfacets, bestoutside, qh MINoutside);
- qh_fprintf(qh ferr, 8005, " testhorizon? %d noupper? %d", testhorizon, noupper);
- qh_fprintf(qh ferr, 8006, " Last point added was p%d.", qh furthest_id);
- qh_fprintf(qh ferr, 8007, " Last merge was #%d. max_outside %2.2g\n", zzval_(Ztotmerge), qh max_outside);
- }
- if (isoutside)
- *isoutside= True;
- if (!startfacet->flipped) { /* test startfacet */
- *numpart= 1;
- qh_distplane(point, startfacet, dist); /* this code is duplicated below */
- if (!bestoutside && *dist >= qh MINoutside
- && (!startfacet->upperdelaunay || !noupper)) {
- bestfacet= startfacet;
- goto LABELreturn_best;
- }
- bestdist= *dist;
- if (!startfacet->upperdelaunay) {
- bestfacet= startfacet;
- }
- }else
- *numpart= 0;
- startfacet->visitid= visitid;
- facet= startfacet;
- while (facet) {
- trace4((qh ferr, 4001, "qh_findbest: neighbors of f%d, bestdist %2.2g f%d\n",
- facet->id, bestdist, getid_(bestfacet)));
- lastfacet= facet;
- FOREACHneighbor_(facet) {
- if (!neighbor->newfacet && isnewfacets)
- continue;
- if (neighbor->visitid == visitid)
- continue;
- neighbor->visitid= visitid;
- if (!neighbor->flipped) { /* code duplicated above */
- (*numpart)++;
- qh_distplane(point, neighbor, dist);
- if (*dist > bestdist) {
- if (!bestoutside && *dist >= qh MINoutside
- && (!neighbor->upperdelaunay || !noupper)) {
- bestfacet= neighbor;
- goto LABELreturn_best;
- }
- if (!neighbor->upperdelaunay) {
- bestfacet= neighbor;
- bestdist= *dist;
- break; /* switch to neighbor */
- }else if (!bestfacet) {
- bestdist= *dist;
- break; /* switch to neighbor */
- }
- } /* end of *dist>bestdist */
- } /* end of !flipped */
- } /* end of FOREACHneighbor */
- facet= neighbor; /* non-NULL only if *dist>bestdist */
- } /* end of while facet (directed search) */
- if (isnewfacets) {
- if (!bestfacet) {
- bestdist= -REALmax/2;
- bestfacet= qh_findbestnew(point, startfacet->next, &bestdist, bestoutside, isoutside, &numpartnew);
- testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
- }else if (!qh findbest_notsharp && bestdist < - qh DISTround) {
- if (qh_sharpnewfacets()) {
- /* seldom used, qh_findbestnew will retest all facets */
- zinc_(Zfindnewsharp);
- bestfacet= qh_findbestnew(point, bestfacet, &bestdist, bestoutside, isoutside, &numpartnew);
- testhorizon= False; /* qh_findbestnew calls qh_findbesthorizon */
- qh findbestnew= True;
- }else
- qh findbest_notsharp= True;
- }
- }
- if (!bestfacet)
- bestfacet= qh_findbestlower(lastfacet, point, &bestdist, numpart);
- if (testhorizon)
- bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet, noupper, &bestdist, &numpartnew);
- *dist= bestdist;
- if (isoutside && bestdist < qh MINoutside)
- *isoutside= False;
-LABELreturn_best:
- zadd_(Zfindbesttot, *numpart);
- zmax_(Zfindbestmax, *numpart);
- (*numpart) += numpartnew;
- qh IStracing= oldtrace;
- return bestfacet;
-} /* findbest */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbesthorizon">-</a>
-
- qh_findbesthorizon( qh_IScheckmax, point, startfacet, qh_NOupper, &bestdist, &numpart )
- search coplanar and better horizon facets from startfacet/bestdist
- ischeckmax turns off statistics and minsearch update
- all arguments must be initialized
- returns(ischeckmax):
- best facet
- returns(!ischeckmax):
- best facet that is not upperdelaunay
- allows upperdelaunay that is clearly outside
- returns:
- bestdist is distance to bestfacet
- numpart -- updates number of distance tests
-
- notes:
- no early out -- use qh_findbest() or qh_findbestnew()
- Searches coplanar or better horizon facets
-
- when called by qh_check_maxout() (qh_IScheckmax)
- startfacet must be closest to the point
- Otherwise, if point is beyond and below startfacet, startfacet may be a local minimum
- even though other facets are below the point.
- updates facet->maxoutside for good, visited facets
- may return NULL
-
- searchdist is qh.max_outside + 2 * DISTround
- + max( MINvisible('Vn'), MAXcoplanar('Un'));
- This setting is a guess. It must be at least max_outside + 2*DISTround
- because a facet may have a geometric neighbor across a vertex
-
- design:
- for each horizon facet of coplanar best facets
- continue if clearly inside
- unless upperdelaunay or clearly outside
- update best facet
-*/
-facetT *qh_findbesthorizon(boolT ischeckmax, pointT* point, facetT *startfacet, boolT noupper, realT *bestdist, int *numpart) {
- facetT *bestfacet= startfacet;
- realT dist;
- facetT *neighbor, **neighborp, *facet;
- facetT *nextfacet= NULL; /* optimize last facet of coplanarfacetset */
- int numpartinit= *numpart, coplanarfacetset_size;
- unsigned int visitid= ++qh visit_id;
- boolT newbest= False; /* for tracing */
- realT minsearch, searchdist; /* skip facets that are too far from point */
-
- if (!ischeckmax) {
- zinc_(Zfindhorizon);
- }else {
-#if qh_MAXoutside
- if ((!qh ONLYgood || startfacet->good) && *bestdist > startfacet->maxoutside)
- startfacet->maxoutside= *bestdist;
-#endif
- }
- searchdist= qh_SEARCHdist; /* multiple of qh.max_outside and precision constants */
- minsearch= *bestdist - searchdist;
- if (ischeckmax) {
- /* Always check coplanar facets. Needed for RBOX 1000 s Z1 G1e-13 t996564279 | QHULL Tv */
- minimize_(minsearch, -searchdist);
- }
- coplanarfacetset_size= 0;
- facet= startfacet;
- while (True) {
- trace4((qh ferr, 4002, "qh_findbesthorizon: neighbors of f%d bestdist %2.2g f%d ischeckmax? %d noupper? %d minsearch %2.2g searchdist %2.2g\n",
- facet->id, *bestdist, getid_(bestfacet), ischeckmax, noupper,
- minsearch, searchdist));
- FOREACHneighbor_(facet) {
- if (neighbor->visitid == visitid)
- continue;
- neighbor->visitid= visitid;
- if (!neighbor->flipped) {
- qh_distplane(point, neighbor, &dist);
- (*numpart)++;
- if (dist > *bestdist) {
- if (!neighbor->upperdelaunay || ischeckmax || (!noupper && dist >= qh MINoutside)) {
- bestfacet= neighbor;
- *bestdist= dist;
- newbest= True;
- if (!ischeckmax) {
- minsearch= dist - searchdist;
- if (dist > *bestdist + searchdist) {
- zinc_(Zfindjump); /* everything in qh.coplanarfacetset at least searchdist below */
- coplanarfacetset_size= 0;
- }
- }
- }
- }else if (dist < minsearch)
- continue; /* if ischeckmax, dist can't be positive */
-#if qh_MAXoutside
- if (ischeckmax && dist > neighbor->maxoutside)
- neighbor->maxoutside= dist;
-#endif
- } /* end of !flipped */
- if (nextfacet) {
- if (!coplanarfacetset_size++) {
- SETfirst_(qh coplanarfacetset)= nextfacet;
- SETtruncate_(qh coplanarfacetset, 1);
- }else
- qh_setappend(&qh coplanarfacetset, nextfacet); /* Was needed for RBOX 1000 s W1e-13 P0 t996547055 | QHULL d Qbb Qc Tv
- and RBOX 1000 s Z1 G1e-13 t996564279 | qhull Tv */
- }
- nextfacet= neighbor;
- } /* end of EACHneighbor */
- facet= nextfacet;
- if (facet)
- nextfacet= NULL;
- else if (!coplanarfacetset_size)
- break;
- else if (!--coplanarfacetset_size) {
- facet= SETfirstt_(qh coplanarfacetset, facetT);
- SETtruncate_(qh coplanarfacetset, 0);
- }else
- facet= (facetT*)qh_setdellast(qh coplanarfacetset);
- } /* while True, for each facet in qh.coplanarfacetset */
- if (!ischeckmax) {
- zadd_(Zfindhorizontot, *numpart - numpartinit);
- zmax_(Zfindhorizonmax, *numpart - numpartinit);
- if (newbest)
- zinc_(Zparthorizon);
- }
- trace4((qh ferr, 4003, "qh_findbesthorizon: newbest? %d bestfacet f%d bestdist %2.2g\n", newbest, getid_(bestfacet), *bestdist));
- return bestfacet;
-} /* findbesthorizon */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findbestnew">-</a>
-
- qh_findbestnew( point, startfacet, dist, isoutside, numpart )
- find best newfacet for point
- searches all of qh.newfacet_list starting at startfacet
- searches horizon facets of coplanar best newfacets
- searches all facets if startfacet == qh.facet_list
- returns:
- best new or horizon facet that is not upperdelaunay
- early out if isoutside and not 'Qf'
- dist is distance to facet
- isoutside is true if point is outside of facet
- numpart is number of distance tests
-
- notes:
- Always used for merged new facets (see qh_USEfindbestnew)
- Avoids upperdelaunay facet unless (isoutside and outside)
-
- Uses qh.visit_id, qh.coplanarfacetset.
- If share visit_id with qh_findbest, coplanarfacetset is incorrect.
-
- If merging (testhorizon), searches horizon facets of coplanar best facets because
- a point maybe coplanar to the bestfacet, below its horizon facet,
- and above a horizon facet of a coplanar newfacet. For example,
- rbox 1000 s Z1 G1e-13 | qhull
- rbox 1000 s W1e-13 P0 t992110337 | QHULL d Qbb Qc
-
- qh_findbestnew() used if
- qh_sharpnewfacets -- newfacets contains a sharp angle
- if many merges, qh_premerge found a merge, or 'Qf' (qh.findbestnew)
-
- see also:
- qh_partitionall() and qh_findbest()
-
- design:
- for each new facet starting from startfacet
- test distance from point to facet
- return facet if clearly outside
- unless upperdelaunay and a lowerdelaunay exists
- update best facet
- test horizon facets
-*/
-facetT *qh_findbestnew(pointT *point, facetT *startfacet,
- realT *dist, boolT bestoutside, boolT *isoutside, int *numpart) {
- realT bestdist= -REALmax/2;
- facetT *bestfacet= NULL, *facet;
- int oldtrace= qh IStracing, i;
- unsigned int visitid= ++qh visit_id;
- realT distoutside= 0.0;
- boolT isdistoutside; /* True if distoutside is defined */
- boolT testhorizon = True; /* needed if precise, e.g., rbox c D6 | qhull Q0 Tv */
-
- if (!startfacet) {
- if (qh MERGING)
- qh_fprintf(qh ferr, 6001, "qhull precision error (qh_findbestnew): merging has formed and deleted a cone of new facets. Can not continue.\n");
- else
- qh_fprintf(qh ferr, 6002, "qhull internal error (qh_findbestnew): no new facets for point p%d\n",
- qh furthest_id);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- zinc_(Zfindnew);
- if (qh BESToutside || bestoutside)
- isdistoutside= False;
- else {
- isdistoutside= True;
- distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
- }
- if (isoutside)
- *isoutside= True;
- *numpart= 0;
- if (qh IStracing >= 3 || (qh TRACElevel && qh TRACEpoint >= 0 && qh TRACEpoint == qh_pointid(point))) {
- if (qh TRACElevel > qh IStracing)
- qh IStracing= qh TRACElevel;
- qh_fprintf(qh ferr, 8008, "qh_findbestnew: point p%d facet f%d. Stop? %d if dist > %2.2g\n",
- qh_pointid(point), startfacet->id, isdistoutside, distoutside);
- qh_fprintf(qh ferr, 8009, " Last point added p%d visitid %d.", qh furthest_id, visitid);
- qh_fprintf(qh ferr, 8010, " Last merge was #%d.\n", zzval_(Ztotmerge));
- }
- /* visit all new facets starting with startfacet, maybe qh facet_list */
- for (i=0, facet=startfacet; i < 2; i++, facet= qh newfacet_list) {
- FORALLfacet_(facet) {
- if (facet == startfacet && i)
- break;
- facet->visitid= visitid;
- if (!facet->flipped) {
- qh_distplane(point, facet, dist);
- (*numpart)++;
- if (*dist > bestdist) {
- if (!facet->upperdelaunay || *dist >= qh MINoutside) {
- bestfacet= facet;
- if (isdistoutside && *dist >= distoutside)
- goto LABELreturn_bestnew;
- bestdist= *dist;
- }
- }
- } /* end of !flipped */
- } /* FORALLfacet from startfacet or qh newfacet_list */
- }
- if (testhorizon || !bestfacet)
- bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, bestfacet ? bestfacet : startfacet,
- !qh_NOupper, &bestdist, numpart);
- *dist= bestdist;
- if (isoutside && *dist < qh MINoutside)
- *isoutside= False;
-LABELreturn_bestnew:
- zadd_(Zfindnewtot, *numpart);
- zmax_(Zfindnewmax, *numpart);
- trace4((qh ferr, 4004, "qh_findbestnew: bestfacet f%d bestdist %2.2g\n", getid_(bestfacet), *dist));
- qh IStracing= oldtrace;
- return bestfacet;
-} /* findbestnew */
-
-/* ============ hyperplane functions -- keep code together [?] ============ */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="backnormal">-</a>
-
- qh_backnormal( rows, numrow, numcol, sign, normal, nearzero )
- given an upper-triangular rows array and a sign,
- solve for normal equation x using back substitution over rows U
-
- returns:
- normal= x
-
- if will not be able to divzero() when normalized(qh.MINdenom_2 and qh.MINdenom_1_2),
- if fails on last row
- this means that the hyperplane intersects [0,..,1]
- sets last coordinate of normal to sign
- otherwise
- sets tail of normal to [...,sign,0,...], i.e., solves for b= [0...0]
- sets nearzero
-
- notes:
- assumes numrow == numcol-1
-
- see Golub & van Loan 4.4-9 for back substitution
-
- solves Ux=b where Ax=b and PA=LU
- b= [0,...,0,sign or 0] (sign is either -1 or +1)
- last row of A= [0,...,0,1]
-
- 1) Ly=Pb == y=b since P only permutes the 0's of b
-
- design:
- for each row from end
- perform back substitution
- if near zero
- use qh_divzero for division
- if zero divide and not last row
- set tail of normal to 0
-*/
-void qh_backnormal(realT **rows, int numrow, int numcol, boolT sign,
- coordT *normal, boolT *nearzero) {
- int i, j;
- coordT *normalp, *normal_tail, *ai, *ak;
- realT diagonal;
- boolT waszero;
- int zerocol= -1;
-
- normalp= normal + numcol - 1;
- *normalp--= (sign ? -1.0 : 1.0);
- for (i=numrow; i--; ) {
- *normalp= 0.0;
- ai= rows[i] + i + 1;
- ak= normalp+1;
- for (j=i+1; j < numcol; j++)
- *normalp -= *ai++ * *ak++;
- diagonal= (rows[i])[i];
- if (fabs_(diagonal) > qh MINdenom_2)
- *(normalp--) /= diagonal;
- else {
- waszero= False;
- *normalp= qh_divzero(*normalp, diagonal, qh MINdenom_1_2, &waszero);
- if (waszero) {
- zerocol= i;
- *(normalp--)= (sign ? -1.0 : 1.0);
- for (normal_tail= normalp+2; normal_tail < normal + numcol; normal_tail++)
- *normal_tail= 0.0;
- }else
- normalp--;
- }
- }
- if (zerocol != -1) {
- zzinc_(Zback0);
- *nearzero= True;
- trace4((qh ferr, 4005, "qh_backnormal: zero diagonal at column %d.\n", i));
- qh_precision("zero diagonal on back substitution");
- }
-} /* backnormal */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="gausselim">-</a>
-
- qh_gausselim( rows, numrow, numcol, sign )
- Gaussian elimination with partial pivoting
-
- returns:
- rows is upper triangular (includes row exchanges)
- flips sign for each row exchange
- sets nearzero if pivot[k] < qh.NEARzero[k], else clears it
-
- notes:
- if nearzero, the determinant's sign may be incorrect.
- assumes numrow <= numcol
-
- design:
- for each row
- determine pivot and exchange rows if necessary
- test for near zero
- perform gaussian elimination step
-*/
-void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero) {
- realT *ai, *ak, *rowp, *pivotrow;
- realT n, pivot, pivot_abs= 0.0, temp;
- int i, j, k, pivoti, flip=0;
-
- *nearzero= False;
- for (k=0; k < numrow; k++) {
- pivot_abs= fabs_((rows[k])[k]);
- pivoti= k;
- for (i=k+1; i < numrow; i++) {
- if ((temp= fabs_((rows[i])[k])) > pivot_abs) {
- pivot_abs= temp;
- pivoti= i;
- }
- }
- if (pivoti != k) {
- rowp= rows[pivoti];
- rows[pivoti]= rows[k];
- rows[k]= rowp;
- *sign ^= 1;
- flip ^= 1;
- }
- if (pivot_abs <= qh NEARzero[k]) {
- *nearzero= True;
- if (pivot_abs == 0.0) { /* remainder of column == 0 */
- if (qh IStracing >= 4) {
- qh_fprintf(qh ferr, 8011, "qh_gausselim: 0 pivot at column %d. (%2.2g < %2.2g)\n", k, pivot_abs, qh DISTround);
- qh_printmatrix(qh ferr, "Matrix:", rows, numrow, numcol);
- }
- zzinc_(Zgauss0);
- qh_precision("zero pivot for Gaussian elimination");
- goto LABELnextcol;
- }
- }
- pivotrow= rows[k] + k;
- pivot= *pivotrow++; /* signed value of pivot, and remainder of row */
- for (i=k+1; i < numrow; i++) {
- ai= rows[i] + k;
- ak= pivotrow;
- n= (*ai++)/pivot; /* divzero() not needed since |pivot| >= |*ai| */
- for (j= numcol - (k+1); j--; )
- *ai++ -= n * *ak++;
- }
- LABELnextcol:
- ;
- }
- wmin_(Wmindenom, pivot_abs); /* last pivot element */
- if (qh IStracing >= 5)
- qh_printmatrix(qh ferr, "qh_gausselem: result", rows, numrow, numcol);
-} /* gausselim */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getangle">-</a>
-
- qh_getangle( vect1, vect2 )
- returns the dot product of two vectors
- if qh.RANDOMdist, joggles result
-
- notes:
- the angle may be > 1.0 or < -1.0 because of roundoff errors
-
-*/
-realT qh_getangle(pointT *vect1, pointT *vect2) {
- realT angle= 0, randr;
- int k;
-
- for (k=qh hull_dim; k--; )
- angle += *vect1++ * *vect2++;
- if (qh RANDOMdist) {
- randr= qh_RANDOMint;
- angle += (2.0 * randr / qh_RANDOMmax - 1.0) *
- qh RANDOMfactor;
- }
- trace4((qh ferr, 4006, "qh_getangle: %2.2g\n", angle));
- return(angle);
-} /* getangle */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getcenter">-</a>
-
- qh_getcenter( vertices )
- returns arithmetic center of a set of vertices as a new point
-
- notes:
- allocates point array for center
-*/
-pointT *qh_getcenter(setT *vertices) {
- int k;
- pointT *center, *coord;
- vertexT *vertex, **vertexp;
- int count= qh_setsize(vertices);
-
- if (count < 2) {
- qh_fprintf(qh ferr, 6003, "qhull internal error (qh_getcenter): not defined for %d points\n", count);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- center= (pointT *)qh_memalloc(qh normal_size);
- for (k=0; k < qh hull_dim; k++) {
- coord= center+k;
- *coord= 0.0;
- FOREACHvertex_(vertices)
- *coord += vertex->point[k];
- *coord /= count;
- }
- return(center);
-} /* getcenter */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getcentrum">-</a>
-
- qh_getcentrum( facet )
- returns the centrum for a facet as a new point
-
- notes:
- allocates the centrum
-*/
-pointT *qh_getcentrum(facetT *facet) {
- realT dist;
- pointT *centrum, *point;
-
- point= qh_getcenter(facet->vertices);
- zzinc_(Zcentrumtests);
- qh_distplane(point, facet, &dist);
- centrum= qh_projectpoint(point, facet, dist);
- qh_memfree(point, qh normal_size);
- trace4((qh ferr, 4007, "qh_getcentrum: for f%d, %d vertices dist= %2.2g\n",
- facet->id, qh_setsize(facet->vertices), dist));
- return centrum;
-} /* getcentrum */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getdistance">-</a>
-
- qh_getdistance( facet, neighbor, mindist, maxdist )
- returns the maxdist and mindist distance of any vertex from neighbor
-
- returns:
- the max absolute value
-
- design:
- for each vertex of facet that is not in neighbor
- test the distance from vertex to neighbor
-*/
-realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist) {
- vertexT *vertex, **vertexp;
- realT dist, maxd, mind;
-
- FOREACHvertex_(facet->vertices)
- vertex->seen= False;
- FOREACHvertex_(neighbor->vertices)
- vertex->seen= True;
- mind= 0.0;
- maxd= 0.0;
- FOREACHvertex_(facet->vertices) {
- if (!vertex->seen) {
- zzinc_(Zbestdist);
- qh_distplane(vertex->point, neighbor, &dist);
- if (dist < mind)
- mind= dist;
- else if (dist > maxd)
- maxd= dist;
- }
- }
- *mindist= mind;
- *maxdist= maxd;
- mind= -mind;
- if (maxd > mind)
- return maxd;
- else
- return mind;
-} /* getdistance */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="normalize">-</a>
-
- qh_normalize( normal, dim, toporient )
- normalize a vector and report if too small
- does not use min norm
-
- see:
- qh_normalize2
-*/
-void qh_normalize(coordT *normal, int dim, boolT toporient) {
- qh_normalize2( normal, dim, toporient, NULL, NULL);
-} /* normalize */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="normalize2">-</a>
-
- qh_normalize2( normal, dim, toporient, minnorm, ismin )
- normalize a vector and report if too small
- qh.MINdenom/MINdenom1 are the upper limits for divide overflow
-
- returns:
- normalized vector
- flips sign if !toporient
- if minnorm non-NULL,
- sets ismin if normal < minnorm
-
- notes:
- if zero norm
- sets all elements to sqrt(1.0/dim)
- if divide by zero (divzero())
- sets largest element to +/-1
- bumps Znearlysingular
-
- design:
- computes norm
- test for minnorm
- if not near zero
- normalizes normal
- else if zero norm
- sets normal to standard value
- else
- uses qh_divzero to normalize
- if nearzero
- sets norm to direction of maximum value
-*/
-void qh_normalize2 (coordT *normal, int dim, boolT toporient,
- realT *minnorm, boolT *ismin) {
- int k;
- realT *colp, *maxp, norm= 0, temp, *norm1, *norm2, *norm3;
- boolT zerodiv;
-
- norm1= normal+1;
- norm2= normal+2;
- norm3= normal+3;
- if (dim == 2)
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1));
- else if (dim == 3)
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2));
- else if (dim == 4) {
- norm= sqrt((*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
- + (*norm3)*(*norm3));
- }else if (dim > 4) {
- norm= (*normal)*(*normal) + (*norm1)*(*norm1) + (*norm2)*(*norm2)
- + (*norm3)*(*norm3);
- for (k=dim-4, colp=normal+4; k--; colp++)
- norm += (*colp) * (*colp);
- norm= sqrt(norm);
- }
- if (minnorm) {
- if (norm < *minnorm)
- *ismin= True;
- else
- *ismin= False;
- }
- wmin_(Wmindenom, norm);
- if (norm > qh MINdenom) {
- if (!toporient)
- norm= -norm;
- *normal /= norm;
- *norm1 /= norm;
- if (dim == 2)
- ; /* all done */
- else if (dim == 3)
- *norm2 /= norm;
- else if (dim == 4) {
- *norm2 /= norm;
- *norm3 /= norm;
- }else if (dim >4) {
- *norm2 /= norm;
- *norm3 /= norm;
- for (k=dim-4, colp=normal+4; k--; )
- *colp++ /= norm;
- }
- }else if (norm == 0.0) {
- temp= sqrt(1.0/dim);
- for (k=dim, colp=normal; k--; )
- *colp++ = temp;
- }else {
- if (!toporient)
- norm= -norm;
- for (k=dim, colp=normal; k--; colp++) { /* k used below */
- temp= qh_divzero(*colp, norm, qh MINdenom_1, &zerodiv);
- if (!zerodiv)
- *colp= temp;
- else {
- maxp= qh_maxabsval(normal, dim);
- temp= ((*maxp * norm >= 0.0) ? 1.0 : -1.0);
- for (k=dim, colp=normal; k--; colp++)
- *colp= 0.0;
- *maxp= temp;
- zzinc_(Znearlysingular);
- trace0((qh ferr, 1, "qh_normalize: norm=%2.2g too small during p%d\n",
- norm, qh furthest_id));
- return;
- }
- }
- }
-} /* normalize */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="projectpoint">-</a>
-
- qh_projectpoint( point, facet, dist )
- project point onto a facet by dist
-
- returns:
- returns a new point
-
- notes:
- if dist= distplane(point,facet)
- this projects point to hyperplane
- assumes qh_memfree_() is valid for normal_size
-*/
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist) {
- pointT *newpoint, *np, *normal;
- int normsize= qh normal_size;
- int k;
- void **freelistp; /* used !qh_NOmem */
-
- qh_memalloc_(normsize, freelistp, newpoint, pointT);
- np= newpoint;
- normal= facet->normal;
- for (k=qh hull_dim; k--; )
- *(np++)= *point++ - dist * *normal++;
- return(newpoint);
-} /* projectpoint */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="setfacetplane">-</a>
-
- qh_setfacetplane( facet )
- sets the hyperplane for a facet
- if qh.RANDOMdist, joggles hyperplane
-
- notes:
- uses global buffers qh.gm_matrix and qh.gm_row
- overwrites facet->normal if already defined
- updates Wnewvertex if PRINTstatistics
- sets facet->upperdelaunay if upper envelope of Delaunay triangulation
-
- design:
- copy vertex coordinates to qh.gm_matrix/gm_row
- compute determinate
- if nearzero
- recompute determinate with gaussian elimination
- if nearzero
- force outside orientation by testing interior point
-*/
-void qh_setfacetplane(facetT *facet) {
- pointT *point;
- vertexT *vertex, **vertexp;
- int normsize= qh normal_size;
- int k,i, oldtrace= 0;
- realT dist;
- void **freelistp; /* used !qh_NOmem */
- coordT *coord, *gmcoord;
- pointT *point0= SETfirstt_(facet->vertices, vertexT)->point;
- boolT nearzero= False;
-
- zzinc_(Zsetplane);
- if (!facet->normal)
- qh_memalloc_(normsize, freelistp, facet->normal, coordT);
- if (facet == qh tracefacet) {
- oldtrace= qh IStracing;
- qh IStracing= 5;
- qh_fprintf(qh ferr, 8012, "qh_setfacetplane: facet f%d created.\n", facet->id);
- qh_fprintf(qh ferr, 8013, " Last point added to hull was p%d.", qh furthest_id);
- if (zzval_(Ztotmerge))
- qh_fprintf(qh ferr, 8014, " Last merge was #%d.", zzval_(Ztotmerge));
- qh_fprintf(qh ferr, 8015, "\n\nCurrent summary is:\n");
- qh_printsummary(qh ferr);
- }
- if (qh hull_dim <= 4) {
- i= 0;
- if (qh RANDOMdist) {
- gmcoord= qh gm_matrix;
- FOREACHvertex_(facet->vertices) {
- qh gm_row[i++]= gmcoord;
- coord= vertex->point;
- for (k=qh hull_dim; k--; )
- *(gmcoord++)= *coord++ * qh_randomfactor(qh RANDOMa, qh RANDOMb);
- }
- }else {
- FOREACHvertex_(facet->vertices)
- qh gm_row[i++]= vertex->point;
- }
- qh_sethyperplane_det(qh hull_dim, qh gm_row, point0, facet->toporient,
- facet->normal, &facet->offset, &nearzero);
- }
- if (qh hull_dim > 4 || nearzero) {
- i= 0;
- gmcoord= qh gm_matrix;
- FOREACHvertex_(facet->vertices) {
- if (vertex->point != point0) {
- qh gm_row[i++]= gmcoord;
- coord= vertex->point;
- point= point0;
- for (k=qh hull_dim; k--; )
- *(gmcoord++)= *coord++ - *point++;
- }
- }
- qh gm_row[i]= gmcoord; /* for areasimplex */
- if (qh RANDOMdist) {
- gmcoord= qh gm_matrix;
- for (i=qh hull_dim-1; i--; ) {
- for (k=qh hull_dim; k--; )
- *(gmcoord++) *= qh_randomfactor(qh RANDOMa, qh RANDOMb);
- }
- }
- qh_sethyperplane_gauss(qh hull_dim, qh gm_row, point0, facet->toporient,
- facet->normal, &facet->offset, &nearzero);
- if (nearzero) {
- if (qh_orientoutside(facet)) {
- trace0((qh ferr, 2, "qh_setfacetplane: flipped orientation after testing interior_point during p%d\n", qh furthest_id));
- /* this is part of using Gaussian Elimination. For example in 5-d
- 1 1 1 1 0
- 1 1 1 1 1
- 0 0 0 1 0
- 0 1 0 0 0
- 1 0 0 0 0
- norm= 0.38 0.38 -0.76 0.38 0
- has a determinate of 1, but g.e. after subtracting pt. 0 has
- 0's in the diagonal, even with full pivoting. It does work
- if you subtract pt. 4 instead. */
- }
- }
- }
- facet->upperdelaunay= False;
- if (qh DELAUNAY) {
- if (qh UPPERdelaunay) { /* matches qh_triangulate_facet and qh.lower_threshold in qh_initbuild */
- if (facet->normal[qh hull_dim -1] >= qh ANGLEround * qh_ZEROdelaunay)
- facet->upperdelaunay= True;
- }else {
- if (facet->normal[qh hull_dim -1] > -qh ANGLEround * qh_ZEROdelaunay)
- facet->upperdelaunay= True;
- }
- }
- if (qh PRINTstatistics || qh IStracing || qh TRACElevel || qh JOGGLEmax < REALmax) {
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- FOREACHvertex_(facet->vertices) {
- if (vertex->point != point0) {
- boolT istrace= False;
- zinc_(Zdiststat);
- qh_distplane(vertex->point, facet, &dist);
- dist= fabs_(dist);
- zinc_(Znewvertex);
- wadd_(Wnewvertex, dist);
- if (dist > wwval_(Wnewvertexmax)) {
- wwval_(Wnewvertexmax)= dist;
- if (dist > qh max_outside) {
- qh max_outside= dist; /* used by qh_maxouter() */
- if (dist > qh TRACEdist)
- istrace= True;
- }
- }else if (-dist > qh TRACEdist)
- istrace= True;
- if (istrace) {
- qh_fprintf(qh ferr, 8016, "qh_setfacetplane: ====== vertex p%d(v%d) increases max_outside to %2.2g for new facet f%d last p%d\n",
- qh_pointid(vertex->point), vertex->id, dist, facet->id, qh furthest_id);
- qh_errprint("DISTANT", facet, NULL, NULL, NULL);
- }
- }
- }
- qh RANDOMdist= qh old_randomdist;
- }
- if (qh IStracing >= 3) {
- qh_fprintf(qh ferr, 8017, "qh_setfacetplane: f%d offset %2.2g normal: ",
- facet->id, facet->offset);
- for (k=0; k < qh hull_dim; k++)
- qh_fprintf(qh ferr, 8018, "%2.2g ", facet->normal[k]);
- qh_fprintf(qh ferr, 8019, "\n");
- }
- if (facet == qh tracefacet)
- qh IStracing= oldtrace;
-} /* setfacetplane */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethyperplane_det">-</a>
-
- qh_sethyperplane_det( dim, rows, point0, toporient, normal, offset, nearzero )
- given dim X dim array indexed by rows[], one row per point,
- toporient(flips all signs),
- and point0 (any row)
- set normalized hyperplane equation from oriented simplex
-
- returns:
- normal (normalized)
- offset (places point0 on the hyperplane)
- sets nearzero if hyperplane not through points
-
- notes:
- only defined for dim == 2..4
- rows[] is not modified
- solves det(P-V_0, V_n-V_0, ..., V_1-V_0)=0, i.e. every point is on hyperplane
- see Bower & Woodworth, A programmer's geometry, Butterworths 1983.
-
- derivation of 3-d minnorm
- Goal: all vertices V_i within qh.one_merge of hyperplane
- Plan: exactly translate the facet so that V_0 is the origin
- exactly rotate the facet so that V_1 is on the x-axis and y_2=0.
- exactly rotate the effective perturbation to only effect n_0
- this introduces a factor of sqrt(3)
- n_0 = ((y_2-y_0)*(z_1-z_0) - (z_2-z_0)*(y_1-y_0)) / norm
- Let M_d be the max coordinate difference
- Let M_a be the greater of M_d and the max abs. coordinate
- Let u be machine roundoff and distround be max error for distance computation
- The max error for n_0 is sqrt(3) u M_a M_d / norm. n_1 is approx. 1 and n_2 is approx. 0
- The max error for distance of V_1 is sqrt(3) u M_a M_d M_d / norm. Offset=0 at origin
- Then minnorm = 1.8 u M_a M_d M_d / qh.ONEmerge
- Note that qh.one_merge is approx. 45.5 u M_a and norm is usually about M_d M_d
-
- derivation of 4-d minnorm
- same as above except rotate the facet so that V_1 on x-axis and w_2, y_3, w_3=0
- [if two vertices fixed on x-axis, can rotate the other two in yzw.]
- n_0 = det3_(...) = y_2 det2_(z_1, w_1, z_3, w_3) = - y_2 w_1 z_3
- [all other terms contain at least two factors nearly zero.]
- The max error for n_0 is sqrt(4) u M_a M_d M_d / norm
- Then minnorm = 2 u M_a M_d M_d M_d / qh.ONEmerge
- Note that qh.one_merge is approx. 82 u M_a and norm is usually about M_d M_d M_d
-*/
-void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
- boolT toporient, coordT *normal, realT *offset, boolT *nearzero) {
- realT maxround, dist;
- int i;
- pointT *point;
-
-
- if (dim == 2) {
- normal[0]= dY(1,0);
- normal[1]= dX(0,1);
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0]+point0[1]*normal[1]);
- *nearzero= False; /* since nearzero norm => incident points */
- }else if (dim == 3) {
- normal[0]= det2_(dY(2,0), dZ(2,0),
- dY(1,0), dZ(1,0));
- normal[1]= det2_(dX(1,0), dZ(1,0),
- dX(2,0), dZ(2,0));
- normal[2]= det2_(dX(2,0), dY(2,0),
- dX(1,0), dY(1,0));
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
- + point0[2]*normal[2]);
- maxround= qh DISTround;
- for (i=dim; i--; ) {
- point= rows[i];
- if (point != point0) {
- dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
- + point[2]*normal[2]);
- if (dist > maxround || dist < -maxround) {
- *nearzero= True;
- break;
- }
- }
- }
- }else if (dim == 4) {
- normal[0]= - det3_(dY(2,0), dZ(2,0), dW(2,0),
- dY(1,0), dZ(1,0), dW(1,0),
- dY(3,0), dZ(3,0), dW(3,0));
- normal[1]= det3_(dX(2,0), dZ(2,0), dW(2,0),
- dX(1,0), dZ(1,0), dW(1,0),
- dX(3,0), dZ(3,0), dW(3,0));
- normal[2]= - det3_(dX(2,0), dY(2,0), dW(2,0),
- dX(1,0), dY(1,0), dW(1,0),
- dX(3,0), dY(3,0), dW(3,0));
- normal[3]= det3_(dX(2,0), dY(2,0), dZ(2,0),
- dX(1,0), dY(1,0), dZ(1,0),
- dX(3,0), dY(3,0), dZ(3,0));
- qh_normalize2 (normal, dim, toporient, NULL, NULL);
- *offset= -(point0[0]*normal[0] + point0[1]*normal[1]
- + point0[2]*normal[2] + point0[3]*normal[3]);
- maxround= qh DISTround;
- for (i=dim; i--; ) {
- point= rows[i];
- if (point != point0) {
- dist= *offset + (point[0]*normal[0] + point[1]*normal[1]
- + point[2]*normal[2] + point[3]*normal[3]);
- if (dist > maxround || dist < -maxround) {
- *nearzero= True;
- break;
- }
- }
- }
- }
- if (*nearzero) {
- zzinc_(Zminnorm);
- trace0((qh ferr, 3, "qh_sethyperplane_det: degenerate norm during p%d.\n", qh furthest_id));
- zzinc_(Znearlysingular);
- }
-} /* sethyperplane_det */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethyperplane_gauss">-</a>
-
- qh_sethyperplane_gauss( dim, rows, point0, toporient, normal, offset, nearzero )
- given(dim-1) X dim array of rows[i]= V_{i+1} - V_0 (point0)
- set normalized hyperplane equation from oriented simplex
-
- returns:
- normal (normalized)
- offset (places point0 on the hyperplane)
-
- notes:
- if nearzero
- orientation may be incorrect because of incorrect sign flips in gausselim
- solves [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0 .. 0 1]
- or [V_n-V_0,...,V_1-V_0, 0 .. 0 1] * N == [0]
- i.e., N is normal to the hyperplane, and the unnormalized
- distance to [0 .. 1] is either 1 or 0
-
- design:
- perform gaussian elimination
- flip sign for negative values
- perform back substitution
- normalize result
- compute offset
-*/
-void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
- boolT toporient, coordT *normal, coordT *offset, boolT *nearzero) {
- coordT *pointcoord, *normalcoef;
- int k;
- boolT sign= toporient, nearzero2= False;
-
- qh_gausselim(rows, dim-1, dim, &sign, nearzero);
- for (k=dim-1; k--; ) {
- if ((rows[k])[k] < 0)
- sign ^= 1;
- }
- if (*nearzero) {
- zzinc_(Znearlysingular);
- trace0((qh ferr, 4, "qh_sethyperplane_gauss: nearly singular or axis parallel hyperplane during p%d.\n", qh furthest_id));
- qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
- }else {
- qh_backnormal(rows, dim-1, dim, sign, normal, &nearzero2);
- if (nearzero2) {
- zzinc_(Znearlysingular);
- trace0((qh ferr, 5, "qh_sethyperplane_gauss: singular or axis parallel hyperplane at normalization during p%d.\n", qh furthest_id));
- }
- }
- if (nearzero2)
- *nearzero= True;
- qh_normalize2(normal, dim, True, NULL, NULL);
- pointcoord= point0;
- normalcoef= normal;
- *offset= -(*pointcoord++ * *normalcoef++);
- for (k=dim-1; k--; )
- *offset -= *pointcoord++ * *normalcoef++;
-} /* sethyperplane_gauss */
-
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/geom.h b/PyMca/Object3D/Object3DQhull/src/geom.h
deleted file mode 100644
index c85049b..0000000
--- a/PyMca/Object3D/Object3DQhull/src/geom.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*<html><pre> -<a href="qh-geom.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- geom.h
- header file for geometric routines
-
- see qh-geom.htm and geom.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/geom.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFgeom
-#define qhDEFgeom 1
-
-#include "libqhull.h"
-
-/* ============ -macros- ======================== */
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="fabs_">-</a>
-
- fabs_(a)
- returns the absolute value of a
-*/
-#define fabs_( a ) ((( a ) < 0 ) ? -( a ):( a ))
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="fmax_">-</a>
-
- fmax_(a,b)
- returns the maximum value of a and b
-*/
-#define fmax_( a,b ) ( ( a ) < ( b ) ? ( b ) : ( a ) )
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="fmin_">-</a>
-
- fmin_(a,b)
- returns the minimum value of a and b
-*/
-#define fmin_( a,b ) ( ( a ) > ( b ) ? ( b ) : ( a ) )
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="maximize_">-</a>
-
- maximize_(maxval, val)
- set maxval to val if val is greater than maxval
-*/
-#define maximize_( maxval, val ) { if (( maxval ) < ( val )) ( maxval )= ( val ); }
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="minimize_">-</a>
-
- minimize_(minval, val)
- set minval to val if val is less than minval
-*/
-#define minimize_( minval, val ) { if (( minval ) > ( val )) ( minval )= ( val ); }
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="det2_">-</a>
-
- det2_(a1, a2,
- b1, b2)
-
- compute a 2-d determinate
-*/
-#define det2_( a1,a2,b1,b2 ) (( a1 )*( b2 ) - ( a2 )*( b1 ))
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="det3_">-</a>
-
- det3_(a1, a2, a3,
- b1, b2, b3,
- c1, c2, c3)
-
- compute a 3-d determinate
-*/
-#define det3_( a1,a2,a3,b1,b2,b3,c1,c2,c3 ) ( ( a1 )*det2_( b2,b3,c2,c3 ) \
- - ( b1 )*det2_( a2,a3,c2,c3 ) + ( c1 )*det2_( a2,a3,b2,b3 ) )
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="dX">-</a>
-
- dX( p1, p2 )
- dY( p1, p2 )
- dZ( p1, p2 )
-
- given two indices into rows[],
-
- compute the difference between X, Y, or Z coordinates
-*/
-#define dX( p1,p2 ) ( *( rows[p1] ) - *( rows[p2] ))
-#define dY( p1,p2 ) ( *( rows[p1]+1 ) - *( rows[p2]+1 ))
-#define dZ( p1,p2 ) ( *( rows[p1]+2 ) - *( rows[p2]+2 ))
-#define dW( p1,p2 ) ( *( rows[p1]+3 ) - *( rows[p2]+3 ))
-
-/*============= prototypes in alphabetical order, infrequent at end ======= */
-
-void qh_backnormal(realT **rows, int numrow, int numcol, boolT sign, coordT *normal, boolT *nearzero);
-void qh_distplane(pointT *point, facetT *facet, realT *dist);
-facetT *qh_findbest(pointT *point, facetT *startfacet,
- boolT bestoutside, boolT isnewfacets, boolT noupper,
- realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbesthorizon(boolT ischeckmax, pointT *point,
- facetT *startfacet, boolT noupper, realT *bestdist, int *numpart);
-facetT *qh_findbestnew(pointT *point, facetT *startfacet, realT *dist,
- boolT bestoutside, boolT *isoutside, int *numpart);
-void qh_gausselim(realT **rows, int numrow, int numcol, boolT *sign, boolT *nearzero);
-realT qh_getangle(pointT *vect1, pointT *vect2);
-pointT *qh_getcenter(setT *vertices);
-pointT *qh_getcentrum(facetT *facet);
-realT qh_getdistance(facetT *facet, facetT *neighbor, realT *mindist, realT *maxdist);
-void qh_normalize(coordT *normal, int dim, boolT toporient);
-void qh_normalize2 (coordT *normal, int dim, boolT toporient,
- realT *minnorm, boolT *ismin);
-pointT *qh_projectpoint(pointT *point, facetT *facet, realT dist);
-
-void qh_setfacetplane(facetT *newfacets);
-void qh_sethyperplane_det(int dim, coordT **rows, coordT *point0,
- boolT toporient, coordT *normal, realT *offset, boolT *nearzero);
-void qh_sethyperplane_gauss(int dim, coordT **rows, pointT *point0,
- boolT toporient, coordT *normal, coordT *offset, boolT *nearzero);
-boolT qh_sharpnewfacets(void);
-
-/*========= infrequently used code in geom2.c =============*/
-
-coordT *qh_copypoints(coordT *points, int numpoints, int dimension);
-void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]);
-realT qh_determinant(realT **rows, int dim, boolT *nearzero);
-realT qh_detjoggle(pointT *points, int numpoints, int dimension);
-void qh_detroundoff(void);
-realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero);
-realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp);
-realT qh_distround(int dimension, realT maxabs, realT maxsumabs);
-realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv);
-realT qh_facetarea(facetT *facet);
-realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
- vertexT *notvertex, boolT toporient, coordT *normal, realT *offset);
-pointT *qh_facetcenter(setT *vertices);
-facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp, facetT **facetlist);
-void qh_getarea(facetT *facetlist);
-boolT qh_gram_schmidt(int dim, realT **rows);
-boolT qh_inthresholds(coordT *normal, realT *angle);
-void qh_joggleinput(void);
-realT *qh_maxabsval(realT *normal, int dim);
-setT *qh_maxmin(pointT *points, int numpoints, int dimension);
-realT qh_maxouter(void);
-void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex);
-realT qh_minabsval(realT *normal, int dim);
-int qh_mindiff(realT *vecA, realT *vecB, int dim);
-boolT qh_orientoutside(facetT *facet);
-void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
-coordT qh_pointdist(pointT *point1, pointT *point2, int dim);
-void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol);
-void qh_printpoints(FILE *fp, const char *string, setT *points);
-void qh_projectinput(void);
-void qh_projectpoints(signed char *project, int n, realT *points,
- int numpoints, int dim, realT *newpoints, int newdim);
-void qh_rotateinput(realT **rows);
-void qh_rotatepoints(realT *points, int numpoints, int dim, realT **rows);
-void qh_scaleinput(void);
-void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
- coordT high, coordT newhigh);
-void qh_scalepoints(pointT *points, int numpoints, int dim,
- realT *newlows, realT *newhighs);
-boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
- coordT *normal, coordT *offset, coordT *feasible);
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
-pointT *qh_voronoi_center(int dim, setT *points);
-
-#endif /* qhDEFgeom */
-
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/geom2.c b/PyMca/Object3D/Object3DQhull/src/geom2.c
deleted file mode 100644
index a78a1cb..0000000
--- a/PyMca/Object3D/Object3DQhull/src/geom2.c
+++ /dev/null
@@ -1,2081 +0,0 @@
-/*<html><pre> -<a href="qh-geom.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
-
- geom2.c
- infrequently used geometric routines of qhull
-
- see qh-geom.htm and geom.h
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/geom2.c#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
- frequently used code goes into geom.c
-*/
-
-#include "qhull_a.h"
-
-/*================== functions in alphabetic order ============*/
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="copypoints">-</a>
-
- qh_copypoints( points, numpoints, dimension)
- return qh_malloc'd copy of points
-*/
-coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
- int size;
- coordT *newpoints;
-
- size= numpoints * dimension * (int)sizeof(coordT);
- if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
- qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
- numpoints);
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- memcpy((char *)newpoints, (char *)points, (size_t)size);
- return newpoints;
-} /* copypoints */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="crossproduct">-</a>
-
- qh_crossproduct( dim, vecA, vecB, vecC )
- crossproduct of 2 dim vectors
- C= A x B
-
- notes:
- from Glasner, Graphics Gems I, p. 639
- only defined for dim==3
-*/
-void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
-
- if (dim == 3) {
- vecC[0]= det2_(vecA[1], vecA[2],
- vecB[1], vecB[2]);
- vecC[1]= - det2_(vecA[0], vecA[2],
- vecB[0], vecB[2]);
- vecC[2]= det2_(vecA[0], vecA[1],
- vecB[0], vecB[1]);
- }
-} /* vcross */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="determinant">-</a>
-
- qh_determinant( rows, dim, nearzero )
- compute signed determinant of a square matrix
- uses qh.NEARzero to test for degenerate matrices
-
- returns:
- determinant
- overwrites rows and the matrix
- if dim == 2 or 3
- nearzero iff determinant < qh NEARzero[dim-1]
- (!quite correct, not critical)
- if dim >= 4
- nearzero iff diagonal[k] < qh NEARzero[k]
-*/
-realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
- realT det=0;
- int i;
- boolT sign= False;
-
- *nearzero= False;
- if (dim < 2) {
- qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }else if (dim == 2) {
- det= det2_(rows[0][0], rows[0][1],
- rows[1][0], rows[1][1]);
- if (fabs_(det) < qh NEARzero[1]) /* not really correct, what should this be? */
- *nearzero= True;
- }else if (dim == 3) {
- det= det3_(rows[0][0], rows[0][1], rows[0][2],
- rows[1][0], rows[1][1], rows[1][2],
- rows[2][0], rows[2][1], rows[2][2]);
- if (fabs_(det) < qh NEARzero[2]) /* not really correct, what should this be? */
- *nearzero= True;
- }else {
- qh_gausselim(rows, dim, dim, &sign, nearzero); /* if nearzero, diagonal still ok*/
- det= 1.0;
- for (i=dim; i--; )
- det *= (rows[i])[i];
- if (sign)
- det= -det;
- }
- return det;
-} /* determinant */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="detjoggle">-</a>
-
- qh_detjoggle( points, numpoints, dimension )
- determine default max joggle for point array
- as qh_distround * qh_JOGGLEdefault
-
- returns:
- initial value for JOGGLEmax from points and REALepsilon
-
- notes:
- computes DISTround since qh_maxmin not called yet
- if qh SCALElast, last dimension will be scaled later to MAXwidth
-
- loop duplicated from qh_maxmin
-*/
-realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
- realT abscoord, distround, joggle, maxcoord, mincoord;
- pointT *point, *pointtemp;
- realT maxabs= -REALmax;
- realT sumabs= 0;
- realT maxwidth= 0;
- int k;
-
- for (k=0; k < dimension; k++) {
- if (qh SCALElast && k == dimension-1)
- abscoord= maxwidth;
- else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
- abscoord= 2 * maxabs * maxabs; /* may be low by qh hull_dim/2 */
- else {
- maxcoord= -REALmax;
- mincoord= REALmax;
- FORALLpoint_(points, numpoints) {
- maximize_(maxcoord, point[k]);
- minimize_(mincoord, point[k]);
- }
- maximize_(maxwidth, maxcoord-mincoord);
- abscoord= fmax_(maxcoord, -mincoord);
- }
- sumabs += abscoord;
- maximize_(maxabs, abscoord);
- } /* for k */
- distround= qh_distround(qh hull_dim, maxabs, sumabs);
- joggle= distround * qh_JOGGLEdefault;
- maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
- trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
- return joggle;
-} /* detjoggle */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="detroundoff">-</a>
-
- qh_detroundoff()
- determine maximum roundoff errors from
- REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
- qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
-
- accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
- qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
- qh.postmerge_centrum, qh.MINoutside,
- qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
-
- returns:
- sets qh.DISTround, etc. (see below)
- appends precision constants to qh.qhull_options
-
- see:
- qh_maxmin() for qh.NEARzero
-
- design:
- determine qh.DISTround for distance computations
- determine minimum denominators for qh_divzero
- determine qh.ANGLEround for angle computations
- adjust qh.premerge_cos,... for roundoff error
- determine qh.ONEmerge for maximum error due to a single merge
- determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
- qh.MINoutside, qh.WIDEfacet
- initialize qh.max_vertex and qh.minvertex
-*/
-void qh_detroundoff(void) {
-
- qh_option("_max-width", NULL, &qh MAXwidth);
- if (!qh SETroundoff) {
- qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
- if (qh RANDOMdist)
- qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
- qh_option("Error-roundoff", NULL, &qh DISTround);
- }
- qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
- qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ; /* if will be normalized */
- qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
- /* for inner product */
- qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
- if (qh RANDOMdist)
- qh ANGLEround += qh RANDOMfactor;
- if (qh premerge_cos < REALmax/2) {
- qh premerge_cos -= qh ANGLEround;
- if (qh RANDOMdist)
- qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
- }
- if (qh postmerge_cos < REALmax/2) {
- qh postmerge_cos -= qh ANGLEround;
- if (qh RANDOMdist)
- qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
- }
- qh premerge_centrum += 2 * qh DISTround; /*2 for centrum and distplane()*/
- qh postmerge_centrum += 2 * qh DISTround;
- if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
- qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
- if (qh RANDOMdist && qh POSTmerge)
- qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
- { /* compute ONEmerge, max vertex offset for merging simplicial facets */
- realT maxangle= 1.0, maxrho;
-
- minimize_(maxangle, qh premerge_cos);
- minimize_(maxangle, qh postmerge_cos);
- /* max diameter * sin theta + DISTround for vertex to its hyperplane */
- qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
- sqrt(1.0 - maxangle * maxangle) + qh DISTround;
- maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
- maximize_(qh ONEmerge, maxrho);
- maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
- maximize_(qh ONEmerge, maxrho);
- if (qh MERGING)
- qh_option("_one-merge", NULL, &qh ONEmerge);
- }
- qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
- if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
- realT maxdist; /* adjust qh.NEARinside for joggle */
- qh KEEPnearinside= True;
- maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
- maxdist= 2*maxdist; /* vertex and coplanar point can joggle in opposite directions */
- maximize_(qh NEARinside, maxdist); /* must agree with qh_nearcoplanar() */
- }
- if (qh KEEPnearinside)
- qh_option("_near-inside", NULL, &qh NEARinside);
- if (qh JOGGLEmax < qh DISTround) {
- qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
- qh JOGGLEmax, qh DISTround);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh MINvisible > REALmax/2) {
- if (!qh MERGING)
- qh MINvisible= qh DISTround;
- else if (qh hull_dim <= 3)
- qh MINvisible= qh premerge_centrum;
- else
- qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
- if (qh APPROXhull && qh MINvisible > qh MINoutside)
- qh MINvisible= qh MINoutside;
- qh_option("Visible-distance", NULL, &qh MINvisible);
- }
- if (qh MAXcoplanar > REALmax/2) {
- qh MAXcoplanar= qh MINvisible;
- qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
- }
- if (!qh APPROXhull) { /* user may specify qh MINoutside */
- qh MINoutside= 2 * qh MINvisible;
- if (qh premerge_cos < REALmax/2)
- maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
- qh_option("Width-outside", NULL, &qh MINoutside);
- }
- qh WIDEfacet= qh MINoutside;
- maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
- maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
- qh_option("_wide-facet", NULL, &qh WIDEfacet);
- if (qh MINvisible > qh MINoutside + 3 * REALepsilon
- && !qh BESToutside && !qh FORCEoutput)
- qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g. Flipped facets are likely.\n",
- qh MINvisible, qh MINoutside);
- qh max_vertex= qh DISTround;
- qh min_vertex= -qh DISTround;
- /* numeric constants reported in printsummary */
-} /* detroundoff */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="detsimplex">-</a>
-
- qh_detsimplex( apex, points, dim, nearzero )
- compute determinant of a simplex with point apex and base points
-
- returns:
- signed determinant and nearzero from qh_determinant
-
- notes:
- uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
-
- design:
- construct qm_matrix by subtracting apex from points
- compute determinate
-*/
-realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
- pointT *coorda, *coordp, *gmcoord, *point, **pointp;
- coordT **rows;
- int k, i=0;
- realT det;
-
- zinc_(Zdetsimplex);
- gmcoord= qh gm_matrix;
- rows= qh gm_row;
- FOREACHpoint_(points) {
- if (i == dim)
- break;
- rows[i++]= gmcoord;
- coordp= point;
- coorda= apex;
- for (k=dim; k--; )
- *(gmcoord++)= *coordp++ - *coorda++;
- }
- if (i < dim) {
- qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
- i, dim);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- det= qh_determinant(rows, dim, nearzero);
- trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
- det, qh_pointid(apex), dim, *nearzero));
- return det;
-} /* detsimplex */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="distnorm">-</a>
-
- qh_distnorm( dim, point, normal, offset )
- return distance from point to hyperplane at normal/offset
-
- returns:
- dist
-
- notes:
- dist > 0 if point is outside of hyperplane
-
- see:
- qh_distplane in geom.c
-*/
-realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
- coordT *normalp= normal, *coordp= point;
- realT dist;
- int k;
-
- dist= *offsetp;
- for (k=dim; k--; )
- dist += *(coordp++) * *(normalp++);
- return dist;
-} /* distnorm */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="distround">-</a>
-
- qh_distround(dimension, maxabs, maxsumabs )
- compute maximum round-off error for a distance computation
- to a normalized hyperplane
- maxabs is the maximum absolute value of a coordinate
- maxsumabs is the maximum possible sum of absolute coordinate values
-
- returns:
- max dist round for REALepsilon
-
- notes:
- calculate roundoff error according to
- Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
- use sqrt(dim) since one vector is normalized
- or use maxsumabs since one vector is < 1
-*/
-realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
- realT maxdistsum, maxround;
-
- maxdistsum= sqrt((realT)dimension) * maxabs;
- minimize_( maxdistsum, maxsumabs);
- maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
- /* adds maxabs for offset */
- trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
- maxround, maxabs, maxsumabs, maxdistsum));
- return maxround;
-} /* distround */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="divzero">-</a>
-
- qh_divzero( numer, denom, mindenom1, zerodiv )
- divide by a number that's nearly zero
- mindenom1= minimum denominator for dividing into 1.0
-
- returns:
- quotient
- sets zerodiv and returns 0.0 if it would overflow
-
- design:
- if numer is nearly zero and abs(numer) < abs(denom)
- return numer/denom
- else if numer is nearly zero
- return 0 and zerodiv
- else if denom/numer non-zero
- return numer/denom
- else
- return 0 and zerodiv
-*/
-realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
- realT temp, numerx, denomx;
-
-
- if (numer < mindenom1 && numer > -mindenom1) {
- numerx= fabs_(numer);
- denomx= fabs_(denom);
- if (numerx < denomx) {
- *zerodiv= False;
- return numer/denom;
- }else {
- *zerodiv= True;
- return 0.0;
- }
- }
- temp= denom/numer;
- if (temp > mindenom1 || temp < -mindenom1) {
- *zerodiv= False;
- return numer/denom;
- }else {
- *zerodiv= True;
- return 0.0;
- }
-} /* divzero */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="facetarea">-</a>
-
- qh_facetarea( facet )
- return area for a facet
-
- notes:
- if non-simplicial,
- uses centrum to triangulate facet and sums the projected areas.
- if (qh DELAUNAY),
- computes projected area instead for last coordinate
- assumes facet->normal exists
- projecting tricoplanar facets to the hyperplane does not appear to make a difference
-
- design:
- if simplicial
- compute area
- else
- for each ridge
- compute area from centrum to ridge
- negate area if upper Delaunay facet
-*/
-realT qh_facetarea(facetT *facet) {
- vertexT *apex;
- pointT *centrum;
- realT area= 0.0;
- ridgeT *ridge, **ridgep;
-
- if (facet->simplicial) {
- apex= SETfirstt_(facet->vertices, vertexT);
- area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
- apex, facet->toporient, facet->normal, &facet->offset);
- }else {
- if (qh CENTERtype == qh_AScentrum)
- centrum= facet->center;
- else
- centrum= qh_getcentrum(facet);
- FOREACHridge_(facet->ridges)
- area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
- NULL, (boolT)(ridge->top == facet), facet->normal, &facet->offset);
- if (qh CENTERtype != qh_AScentrum)
- qh_memfree(centrum, qh normal_size);
- }
- if (facet->upperdelaunay && qh DELAUNAY)
- area= -area; /* the normal should be [0,...,1] */
- trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
- return area;
-} /* facetarea */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="facetarea_simplex">-</a>
-
- qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
- return area for a simplex defined by
- an apex, a base of vertices, an orientation, and a unit normal
- if simplicial or tricoplanar facet,
- notvertex is defined and it is skipped in vertices
-
- returns:
- computes area of simplex projected to plane [normal,offset]
- returns 0 if vertex too far below plane (qh WIDEfacet)
- vertex can't be apex of tricoplanar facet
-
- notes:
- if (qh DELAUNAY),
- computes projected area instead for last coordinate
- uses qh gm_matrix/gm_row and qh hull_dim
- helper function for qh_facetarea
-
- design:
- if Notvertex
- translate simplex to apex
- else
- project simplex to normal/offset
- translate simplex to apex
- if Delaunay
- set last row/column to 0 with -1 on diagonal
- else
- set last row to Normal
- compute determinate
- scale and flip sign for area
-*/
-realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
- vertexT *notvertex, boolT toporient, coordT *normal, realT *offset) {
- pointT *coorda, *coordp, *gmcoord;
- coordT **rows, *normalp;
- int k, i=0;
- realT area, dist;
- vertexT *vertex, **vertexp;
- boolT nearzero;
-
- gmcoord= qh gm_matrix;
- rows= qh gm_row;
- FOREACHvertex_(vertices) {
- if (vertex == notvertex)
- continue;
- rows[i++]= gmcoord;
- coorda= apex;
- coordp= vertex->point;
- normalp= normal;
- if (notvertex) {
- for (k=dim; k--; )
- *(gmcoord++)= *coordp++ - *coorda++;
- }else {
- dist= *offset;
- for (k=dim; k--; )
- dist += *coordp++ * *normalp++;
- if (dist < -qh WIDEfacet) {
- zinc_(Znoarea);
- return 0.0;
- }
- coordp= vertex->point;
- normalp= normal;
- for (k=dim; k--; )
- *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
- }
- }
- if (i != dim-1) {
- qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
- i, dim);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- rows[i]= gmcoord;
- if (qh DELAUNAY) {
- for (i=0; i < dim-1; i++)
- rows[i][dim-1]= 0.0;
- for (k=dim; k--; )
- *(gmcoord++)= 0.0;
- rows[dim-1][dim-1]= -1.0;
- }else {
- normalp= normal;
- for (k=dim; k--; )
- *(gmcoord++)= *normalp++;
- }
- zinc_(Zdetsimplex);
- area= qh_determinant(rows, dim, &nearzero);
- if (toporient)
- area= -area;
- area *= qh AREAfactor;
- trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
- area, qh_pointid(apex), toporient, nearzero));
- return area;
-} /* facetarea_simplex */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="facetcenter">-</a>
-
- qh_facetcenter( vertices )
- return Voronoi center (Voronoi vertex) for a facet's vertices
-
- returns:
- return temporary point equal to the center
-
- see:
- qh_voronoi_center()
-*/
-pointT *qh_facetcenter(setT *vertices) {
- setT *points= qh_settemp(qh_setsize(vertices));
- vertexT *vertex, **vertexp;
- pointT *center;
-
- FOREACHvertex_(vertices)
- qh_setappend(&points, vertex->point);
- center= qh_voronoi_center(qh hull_dim-1, points);
- qh_settempfree(&points);
- return center;
-} /* facetcenter */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="findgooddist">-</a>
-
- qh_findgooddist( point, facetA, dist, facetlist )
- find best good facet visible for point from facetA
- assumes facetA is visible from point
-
- returns:
- best facet, i.e., good facet that is furthest from point
- distance to best facet
- NULL if none
-
- moves good, visible facets (and some other visible facets)
- to end of qh facet_list
-
- notes:
- uses qh visit_id
-
- design:
- initialize bestfacet if facetA is good
- move facetA to end of facetlist
- for each facet on facetlist
- for each unvisited neighbor of facet
- move visible neighbors to end of facetlist
- update best good neighbor
- if no good neighbors, update best facet
-*/
-facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
- facetT **facetlist) {
- realT bestdist= -REALmax, dist;
- facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
- boolT goodseen= False;
-
- if (facetA->good) {
- zzinc_(Zcheckpart); /* calls from check_bestdist occur after print stats */
- qh_distplane(point, facetA, &bestdist);
- bestfacet= facetA;
- goodseen= True;
- }
- qh_removefacet(facetA);
- qh_appendfacet(facetA);
- *facetlist= facetA;
- facetA->visitid= ++qh visit_id;
- FORALLfacet_(*facetlist) {
- FOREACHneighbor_(facet) {
- if (neighbor->visitid == qh visit_id)
- continue;
- neighbor->visitid= qh visit_id;
- if (goodseen && !neighbor->good)
- continue;
- zzinc_(Zcheckpart);
- qh_distplane(point, neighbor, &dist);
- if (dist > 0) {
- qh_removefacet(neighbor);
- qh_appendfacet(neighbor);
- if (neighbor->good) {
- goodseen= True;
- if (dist > bestdist) {
- bestdist= dist;
- bestfacet= neighbor;
- }
- }
- }
- }
- }
- if (bestfacet) {
- *distp= bestdist;
- trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
- qh_pointid(point), bestdist, bestfacet->id));
- return bestfacet;
- }
- trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
- qh_pointid(point), facetA->id));
- return NULL;
-} /* findgooddist */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="getarea">-</a>
-
- qh_getarea( facetlist )
- set area of all facets in facetlist
- collect statistics
- nop if hasAreaVolume
-
- returns:
- sets qh totarea/totvol to total area and volume of convex hull
- for Delaunay triangulation, computes projected area of the lower or upper hull
- ignores upper hull if qh ATinfinity
-
- notes:
- could compute outer volume by expanding facet area by rays from interior
- the following attempt at perpendicular projection underestimated badly:
- qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
- * area/ qh hull_dim;
- design:
- for each facet on facetlist
- compute facet->area
- update qh.totarea and qh.totvol
-*/
-void qh_getarea(facetT *facetlist) {
- realT area;
- realT dist;
- facetT *facet;
-
- if (qh hasAreaVolume)
- return;
- if (qh REPORTfreq)
- qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
- else
- trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
- qh totarea= qh totvol= 0.0;
- FORALLfacet_(facetlist) {
- if (!facet->normal)
- continue;
- if (facet->upperdelaunay && qh ATinfinity)
- continue;
- if (!facet->isarea) {
- facet->f.area= qh_facetarea(facet);
- facet->isarea= True;
- }
- area= facet->f.area;
- if (qh DELAUNAY) {
- if (facet->upperdelaunay == qh UPPERdelaunay)
- qh totarea += area;
- }else {
- qh totarea += area;
- qh_distplane(qh interior_point, facet, &dist);
- qh totvol += -dist * area/ qh hull_dim;
- }
- if (qh PRINTstatistics) {
- wadd_(Wareatot, area);
- wmax_(Wareamax, area);
- wmin_(Wareamin, area);
- }
- }
- qh hasAreaVolume= True;
-} /* getarea */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="gram_schmidt">-</a>
-
- qh_gram_schmidt( dim, row )
- implements Gram-Schmidt orthogonalization by rows
-
- returns:
- false if zero norm
- overwrites rows[dim][dim]
-
- notes:
- see Golub & van Loan Algorithm 6.2-2
- overflow due to small divisors not handled
-
- design:
- for each row
- compute norm for row
- if non-zero, normalize row
- for each remaining rowA
- compute inner product of row and rowA
- reduce rowA by row * inner product
-*/
-boolT qh_gram_schmidt(int dim, realT **row) {
- realT *rowi, *rowj, norm;
- int i, j, k;
-
- for (i=0; i < dim; i++) {
- rowi= row[i];
- for (norm= 0.0, k= dim; k--; rowi++)
- norm += *rowi * *rowi;
- norm= sqrt(norm);
- wmin_(Wmindenom, norm);
- if (norm == 0.0) /* either 0 or overflow due to sqrt */
- return False;
- for (k=dim; k--; )
- *(--rowi) /= norm;
- for (j=i+1; j < dim; j++) {
- rowj= row[j];
- for (norm= 0.0, k=dim; k--; )
- norm += *rowi++ * *rowj++;
- for (k=dim; k--; )
- *(--rowj) -= *(--rowi) * norm;
- }
- }
- return True;
-} /* gram_schmidt */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="inthresholds">-</a>
-
- qh_inthresholds( normal, angle )
- return True if normal within qh.lower_/upper_threshold
-
- returns:
- estimate of angle by summing of threshold diffs
- angle may be NULL
- smaller "angle" is better
-
- notes:
- invalid if qh.SPLITthresholds
-
- see:
- qh.lower_threshold in qh_initbuild()
- qh_initthresholds()
-
- design:
- for each dimension
- test threshold
-*/
-boolT qh_inthresholds(coordT *normal, realT *angle) {
- boolT within= True;
- int k;
- realT threshold;
-
- if (angle)
- *angle= 0.0;
- for (k=0; k < qh hull_dim; k++) {
- threshold= qh lower_threshold[k];
- if (threshold > -REALmax/2) {
- if (normal[k] < threshold)
- within= False;
- if (angle) {
- threshold -= normal[k];
- *angle += fabs_(threshold);
- }
- }
- if (qh upper_threshold[k] < REALmax/2) {
- threshold= qh upper_threshold[k];
- if (normal[k] > threshold)
- within= False;
- if (angle) {
- threshold -= normal[k];
- *angle += fabs_(threshold);
- }
- }
- }
- return within;
-} /* inthresholds */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="joggleinput">-</a>
-
- qh_joggleinput()
- randomly joggle input to Qhull by qh.JOGGLEmax
- initial input is qh.first_point/qh.num_points of qh.hull_dim
- repeated calls use qh.input_points/qh.num_points
-
- returns:
- joggles points at qh.first_point/qh.num_points
- copies data to qh.input_points/qh.input_malloc if first time
- determines qh.JOGGLEmax if it was zero
- if qh.DELAUNAY
- computes the Delaunay projection of the joggled points
-
- notes:
- if qh.DELAUNAY, unnecessarily joggles the last coordinate
- the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
-
- design:
- if qh.DELAUNAY
- set qh.SCALElast for reduced precision errors
- if first call
- initialize qh.input_points to the original input points
- if qh.JOGGLEmax == 0
- determine default qh.JOGGLEmax
- else
- increase qh.JOGGLEmax according to qh.build_cnt
- joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
- if qh.DELAUNAY
- sets the Delaunay projection
-*/
-void qh_joggleinput(void) {
- int i, seed, size;
- coordT *coordp, *inputp;
- realT randr, randa, randb;
-
- if (!qh input_points) { /* first call */
- qh input_points= qh first_point;
- qh input_malloc= qh POINTSmalloc;
- size= qh num_points * qh hull_dim * sizeof(coordT);
- if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
- qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
- qh num_points);
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- qh POINTSmalloc= True;
- if (qh JOGGLEmax == 0.0) {
- qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
- qh_option("QJoggle", NULL, &qh JOGGLEmax);
- }
- }else { /* repeated call */
- if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
- if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
- realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
- if (qh JOGGLEmax < maxjoggle) {
- qh JOGGLEmax *= qh_JOGGLEincrease;
- minimize_(qh JOGGLEmax, maxjoggle);
- }
- }
- }
- qh_option("QJoggle", NULL, &qh JOGGLEmax);
- }
- if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
- qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input. If possible, recompile Qhull with higher-precision reals.\n",
- qh JOGGLEmax);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
- seed= qh_RANDOMint;
- qh_option("_joggle-seed", &seed, NULL);
- trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
- qh JOGGLEmax, seed));
- inputp= qh input_points;
- coordp= qh first_point;
- randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
- randb= -qh JOGGLEmax;
- size= qh num_points * qh hull_dim;
- for (i=size; i--; ) {
- randr= qh_RANDOMint;
- *(coordp++)= *(inputp++) + (randr * randa + randb);
- }
- if (qh DELAUNAY) {
- qh last_low= qh last_high= qh last_newhigh= REALmax;
- qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
- }
-} /* joggleinput */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="maxabsval">-</a>
-
- qh_maxabsval( normal, dim )
- return pointer to maximum absolute value of a dim vector
- returns NULL if dim=0
-*/
-realT *qh_maxabsval(realT *normal, int dim) {
- realT maxval= -REALmax;
- realT *maxp= NULL, *colp, absval;
- int k;
-
- for (k=dim, colp= normal; k--; colp++) {
- absval= fabs_(*colp);
- if (absval > maxval) {
- maxval= absval;
- maxp= colp;
- }
- }
- return maxp;
-} /* maxabsval */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="maxmin">-</a>
-
- qh_maxmin( points, numpoints, dimension )
- return max/min points for each dimension
- determine max and min coordinates
-
- returns:
- returns a temporary set of max and min points
- may include duplicate points. Does not include qh.GOODpoint
- sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
- qh.MAXlastcoord, qh.MINlastcoord
- initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
-
- notes:
- loop duplicated in qh_detjoggle()
-
- design:
- initialize global precision variables
- checks definition of REAL...
- for each dimension
- for each point
- collect maximum and minimum point
- collect maximum of maximums and minimum of minimums
- determine qh.NEARzero for Gaussian Elimination
-*/
-setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
- int k;
- realT maxcoord, temp;
- pointT *minimum, *maximum, *point, *pointtemp;
- setT *set;
-
- qh max_outside= 0.0;
- qh MAXabs_coord= 0.0;
- qh MAXwidth= -REALmax;
- qh MAXsumcoord= 0.0;
- qh min_vertex= 0.0;
- qh WAScoplanar= False;
- if (qh ZEROcentrum)
- qh ZEROall_ok= True;
- if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
- && REALmax > 0.0 && -REALmax < 0.0)
- ; /* all ok */
- else {
- qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
-REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
- REALepsilon, REALmin, REALmax, -REALmax);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- set= qh_settemp(2*dimension);
- for (k=0; k < dimension; k++) {
- if (points == qh GOODpointp)
- minimum= maximum= points + dimension;
- else
- minimum= maximum= points;
- FORALLpoint_(points, numpoints) {
- if (point == qh GOODpointp)
- continue;
- if (maximum[k] < point[k])
- maximum= point;
- else if (minimum[k] > point[k])
- minimum= point;
- }
- if (k == dimension-1) {
- qh MINlastcoord= minimum[k];
- qh MAXlastcoord= maximum[k];
- }
- if (qh SCALElast && k == dimension-1)
- maxcoord= qh MAXwidth;
- else {
- maxcoord= fmax_(maximum[k], -minimum[k]);
- if (qh GOODpointp) {
- temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
- maximize_(maxcoord, temp);
- }
- temp= maximum[k] - minimum[k];
- maximize_(qh MAXwidth, temp);
- }
- maximize_(qh MAXabs_coord, maxcoord);
- qh MAXsumcoord += maxcoord;
- qh_setappend(&set, maximum);
- qh_setappend(&set, minimum);
- /* calculation of qh NEARzero is based on error formula 4.4-13 of
- Golub & van Loan, authors say n^3 can be ignored and 10 be used in
- place of rho */
- qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
- }
- if (qh IStracing >=1)
- qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
- return(set);
-} /* maxmin */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="maxouter">-</a>
-
- qh_maxouter()
- return maximum distance from facet to outer plane
- normally this is qh.max_outside+qh.DISTround
- does not include qh.JOGGLEmax
-
- see:
- qh_outerinner()
-
- notes:
- need to add another qh.DISTround if testing actual point with computation
-
- for joggle:
- qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
- need to use Wnewvertexmax since could have a coplanar point for a high
- facet that is replaced by a low facet
- need to add qh.JOGGLEmax if testing input points
-*/
-realT qh_maxouter(void) {
- realT dist;
-
- dist= fmax_(qh max_outside, qh DISTround);
- dist += qh DISTround;
- trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
- return dist;
-} /* maxouter */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="maxsimplex">-</a>
-
- qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
- determines maximum simplex for a set of points
- starts from points already in simplex
- skips qh.GOODpointp (assumes that it isn't in maxpoints)
-
- returns:
- simplex with dim+1 points
-
- notes:
- assumes at least pointsneeded points in points
- maximizes determinate for x,y,z,w, etc.
- uses maxpoints as long as determinate is clearly non-zero
-
- design:
- initialize simplex with at least two points
- (find points with max or min x coordinate)
- for each remaining dimension
- add point that maximizes the determinate
- (use points from maxpoints first)
-*/
-void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
- pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
- boolT nearzero, maxnearzero= False;
- int k, sizinit;
- realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
-
- sizinit= qh_setsize(*simplex);
- if (sizinit < 2) {
- if (qh_setsize(maxpoints) >= 2) {
- FOREACHpoint_(maxpoints) {
- if (maxcoord < point[0]) {
- maxcoord= point[0];
- maxx= point;
- }
- if (mincoord > point[0]) {
- mincoord= point[0];
- minx= point;
- }
- }
- }else {
- FORALLpoint_(points, numpoints) {
- if (point == qh GOODpointp)
- continue;
- if (maxcoord < point[0]) {
- maxcoord= point[0];
- maxx= point;
- }
- if (mincoord > point[0]) {
- mincoord= point[0];
- minx= point;
- }
- }
- }
- qh_setunique(simplex, minx);
- if (qh_setsize(*simplex) < 2)
- qh_setunique(simplex, maxx);
- sizinit= qh_setsize(*simplex);
- if (sizinit < 2) {
- qh_precision("input has same x coordinate");
- if (zzval_(Zsetplane) > qh hull_dim+1) {
- qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
- qh_setsize(maxpoints)+numpoints);
- qh_errexit(qh_ERRprec, NULL, NULL);
- }else {
- qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- }
- }
- for (k=sizinit; k < dim+1; k++) {
- maxpoint= NULL;
- maxdet= -REALmax;
- FOREACHpoint_(maxpoints) {
- if (!qh_setin(*simplex, point)) {
- det= qh_detsimplex(point, *simplex, k, &nearzero);
- if ((det= fabs_(det)) > maxdet) {
- maxdet= det;
- maxpoint= point;
- maxnearzero= nearzero;
- }
- }
- }
- if (!maxpoint || maxnearzero) {
- zinc_(Zsearchpoints);
- if (!maxpoint) {
- trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
- }else {
- trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
- k+1, qh_pointid(maxpoint), maxdet));
- }
- FORALLpoint_(points, numpoints) {
- if (point == qh GOODpointp)
- continue;
- if (!qh_setin(*simplex, point)) {
- det= qh_detsimplex(point, *simplex, k, &nearzero);
- if ((det= fabs_(det)) > maxdet) {
- maxdet= det;
- maxpoint= point;
- maxnearzero= nearzero;
- }
- }
- }
- } /* !maxpoint */
- if (!maxpoint) {
- qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh_setappend(simplex, maxpoint);
- trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
- qh_pointid(maxpoint), k+1, maxdet));
- } /* k */
-} /* maxsimplex */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="minabsval">-</a>
-
- qh_minabsval( normal, dim )
- return minimum absolute value of a dim vector
-*/
-realT qh_minabsval(realT *normal, int dim) {
- realT minval= 0;
- realT maxval= 0;
- realT *colp;
- int k;
-
- for (k=dim, colp=normal; k--; colp++) {
- maximize_(maxval, *colp);
- minimize_(minval, *colp);
- }
- return fmax_(maxval, -minval);
-} /* minabsval */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="mindiff">-</a>
-
- qh_mindif ( vecA, vecB, dim )
- return index of min abs. difference of two vectors
-*/
-int qh_mindiff(realT *vecA, realT *vecB, int dim) {
- realT mindiff= REALmax, diff;
- realT *vecAp= vecA, *vecBp= vecB;
- int k, mink= 0;
-
- for (k=0; k < dim; k++) {
- diff= *vecAp++ - *vecBp++;
- diff= fabs_(diff);
- if (diff < mindiff) {
- mindiff= diff;
- mink= k;
- }
- }
- return mink;
-} /* mindiff */
-
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="orientoutside">-</a>
-
- qh_orientoutside( facet )
- make facet outside oriented via qh.interior_point
-
- returns:
- True if facet reversed orientation.
-*/
-boolT qh_orientoutside(facetT *facet) {
- int k;
- realT dist;
-
- qh_distplane(qh interior_point, facet, &dist);
- if (dist > 0) {
- for (k=qh hull_dim; k--; )
- facet->normal[k]= -facet->normal[k];
- facet->offset= -facet->offset;
- return True;
- }
- return False;
-} /* orientoutside */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="outerinner">-</a>
-
- qh_outerinner( facet, outerplane, innerplane )
- if facet and qh.maxoutdone (i.e., qh_check_maxout)
- returns outer and inner plane for facet
- else
- returns maximum outer and inner plane
- accounts for qh.JOGGLEmax
-
- see:
- qh_maxouter(), qh_check_bestdist(), qh_check_points()
-
- notes:
- outerplaner or innerplane may be NULL
- facet is const
- Does not error (QhullFacet)
-
- includes qh.DISTround for actual points
- adds another qh.DISTround if testing with floating point arithmetic
-*/
-void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
- realT dist, mindist;
- vertexT *vertex, **vertexp;
-
- if (outerplane) {
- if (!qh_MAXoutside || !facet || !qh maxoutdone) {
- *outerplane= qh_maxouter(); /* includes qh.DISTround */
- }else { /* qh_MAXoutside ... */
-#if qh_MAXoutside
- *outerplane= facet->maxoutside + qh DISTround;
-#endif
-
- }
- if (qh JOGGLEmax < REALmax/2)
- *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
- }
- if (innerplane) {
- if (facet) {
- mindist= REALmax;
- FOREACHvertex_(facet->vertices) {
- zinc_(Zdistio);
- qh_distplane(vertex->point, facet, &dist);
- minimize_(mindist, dist);
- }
- *innerplane= mindist - qh DISTround;
- }else
- *innerplane= qh min_vertex - qh DISTround;
- if (qh JOGGLEmax < REALmax/2)
- *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
- }
-} /* outerinner */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="pointdist">-</a>
-
- qh_pointdist( point1, point2, dim )
- return distance between two points
-
- notes:
- returns distance squared if 'dim' is negative
-*/
-coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
- coordT dist, diff;
- int k;
-
- dist= 0.0;
- for (k= (dim > 0 ? dim : -dim); k--; ) {
- diff= *point1++ - *point2++;
- dist += diff * diff;
- }
- if (dim > 0)
- return(sqrt(dist));
- return dist;
-} /* pointdist */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="printmatrix">-</a>
-
- qh_printmatrix( fp, string, rows, numrow, numcol )
- print matrix to fp given by row vectors
- print string as header
-
- notes:
- print a vector by qh_printmatrix(fp, "", &vect, 1, len)
-*/
-void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
- realT *rowp;
- realT r; /*bug fix*/
- int i,k;
-
- qh_fprintf(fp, 9001, "%s\n", string);
- for (i=0; i < numrow; i++) {
- rowp= rows[i];
- for (k=0; k < numcol; k++) {
- r= *rowp++;
- qh_fprintf(fp, 9002, "%6.3g ", r);
- }
- qh_fprintf(fp, 9003, "\n");
- }
-} /* printmatrix */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="printpoints">-</a>
-
- qh_printpoints( fp, string, points )
- print pointids to fp for a set of points
- if string, prints string and 'p' point ids
-*/
-void qh_printpoints(FILE *fp, const char *string, setT *points) {
- pointT *point, **pointp;
-
- if (string) {
- qh_fprintf(fp, 9004, "%s", string);
- FOREACHpoint_(points)
- qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
- qh_fprintf(fp, 9006, "\n");
- }else {
- FOREACHpoint_(points)
- qh_fprintf(fp, 9007, " %d", qh_pointid(point));
- qh_fprintf(fp, 9008, "\n");
- }
-} /* printpoints */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="projectinput">-</a>
-
- qh_projectinput()
- project input points using qh.lower_bound/upper_bound and qh DELAUNAY
- if qh.lower_bound[k]=qh.upper_bound[k]= 0,
- removes dimension k
- if halfspace intersection
- removes dimension k from qh.feasible_point
- input points in qh first_point, num_points, input_dim
-
- returns:
- new point array in qh first_point of qh hull_dim coordinates
- sets qh POINTSmalloc
- if qh DELAUNAY
- projects points to paraboloid
- lowbound/highbound is also projected
- if qh ATinfinity
- adds point "at-infinity"
- if qh POINTSmalloc
- frees old point array
-
- notes:
- checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
-
-
- design:
- sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
- determines newdim and newnum for qh hull_dim and qh num_points
- projects points to newpoints
- projects qh.lower_bound to itself
- projects qh.upper_bound to itself
- if qh DELAUNAY
- if qh ATINFINITY
- projects points to paraboloid
- computes "infinity" point as vertex average and 10% above all points
- else
- uses qh_setdelaunay to project points to paraboloid
-*/
-void qh_projectinput(void) {
- int k,i;
- int newdim= qh input_dim, newnum= qh num_points;
- signed char *project;
- int size= (qh input_dim+1)*sizeof(*project);
- pointT *newpoints, *coord, *infinity;
- realT paraboloid, maxboloid= 0;
-
- project= (signed char*)qh_memalloc(size);
- memset((char*)project, 0, (size_t)size);
- for (k=0; k < qh input_dim; k++) { /* skip Delaunay bound */
- if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
- project[k]= -1;
- newdim--;
- }
- }
- if (qh DELAUNAY) {
- project[k]= 1;
- newdim++;
- if (qh ATinfinity)
- newnum++;
- }
- if (newdim != qh hull_dim) {
- qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (!(newpoints=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
- qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
- qh num_points);
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- qh_projectpoints(project, qh input_dim+1, qh first_point,
- qh num_points, qh input_dim, newpoints, newdim);
- trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
- qh_projectpoints(project, qh input_dim+1, qh lower_bound,
- 1, qh input_dim+1, qh lower_bound, newdim+1);
- qh_projectpoints(project, qh input_dim+1, qh upper_bound,
- 1, qh input_dim+1, qh upper_bound, newdim+1);
- if (qh HALFspace) {
- if (!qh feasible_point) {
- qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh_projectpoints(project, qh input_dim, qh feasible_point,
- 1, qh input_dim, qh feasible_point, newdim);
- }
- qh_memfree(project, (qh input_dim+1)*sizeof(*project));
- if (qh POINTSmalloc)
- qh_free(qh first_point);
- qh first_point= newpoints;
- qh POINTSmalloc= True;
- if (qh DELAUNAY && qh ATinfinity) {
- coord= qh first_point;
- infinity= qh first_point + qh hull_dim * qh num_points;
- for (k=qh hull_dim-1; k--; )
- infinity[k]= 0.0;
- for (i=qh num_points; i--; ) {
- paraboloid= 0.0;
- for (k=0; k < qh hull_dim-1; k++) {
- paraboloid += *coord * *coord;
- infinity[k] += *coord;
- coord++;
- }
- *(coord++)= paraboloid;
- maximize_(maxboloid, paraboloid);
- }
- /* coord == infinity */
- for (k=qh hull_dim-1; k--; )
- *(coord++) /= qh num_points;
- *(coord++)= maxboloid * 1.1;
- qh num_points++;
- trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
- }else if (qh DELAUNAY) /* !qh ATinfinity */
- qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
-} /* projectinput */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="projectpoints">-</a>
-
- qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
- project points/numpoints/dim to newpoints/newdim
- if project[k] == -1
- delete dimension k
- if project[k] == 1
- add dimension k by duplicating previous column
- n is size of project
-
- notes:
- newpoints may be points if only adding dimension at end
-
- design:
- check that 'project' and 'newdim' agree
- for each dimension
- if project == -1
- skip dimension
- else
- determine start of column in newpoints
- determine start of column in points
- if project == +1, duplicate previous column
- copy dimension (column) from points to newpoints
-*/
-void qh_projectpoints(signed char *project, int n, realT *points,
- int numpoints, int dim, realT *newpoints, int newdim) {
- int testdim= dim, oldk=0, newk=0, i,j=0,k;
- realT *newp, *oldp;
-
- for (k=0; k < n; k++)
- testdim += project[k];
- if (testdim != newdim) {
- qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
- newdim, testdim);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- for (j=0; j<n; j++) {
- if (project[j] == -1)
- oldk++;
- else {
- newp= newpoints+newk++;
- if (project[j] == +1) {
- if (oldk >= dim)
- continue;
- oldp= points+oldk;
- }else
- oldp= points+oldk++;
- for (i=numpoints; i--; ) {
- *newp= *oldp;
- newp += newdim;
- oldp += dim;
- }
- }
- if (oldk >= dim)
- break;
- }
- trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
- numpoints, dim, newdim));
-} /* projectpoints */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="rotateinput">-</a>
-
- qh_rotateinput( rows )
- rotate input using row matrix
- input points given by qh first_point, num_points, hull_dim
- assumes rows[dim] is a scratch buffer
- if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
- returns:
- rotated input
- sets qh POINTSmalloc
-
- design:
- see qh_rotatepoints
-*/
-void qh_rotateinput(realT **rows) {
-
- if (!qh POINTSmalloc) {
- qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
- qh POINTSmalloc= True;
- }
- qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
-} /* rotateinput */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="rotatepoints">-</a>
-
- qh_rotatepoints( points, numpoints, dim, row )
- rotate numpoints points by a d-dim row matrix
- assumes rows[dim] is a scratch buffer
-
- returns:
- rotated points in place
-
- design:
- for each point
- for each coordinate
- use row[dim] to compute partial inner product
- for each coordinate
- rotate by partial inner product
-*/
-void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
- realT *point, *rowi, *coord= NULL, sum, *newval;
- int i,j,k;
-
- if (qh IStracing >= 1)
- qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
- for (point= points, j= numpoints; j--; point += dim) {
- newval= row[dim];
- for (i=0; i < dim; i++) {
- rowi= row[i];
- coord= point;
- for (sum= 0.0, k= dim; k--; )
- sum += *rowi++ * *coord++;
- *(newval++)= sum;
- }
- for (k=dim; k--; )
- *(--coord)= *(--newval);
- }
-} /* rotatepoints */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="scaleinput">-</a>
-
- qh_scaleinput()
- scale input points using qh low_bound/high_bound
- input points given by qh first_point, num_points, hull_dim
- if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
- returns:
- scales coordinates of points to low_bound[k], high_bound[k]
- sets qh POINTSmalloc
-
- design:
- see qh_scalepoints
-*/
-void qh_scaleinput(void) {
-
- if (!qh POINTSmalloc) {
- qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
- qh POINTSmalloc= True;
- }
- qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
- qh lower_bound, qh upper_bound);
-} /* scaleinput */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="scalelast">-</a>
-
- qh_scalelast( points, numpoints, dim, low, high, newhigh )
- scale last coordinate to [0,m] for Delaunay triangulations
- input points given by points, numpoints, dim
-
- returns:
- changes scale of last coordinate from [low, high] to [0, newhigh]
- overwrites last coordinate of each point
- saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
-
- notes:
- when called by qh_setdelaunay, low/high may not match actual data
-
- design:
- compute scale and shift factors
- apply to last coordinate of each point
-*/
-void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
- coordT high, coordT newhigh) {
- realT scale, shift;
- coordT *coord;
- int i;
- boolT nearzero= False;
-
- trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
- low, high, newhigh));
- qh last_low= low;
- qh last_high= high;
- qh last_newhigh= newhigh;
- scale= qh_divzero(newhigh, high - low,
- qh MINdenom_1, &nearzero);
- if (nearzero) {
- if (qh DELAUNAY)
- qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate. Input is cocircular\n or cospherical. Use option 'Qz' to add a point at infinity.\n");
- else
- qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate. New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
- newhigh, low, high, high-low);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- shift= - low * newhigh / (high-low);
- coord= points + dim - 1;
- for (i=numpoints; i--; coord += dim)
- *coord= *coord * scale + shift;
-} /* scalelast */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="scalepoints">-</a>
-
- qh_scalepoints( points, numpoints, dim, newlows, newhighs )
- scale points to new lowbound and highbound
- retains old bound when newlow= -REALmax or newhigh= +REALmax
-
- returns:
- scaled points
- overwrites old points
-
- design:
- for each coordinate
- compute current low and high bound
- compute scale and shift factors
- scale all points
- enforce new low and high bound for all points
-*/
-void qh_scalepoints(pointT *points, int numpoints, int dim,
- realT *newlows, realT *newhighs) {
- int i,k;
- realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
- boolT nearzero= False;
-
- for (k=0; k < dim; k++) {
- newhigh= newhighs[k];
- newlow= newlows[k];
- if (newhigh > REALmax/2 && newlow < -REALmax/2)
- continue;
- low= REALmax;
- high= -REALmax;
- for (i=numpoints, coord=points+k; i--; coord += dim) {
- minimize_(low, *coord);
- maximize_(high, *coord);
- }
- if (newhigh > REALmax/2)
- newhigh= high;
- if (newlow < -REALmax/2)
- newlow= low;
- if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
- qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
- k, k, newhigh, newlow);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- scale= qh_divzero(newhigh - newlow, high - low,
- qh MINdenom_1, &nearzero);
- if (nearzero) {
- qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
- k, newlow, newhigh, low, high);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- shift= (newlow * high - low * newhigh)/(high-low);
- coord= points+k;
- for (i=numpoints; i--; coord += dim)
- *coord= *coord * scale + shift;
- coord= points+k;
- if (newlow < newhigh) {
- mincoord= newlow;
- maxcoord= newhigh;
- }else {
- mincoord= newhigh;
- maxcoord= newlow;
- }
- for (i=numpoints; i--; coord += dim) {
- minimize_(*coord, maxcoord); /* because of roundoff error */
- maximize_(*coord, mincoord);
- }
- trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
- k, low, high, newlow, newhigh, numpoints, scale, shift));
- }
-} /* scalepoints */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="setdelaunay">-</a>
-
- qh_setdelaunay( dim, count, points )
- project count points to dim-d paraboloid for Delaunay triangulation
-
- dim is one more than the dimension of the input set
- assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
-
- points is a dim*count realT array. The first dim-1 coordinates
- are the coordinates of the first input point. array[dim] is
- the first coordinate of the second input point. array[2*dim] is
- the first coordinate of the third input point.
-
- if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
- calls qh_scalelast to scale the last coordinate the same as the other points
-
- returns:
- for each point
- sets point[dim-1] to sum of squares of coordinates
- scale points to 'Qbb' if needed
-
- notes:
- to project one point, use
- qh_setdelaunay(qh hull_dim, 1, point)
-
- Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
- the coordinates after the original projection.
-
-*/
-void qh_setdelaunay(int dim, int count, pointT *points) {
- int i, k;
- coordT *coordp, coord;
- realT paraboloid;
-
- trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
- coordp= points;
- for (i=0; i < count; i++) {
- coord= *coordp++;
- paraboloid= coord*coord;
- for (k=dim-2; k--; ) {
- coord= *coordp++;
- paraboloid += coord*coord;
- }
- *coordp++ = paraboloid;
- }
- if (qh last_low < REALmax/2)
- qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
-} /* setdelaunay */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethalfspace">-</a>
-
- qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
- set point to dual of halfspace relative to feasible point
- halfspace is normal coefficients and offset.
-
- returns:
- false if feasible point is outside of hull (error message already reported)
- overwrites coordinates for point at dim coords
- nextp= next point (coords)
-
- design:
- compute distance from feasible point to halfspace
- divide each normal coefficient by -dist
-*/
-boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
- coordT *normal, coordT *offset, coordT *feasible) {
- coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
- realT dist;
- realT r; /*bug fix*/
- int k;
- boolT zerodiv;
-
- dist= *offset;
- for (k=dim; k--; )
- dist += *(normp++) * *(feasiblep++);
- if (dist > 0)
- goto LABELerroroutside;
- normp= normal;
- if (dist < -qh MINdenom) {
- for (k=dim; k--; )
- *(coordp++)= *(normp++) / -dist;
- }else {
- for (k=dim; k--; ) {
- *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
- if (zerodiv)
- goto LABELerroroutside;
- }
- }
- *nextp= coordp;
- if (qh IStracing >= 4) {
- qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
- for (k=dim, coordp=coords; k--; ) {
- r= *coordp++;
- qh_fprintf(qh ferr, 8022, " %6.2g", r);
- }
- qh_fprintf(qh ferr, 8023, "\n");
- }
- return True;
-LABELerroroutside:
- feasiblep= feasible;
- normp= normal;
- qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
- for (k=dim; k--; )
- qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
- qh_fprintf(qh ferr, 8025, "\n halfspace: ");
- for (k=dim; k--; )
- qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
- qh_fprintf(qh ferr, 8027, "\n at offset: ");
- qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
- qh_fprintf(qh ferr, 8029, " and distance: ");
- qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
- qh_fprintf(qh ferr, 8031, "\n");
- return False;
-} /* sethalfspace */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sethalfspace_all">-</a>
-
- qh_sethalfspace_all( dim, count, halfspaces, feasible )
- generate dual for halfspace intersection with feasible point
- array of count halfspaces
- each halfspace is normal coefficients followed by offset
- the origin is inside the halfspace if the offset is negative
-
- returns:
- malloc'd array of count X dim-1 points
-
- notes:
- call before qh_init_B or qh_initqhull_globals
- unused/untested code: please email bradb@shore.net if this works ok for you
- If using option 'Fp', also set qh feasible_point. It is a malloc'd array
- that is freed by qh_freebuffers.
-
- design:
- see qh_sethalfspace
-*/
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
- int i, newdim;
- pointT *newpoints;
- coordT *coordp, *normalp, *offsetp;
-
- trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
- newdim= dim - 1;
- if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
- qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
- count);
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- coordp= newpoints;
- normalp= halfspaces;
- for (i=0; i < count; i++) {
- offsetp= normalp + newdim;
- if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
- qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- normalp= offsetp + 1;
- }
- return newpoints;
-} /* sethalfspace_all */
-
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="sharpnewfacets">-</a>
-
- qh_sharpnewfacets()
-
- returns:
- true if could be an acute angle (facets in different quadrants)
-
- notes:
- for qh_findbest
-
- design:
- for all facets on qh.newfacet_list
- if two facets are in different quadrants
- set issharp
-*/
-boolT qh_sharpnewfacets() {
- facetT *facet;
- boolT issharp = False;
- int *quadrant, k;
-
- quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
- FORALLfacet_(qh newfacet_list) {
- if (facet == qh newfacet_list) {
- for (k=qh hull_dim; k--; )
- quadrant[ k]= (facet->normal[ k] > 0);
- }else {
- for (k=qh hull_dim; k--; ) {
- if (quadrant[ k] != (facet->normal[ k] > 0)) {
- issharp= True;
- break;
- }
- }
- }
- if (issharp)
- break;
- }
- qh_memfree( quadrant, qh hull_dim * sizeof(int));
- trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
- return issharp;
-} /* sharpnewfacets */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="voronoi_center">-</a>
-
- qh_voronoi_center( dim, points )
- return Voronoi center for a set of points
- dim is the orginal dimension of the points
- gh.gm_matrix/qh.gm_row are scratch buffers
-
- returns:
- center as a temporary point
- if non-simplicial,
- returns center for max simplex of points
-
- notes:
- from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
-
- design:
- if non-simplicial
- determine max simplex for points
- translate point0 of simplex to origin
- compute sum of squares of diagonal
- compute determinate
- compute Voronoi center (see Bowyer & Woodwark)
-*/
-pointT *qh_voronoi_center(int dim, setT *points) {
- pointT *point, **pointp, *point0;
- pointT *center= (pointT*)qh_memalloc(qh center_size);
- setT *simplex;
- int i, j, k, size= qh_setsize(points);
- coordT *gmcoord;
- realT *diffp, sum2, *sum2row, *sum2p, det, factor;
- boolT nearzero, infinite;
-
- if (size == dim+1)
- simplex= points;
- else if (size < dim+1) {
- qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n need at least %d points to construct a Voronoi center\n",
- dim+1);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- simplex= points; /* never executed -- avoids warning */
- }else {
- simplex= qh_settemp(dim+1);
- qh_maxsimplex(dim, points, NULL, 0, &simplex);
- }
- point0= SETfirstt_(simplex, pointT);
- gmcoord= qh gm_matrix;
- for (k=0; k < dim; k++) {
- qh gm_row[k]= gmcoord;
- FOREACHpoint_(simplex) {
- if (point != point0)
- *(gmcoord++)= point[k] - point0[k];
- }
- }
- sum2row= gmcoord;
- for (i=0; i < dim; i++) {
- sum2= 0.0;
- for (k=0; k < dim; k++) {
- diffp= qh gm_row[k] + i;
- sum2 += *diffp * *diffp;
- }
- *(gmcoord++)= sum2;
- }
- det= qh_determinant(qh gm_row, dim, &nearzero);
- factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
- if (infinite) {
- for (k=dim; k--; )
- center[k]= qh_INFINITE;
- if (qh IStracing)
- qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
- }else {
- for (i=0; i < dim; i++) {
- gmcoord= qh gm_matrix;
- sum2p= sum2row;
- for (k=0; k < dim; k++) {
- qh gm_row[k]= gmcoord;
- if (k == i) {
- for (j=dim; j--; )
- *(gmcoord++)= *sum2p++;
- }else {
- FOREACHpoint_(simplex) {
- if (point != point0)
- *(gmcoord++)= point[k] - point0[k];
- }
- }
- }
- center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
- }
-#ifndef qh_NOtrace
- if (qh IStracing >= 3) {
- qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
- qh_printmatrix(qh ferr, "center:", &center, 1, dim);
- if (qh IStracing >= 5) {
- qh_printpoints(qh ferr, "points", simplex);
- FOREACHpoint_(simplex)
- qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
- qh_pointdist(point, center, dim));
- qh_fprintf(qh ferr, 8035, "\n");
- }
- }
-#endif
- }
- if (simplex != points)
- qh_settempfree(&simplex);
- return center;
-} /* voronoi_center */
-
diff --git a/PyMca/Object3D/Object3DQhull/src/global.c b/PyMca/Object3D/Object3DQhull/src/global.c
deleted file mode 100644
index a9063ea..0000000
--- a/PyMca/Object3D/Object3DQhull/src/global.c
+++ /dev/null
@@ -1,2127 +0,0 @@
-
-/*<html><pre> -<a href="qh-globa.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- global.c
- initializes all the globals of the qhull application
-
- see README
-
- see libqhull.h for qh.globals and function prototypes
-
- see qhull_a.h for internal functions
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $
- $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
- */
-
-#include "qhull_a.h"
-
-/*========= qh definition -- globals defined in libqhull.h =======================*/
-
-int qhull_inuse= 0; /* not used */
-
-#if qh_QHpointer
-qhT *qh_qh= NULL; /* pointer to all global variables */
-#else
-qhT qh_qh; /* all global variables.
- Add "= {0}" if this causes a compiler error.
- Also qh_qhstat in stat.c and qhmem in mem.c. */
-#endif
-
-/*-<a href ="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh_version">-</a>
-
- qh_version
- version string by year and date
-
- the revision increases on code changes only
-
- notes:
- change date: Changes.txt, Announce.txt, index.htm, README.txt,
- qhull-news.html, Eudora signatures, CMakeLists.txt
- change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
- change year: Copying.txt
- check download size
- recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
-*/
-
-const char *qh_version = "2012.1 2012/02/18";
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="appendprint">-</a>
-
- qh_appendprint( printFormat )
- append printFormat to qh.PRINTout unless already defined
-*/
-void qh_appendprint(qh_PRINT format) {
- int i;
-
- for (i=0; i < qh_PRINTEND; i++) {
- if (qh PRINTout[i] == format && format != qh_PRINTqhull)
- break;
- if (!qh PRINTout[i]) {
- qh PRINTout[i]= format;
- break;
- }
- }
-} /* appendprint */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="checkflags">-</a>
-
- qh_checkflags( commandStr, hiddenFlags )
- errors if commandStr contains hiddenFlags
- hiddenFlags starts and ends with a space and is space deliminated (checked)
-
- notes:
- ignores first word (e.g., "qconvex i")
- use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
- see:
- qh_initflags() initializes Qhull according to commandStr
-*/
-void qh_checkflags(char *command, char *hiddenflags) {
- char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
- char key, opt, prevopt;
- char chkkey[]= " ";
- char chkopt[]= " ";
- char chkopt2[]= " ";
- boolT waserr= False;
-
- if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
- qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (strpbrk(hiddenflags, ",\n\r\t")) {
- qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- while (*s && !isspace(*s)) /* skip program name */
- s++;
- while (*s) {
- while (*s && isspace(*s))
- s++;
- if (*s == '-')
- s++;
- if (!*s)
- break;
- key = *s++;
- chkerr = NULL;
- if (key == 'T' && (*s == 'I' || *s == 'O')) { /* TI or TO 'file name' */
- s= qh_skipfilename(++s);
- continue;
- }
- chkkey[1]= key;
- if (strstr(hiddenflags, chkkey)) {
- chkerr= chkkey;
- }else if (isupper(key)) {
- opt= ' ';
- prevopt= ' ';
- chkopt[1]= key;
- chkopt2[1]= key;
- while (!chkerr && *s && !isspace(*s)) {
- opt= *s++;
- if (isalpha(opt)) {
- chkopt[2]= opt;
- if (strstr(hiddenflags, chkopt))
- chkerr= chkopt;
- if (prevopt != ' ') {
- chkopt2[2]= prevopt;
- chkopt2[3]= opt;
- if (strstr(hiddenflags, chkopt2))
- chkerr= chkopt2;
- }
- }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
- && (prevopt == ' ' || islower(prevopt))) {
- chkopt[2]= opt;
- if (strstr(hiddenflags, chkopt))
- chkerr= chkopt;
- }else {
- qh_strtod(s-1, &t);
- if (s < t)
- s= t;
- }
- prevopt= opt;
- }
- }
- if (chkerr) {
- *chkerr= '\'';
- chkerr[strlen(chkerr)-1]= '\'';
- qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n It may be used with qhull.\n", chkerr);
- waserr= True;
- }
- }
- if (waserr)
- qh_errexit(qh_ERRinput, NULL, NULL);
-} /* checkflags */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="qh_clear_outputflags">-</a>
-
- qh_clear_outputflags()
- Clear output flags for QhullPoints
-*/
-void qh_clear_outputflags(void) {
- int i,k;
-
- qh ANNOTATEoutput= False;
- qh DOintersections= False;
- qh DROPdim= -1;
- qh FORCEoutput= False;
- qh GETarea= False;
- qh GOODpoint= 0;
- qh GOODpointp= NULL;
- qh GOODthreshold= False;
- qh GOODvertex= 0;
- qh GOODvertexp= NULL;
- qh IStracing= 0;
- qh KEEParea= False;
- qh KEEPmerge= False;
- qh KEEPminArea= REALmax;
- qh PRINTcentrums= False;
- qh PRINTcoplanar= False;
- qh PRINTdots= False;
- qh PRINTgood= False;
- qh PRINTinner= False;
- qh PRINTneighbors= False;
- qh PRINTnoplanes= False;
- qh PRINToptions1st= False;
- qh PRINTouter= False;
- qh PRINTprecision= True;
- qh PRINTridges= False;
- qh PRINTspheres= False;
- qh PRINTstatistics= False;
- qh PRINTsummary= False;
- qh PRINTtransparent= False;
- qh SPLITthresholds= False;
- qh TRACElevel= 0;
- qh TRInormals= False;
- qh USEstdout= False;
- qh VERIFYoutput= False;
- for (k=qh input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_ouputflags */
- qh lower_threshold[k]= -REALmax;
- qh upper_threshold[k]= REALmax;
- qh lower_bound[k]= -REALmax;
- qh upper_bound[k]= REALmax;
- }
-
- for (i=0; i < qh_PRINTEND; i++) {
- qh PRINTout[i]= qh_PRINTnone;
- }
-
- if (!qh qhull_commandsiz2)
- qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
- else {
- qh qhull_command[qh qhull_commandsiz2]= '\0';
- }
- if (!qh qhull_optionsiz2)
- qh qhull_optionsiz2= (int)strlen(qh qhull_options); /* WARN64 */
- else {
- qh qhull_options[qh qhull_optionsiz2]= '\0';
- qh qhull_optionlen= qh_OPTIONline; /* start a new line */
- }
-} /* clear_outputflags */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="clock">-</a>
-
- qh_clock()
- return user CPU time in 100ths (qh_SECtick)
- only defined for qh_CLOCKtype == 2
-
- notes:
- use first value to determine time 0
- from Stevens '92 8.15
-*/
-unsigned long qh_clock(void) {
-
-#if (qh_CLOCKtype == 2)
- struct tms time;
- static long clktck; /* initialized first call */
- double ratio, cpu;
- unsigned long ticks;
-
- if (!clktck) {
- if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
- qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed. Use qh_CLOCKtype 1 in user.h\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- }
- if (times(&time) == -1) {
- qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed. Use qh_CLOCKtype 1 in user.h\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- ratio= qh_SECticks / (double)clktck;
- ticks= time.tms_utime * ratio;
- return ticks;
-#else
- qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
- qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
- return 0;
-#endif
-} /* clock */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="freebuffers">-</a>
-
- qh_freebuffers()
- free up global memory buffers
-
- notes:
- must match qh_initbuffers()
-*/
-void qh_freebuffers(void) {
-
- trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
- /* allocated by qh_initqhull_buffers */
- qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
- qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
- qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
- qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
- qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
- qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
- qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
- qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
- qh lower_bound= qh upper_bound= NULL;
- qh gm_matrix= NULL;
- qh gm_row= NULL;
- qh_setfree(&qh other_points);
- qh_setfree(&qh del_vertices);
- qh_setfree(&qh coplanarfacetset);
- if (qh line) /* allocated by qh_readinput, freed if no error */
- qh_free(qh line);
- if (qh half_space)
- qh_free(qh half_space);
- if (qh temp_malloc)
- qh_free(qh temp_malloc);
- if (qh feasible_point) /* allocated by qh_readfeasible */
- qh_free(qh feasible_point);
- if (qh feasible_string) /* allocated by qh_initflags */
- qh_free(qh feasible_string);
- qh line= qh feasible_string= NULL;
- qh half_space= qh feasible_point= qh temp_malloc= NULL;
- /* usually allocated by qh_readinput */
- if (qh first_point && qh POINTSmalloc) {
- qh_free(qh first_point);
- qh first_point= NULL;
- }
- if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
- qh_free(qh input_points);
- qh input_points= NULL;
- }
- trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
-} /* freebuffers */
-
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="freebuild">-</a>
-
- qh_freebuild( allmem )
- free global memory used by qh_initbuild and qh_buildhull
- if !allmem,
- does not free short memory (e.g., facetT, freed by qh_memfreeshort)
-
- design:
- free centrums
- free each vertex
- mark unattached ridges
- for each facet
- free ridges
- free outside set, coplanar set, neighbor set, ridge set, vertex set
- free facet
- free hash table
- free interior point
- free merge set
- free temporary sets
-*/
-void qh_freebuild(boolT allmem) {
- facetT *facet;
- vertexT *vertex;
- ridgeT *ridge, **ridgep;
- mergeT *merge, **mergep;
-
- trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
- if (qh del_vertices)
- qh_settruncate(qh del_vertices, 0);
- if (allmem) {
- while ((vertex= qh vertex_list)) {
- if (vertex->next)
- qh_delvertex(vertex);
- else {
- qh_memfree(vertex, (int)sizeof(vertexT));
- qh newvertex_list= qh vertex_list= NULL;
- }
- }
- }else if (qh VERTEXneighbors) {
- FORALLvertices
- qh_setfreelong(&(vertex->neighbors));
- }
- qh VERTEXneighbors= False;
- qh GOODclosest= NULL;
- if (allmem) {
- FORALLfacets {
- FOREACHridge_(facet->ridges)
- ridge->seen= False;
- }
- FORALLfacets {
- if (facet->visible) {
- FOREACHridge_(facet->ridges) {
- if (!otherfacet_(ridge, facet)->visible)
- ridge->seen= True; /* an unattached ridge */
- }
- }
- }
- while ((facet= qh facet_list)) {
- FOREACHridge_(facet->ridges) {
- if (ridge->seen) {
- qh_setfree(&(ridge->vertices));
- qh_memfree(ridge, (int)sizeof(ridgeT));
- }else
- ridge->seen= True;
- }
- qh_setfree(&(facet->outsideset));
- qh_setfree(&(facet->coplanarset));
- qh_setfree(&(facet->neighbors));
- qh_setfree(&(facet->ridges));
- qh_setfree(&(facet->vertices));
- if (facet->next)
- qh_delfacet(facet);
- else {
- qh_memfree(facet, (int)sizeof(facetT));
- qh visible_list= qh newfacet_list= qh facet_list= NULL;
- }
- }
- }else {
- FORALLfacets {
- qh_setfreelong(&(facet->outsideset));
- qh_setfreelong(&(facet->coplanarset));
- if (!facet->simplicial) {
- qh_setfreelong(&(facet->neighbors));
- qh_setfreelong(&(facet->ridges));
- qh_setfreelong(&(facet->vertices));
- }
- }
- }
- qh_setfree(&(qh hash_table));
- qh_memfree(qh interior_point, qh normal_size);
- qh interior_point= NULL;
- FOREACHmerge_(qh facet_mergeset) /* usually empty */
- qh_memfree(merge, (int)sizeof(mergeT));
- qh facet_mergeset= NULL; /* temp set */
- qh degen_mergeset= NULL; /* temp set */
- qh_settempfree_all();
-} /* freebuild */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="freeqhull">-</a>
-
- qh_freeqhull( allmem )
- see qh_freeqhull2
- if qh_QHpointer, frees qh_qh
-*/
-void qh_freeqhull(boolT allmem) {
- qh_freeqhull2(allmem);
-#if qh_QHpointer
- qh_free(qh_qh);
- qh_qh= NULL;
-#endif
-}
-
-/*-<a href="qh-globa.htm#TOC"
->-------------------------------</a><a name="freeqhull2">-</a>
-
-qh_freeqhull2( allmem )
- free global memory
- if !allmem,
- does not free short memory (freed by qh_memfreeshort)
-
-notes:
- sets qh.NOerrexit in case caller forgets to
-
-see:
- see qh_initqhull_start2()
-
-design:
- free global and temporary memory from qh_initbuild and qh_buildhull
- free buffers
- free statistics
-*/
-void qh_freeqhull2(boolT allmem) {
-
- trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n"));
- qh NOerrexit= True; /* no more setjmp since called at exit and ~QhullQh */
- qh_freebuild(allmem);
- qh_freebuffers();
- qh_freestatistics();
-#if qh_QHpointer
- memset((char *)qh_qh, 0, sizeof(qhT));
- /* qh_qh freed by caller, qh_freeqhull() */
-#else
- memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
- qh NOerrexit= True;
-} /* freeqhull2 */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="init_A">-</a>
-
- qh_init_A( infile, outfile, errfile, argc, argv )
- initialize memory and stdio files
- convert input options to option string (qh.qhull_command)
-
- notes:
- infile may be NULL if qh_readpoints() is not called
-
- errfile should always be defined. It is used for reporting
- errors. outfile is used for output and format options.
-
- argc/argv may be 0/NULL
-
- called before error handling initialized
- qh_errexit() may not be used
-*/
-void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
- qh_meminit(errfile);
- qh_initqhull_start(infile, outfile, errfile);
- qh_init_qhull_command(argc, argv);
-} /* init_A */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="init_B">-</a>
-
- qh_init_B( points, numpoints, dim, ismalloc )
- initialize globals for points array
-
- points has numpoints dim-dimensional points
- points[0] is the first coordinate of the first point
- points[1] is the second coordinate of the first point
- points[dim] is the first coordinate of the second point
-
- ismalloc=True
- Qhull will call qh_free(points) on exit or input transformation
- ismalloc=False
- Qhull will allocate a new point array if needed for input transformation
-
- qh.qhull_command
- is the option string.
- It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
-
- returns:
- if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
- projects the input to a new point array
-
- if qh.DELAUNAY,
- qh.hull_dim is increased by one
- if qh.ATinfinity,
- qh_projectinput adds point-at-infinity for Delaunay tri.
-
- if qh.SCALEinput
- changes the upper and lower bounds of the input, see qh_scaleinput()
-
- if qh.ROTATEinput
- rotates the input by a random rotation, see qh_rotateinput()
- if qh.DELAUNAY
- rotates about the last coordinate
-
- notes:
- called after points are defined
- qh_errexit() may be used
-*/
-void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
- qh_initqhull_globals(points, numpoints, dim, ismalloc);
- if (qhmem.LASTsize == 0)
- qh_initqhull_mem();
- /* mem.c and qset.c are initialized */
- qh_initqhull_buffers();
- qh_initthresholds(qh qhull_command);
- if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
- qh_projectinput();
- if (qh SCALEinput)
- qh_scaleinput();
- if (qh ROTATErandom >= 0) {
- qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
- if (qh DELAUNAY) {
- int k, lastk= qh hull_dim-1;
- for (k=0; k < lastk; k++) {
- qh gm_row[k][lastk]= 0.0;
- qh gm_row[lastk][k]= 0.0;
- }
- qh gm_row[lastk][lastk]= 1.0;
- }
- qh_gram_schmidt(qh hull_dim, qh gm_row);
- qh_rotateinput(qh gm_row);
- }
-} /* init_B */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="init_qhull_command">-</a>
-
- qh_init_qhull_command( argc, argv )
- build qh.qhull_command from argc/argv
-
- returns:
- a space-delimited string of options (just as typed)
-
- notes:
- makes option string easy to input and output
-
- argc/argv may be 0/NULL
-*/
-void qh_init_qhull_command(int argc, char *argv[]) {
-
- if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
- /* Assumes qh.ferr is defined. */
- qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
- (int)sizeof(qh qhull_command));
- qh_exit(qh_ERRinput); /* error reported, can not use qh_errexit */
- }
-} /* init_qhull_command */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initflags">-</a>
-
- qh_initflags( commandStr )
- set flags and initialized constants from commandStr
-
- returns:
- sets qh.qhull_command to command if needed
-
- notes:
- ignores first word (e.g., "qhull d")
- use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
- see:
- qh_initthresholds() continues processing of 'Pdn' and 'PDn'
- 'prompt' in unix.c for documentation
-
- design:
- for each space-deliminated option group
- if top-level option
- check syntax
- append approriate option to option string
- set appropriate global variable or append printFormat to print options
- else
- for each sub-option
- check syntax
- append approriate option to option string
- set appropriate global variable or append printFormat to print options
-*/
-void qh_initflags(char *command) {
- int k, i, lastproject;
- char *s= command, *t, *prev_s, *start, key;
- boolT isgeom= False, wasproject;
- realT r;
-
- if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
- if (command != &qh qhull_command[0]) {
- *qh qhull_command= '\0';
- strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
- }
- while (*s && !isspace(*s)) /* skip program name */
- s++;
- }
- while (*s) {
- while (*s && isspace(*s))
- s++;
- if (*s == '-')
- s++;
- if (!*s)
- break;
- prev_s= s;
- switch (*s++) {
- case 'd':
- qh_option("delaunay", NULL, NULL);
- qh DELAUNAY= True;
- break;
- case 'f':
- qh_option("facets", NULL, NULL);
- qh_appendprint(qh_PRINTfacets);
- break;
- case 'i':
- qh_option("incidence", NULL, NULL);
- qh_appendprint(qh_PRINTincidences);
- break;
- case 'm':
- qh_option("mathematica", NULL, NULL);
- qh_appendprint(qh_PRINTmathematica);
- break;
- case 'n':
- qh_option("normals", NULL, NULL);
- qh_appendprint(qh_PRINTnormals);
- break;
- case 'o':
- qh_option("offFile", NULL, NULL);
- qh_appendprint(qh_PRINToff);
- break;
- case 'p':
- qh_option("points", NULL, NULL);
- qh_appendprint(qh_PRINTpoints);
- break;
- case 's':
- qh_option("summary", NULL, NULL);
- qh PRINTsummary= True;
- break;
- case 'v':
- qh_option("voronoi", NULL, NULL);
- qh VORONOI= True;
- qh DELAUNAY= True;
- break;
- case 'A':
- if (!isdigit(*s) && *s != '.' && *s != '-')
- qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'. Ignored.\n");
- else {
- if (*s == '-') {
- qh premerge_cos= -qh_strtod(s, &s);
- qh_option("Angle-premerge-", NULL, &qh premerge_cos);
- qh PREmerge= True;
- }else {
- qh postmerge_cos= qh_strtod(s, &s);
- qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
- qh POSTmerge= True;
- }
- qh MERGING= True;
- }
- break;
- case 'C':
- if (!isdigit(*s) && *s != '.' && *s != '-')
- qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'. Ignored.\n");
- else {
- if (*s == '-') {
- qh premerge_centrum= -qh_strtod(s, &s);
- qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
- qh PREmerge= True;
- }else {
- qh postmerge_centrum= qh_strtod(s, &s);
- qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
- qh POSTmerge= True;
- }
- qh MERGING= True;
- }
- break;
- case 'E':
- if (*s == '-')
- qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'. Ignored.\n");
- else if (!isdigit(*s))
- qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'. Ignored.\n");
- else {
- qh DISTround= qh_strtod(s, &s);
- qh_option("Distance-roundoff", NULL, &qh DISTround);
- qh SETroundoff= True;
- }
- break;
- case 'H':
- start= s;
- qh HALFspace= True;
- qh_strtod(s, &t);
- while (t > s) {
- if (*t && !isspace(*t)) {
- if (*t == ',')
- t++;
- else
- qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
- }
- s= t;
- qh_strtod(s, &t);
- }
- if (start < t) {
- if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
- qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- strncpy(qh feasible_string, start, (size_t)(t-start));
- qh_option("Halfspace-about", NULL, NULL);
- qh_option(qh feasible_string, NULL, NULL);
- }else
- qh_option("Halfspace", NULL, NULL);
- break;
- case 'R':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'. Ignored\n");
- else {
- qh RANDOMfactor= qh_strtod(s, &s);
- qh_option("Random_perturb", NULL, &qh RANDOMfactor);
- qh RANDOMdist= True;
- }
- break;
- case 'V':
- if (!isdigit(*s) && *s != '-')
- qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'. Ignored\n");
- else {
- qh MINvisible= qh_strtod(s, &s);
- qh_option("Visible", NULL, &qh MINvisible);
- }
- break;
- case 'U':
- if (!isdigit(*s) && *s != '-')
- qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'. Ignored\n");
- else {
- qh MAXcoplanar= qh_strtod(s, &s);
- qh_option("U-coplanar", NULL, &qh MAXcoplanar);
- }
- break;
- case 'W':
- if (*s == '-')
- qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'. Ignored.\n");
- else if (!isdigit(*s))
- qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'. Ignored\n");
- else {
- qh MINoutside= qh_strtod(s, &s);
- qh_option("W-outside", NULL, &qh MINoutside);
- qh APPROXhull= True;
- }
- break;
- /************ sub menus ***************/
- case 'F':
- while (*s && !isspace(*s)) {
- switch (*s++) {
- case 'a':
- qh_option("Farea", NULL, NULL);
- qh_appendprint(qh_PRINTarea);
- qh GETarea= True;
- break;
- case 'A':
- qh_option("FArea-total", NULL, NULL);
- qh GETarea= True;
- break;
- case 'c':
- qh_option("Fcoplanars", NULL, NULL);
- qh_appendprint(qh_PRINTcoplanars);
- break;
- case 'C':
- qh_option("FCentrums", NULL, NULL);
- qh_appendprint(qh_PRINTcentrums);
- break;
- case 'd':
- qh_option("Fd-cdd-in", NULL, NULL);
- qh CDDinput= True;
- break;
- case 'D':
- qh_option("FD-cdd-out", NULL, NULL);
- qh CDDoutput= True;
- break;
- case 'F':
- qh_option("FFacets-xridge", NULL, NULL);
- qh_appendprint(qh_PRINTfacets_xridge);
- break;
- case 'i':
- qh_option("Finner", NULL, NULL);
- qh_appendprint(qh_PRINTinner);
- break;
- case 'I':
- qh_option("FIDs", NULL, NULL);
- qh_appendprint(qh_PRINTids);
- break;
- case 'm':
- qh_option("Fmerges", NULL, NULL);
- qh_appendprint(qh_PRINTmerges);
- break;
- case 'M':
- qh_option("FMaple", NULL, NULL);
- qh_appendprint(qh_PRINTmaple);
- break;
- case 'n':
- qh_option("Fneighbors", NULL, NULL);
- qh_appendprint(qh_PRINTneighbors);
- break;
- case 'N':
- qh_option("FNeighbors-vertex", NULL, NULL);
- qh_appendprint(qh_PRINTvneighbors);
- break;
- case 'o':
- qh_option("Fouter", NULL, NULL);
- qh_appendprint(qh_PRINTouter);
- break;
- case 'O':
- if (qh PRINToptions1st) {
- qh_option("FOptions", NULL, NULL);
- qh_appendprint(qh_PRINToptions);
- }else
- qh PRINToptions1st= True;
- break;
- case 'p':
- qh_option("Fpoint-intersect", NULL, NULL);
- qh_appendprint(qh_PRINTpointintersect);
- break;
- case 'P':
- qh_option("FPoint-nearest", NULL, NULL);
- qh_appendprint(qh_PRINTpointnearest);
- break;
- case 'Q':
- qh_option("FQhull", NULL, NULL);
- qh_appendprint(qh_PRINTqhull);
- break;
- case 's':
- qh_option("Fsummary", NULL, NULL);
- qh_appendprint(qh_PRINTsummary);
- break;
- case 'S':
- qh_option("FSize", NULL, NULL);
- qh_appendprint(qh_PRINTsize);
- qh GETarea= True;
- break;
- case 't':
- qh_option("Ftriangles", NULL, NULL);
- qh_appendprint(qh_PRINTtriangles);
- break;
- case 'v':
- /* option set in qh_initqhull_globals */
- qh_appendprint(qh_PRINTvertices);
- break;
- case 'V':
- qh_option("FVertex-average", NULL, NULL);
- qh_appendprint(qh_PRINTaverage);
- break;
- case 'x':
- qh_option("Fxtremes", NULL, NULL);
- qh_appendprint(qh_PRINTextremes);
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- }
- break;
- case 'G':
- isgeom= True;
- qh_appendprint(qh_PRINTgeom);
- while (*s && !isspace(*s)) {
- switch (*s++) {
- case 'a':
- qh_option("Gall-points", NULL, NULL);
- qh PRINTdots= True;
- break;
- case 'c':
- qh_option("Gcentrums", NULL, NULL);
- qh PRINTcentrums= True;
- break;
- case 'h':
- qh_option("Gintersections", NULL, NULL);
- qh DOintersections= True;
- break;
- case 'i':
- qh_option("Ginner", NULL, NULL);
- qh PRINTinner= True;
- break;
- case 'n':
- qh_option("Gno-planes", NULL, NULL);
- qh PRINTnoplanes= True;
- break;
- case 'o':
- qh_option("Gouter", NULL, NULL);
- qh PRINTouter= True;
- break;
- case 'p':
- qh_option("Gpoints", NULL, NULL);
- qh PRINTcoplanar= True;
- break;
- case 'r':
- qh_option("Gridges", NULL, NULL);
- qh PRINTridges= True;
- break;
- case 't':
- qh_option("Gtransparent", NULL, NULL);
- qh PRINTtransparent= True;
- break;
- case 'v':
- qh_option("Gvertices", NULL, NULL);
- qh PRINTspheres= True;
- break;
- case 'D':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
- else {
- if (qh DROPdim >= 0)
- qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension. Previous 'GD%d' ignored\n",
- qh DROPdim);
- qh DROPdim= qh_strtol(s, &s);
- qh_option("GDrop-dim", &qh DROPdim, NULL);
- }
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- }
- break;
- case 'P':
- while (*s && !isspace(*s)) {
- switch (*s++) {
- case 'd': case 'D': /* see qh_initthresholds() */
- key= s[-1];
- i= qh_strtol(s, &s);
- r= 0;
- if (*s == ':') {
- s++;
- r= qh_strtod(s, &s);
- }
- if (key == 'd')
- qh_option("Pdrop-facets-dim-less", &i, &r);
- else
- qh_option("PDrop-facets-dim-more", &i, &r);
- break;
- case 'g':
- qh_option("Pgood-facets", NULL, NULL);
- qh PRINTgood= True;
- break;
- case 'G':
- qh_option("PGood-facet-neighbors", NULL, NULL);
- qh PRINTneighbors= True;
- break;
- case 'o':
- qh_option("Poutput-forced", NULL, NULL);
- qh FORCEoutput= True;
- break;
- case 'p':
- qh_option("Pprecision-ignore", NULL, NULL);
- qh PRINTprecision= False;
- break;
- case 'A':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
- else {
- qh KEEParea= qh_strtol(s, &s);
- qh_option("PArea-keep", &qh KEEParea, NULL);
- qh GETarea= True;
- }
- break;
- case 'F':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
- else {
- qh KEEPminArea= qh_strtod(s, &s);
- qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
- qh GETarea= True;
- }
- break;
- case 'M':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
- else {
- qh KEEPmerge= qh_strtol(s, &s);
- qh_option("PMerge-keep", &qh KEEPmerge, NULL);
- }
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- }
- break;
- case 'Q':
- lastproject= -1;
- while (*s && !isspace(*s)) {
- switch (*s++) {
- case 'b': case 'B': /* handled by qh_initthresholds */
- key= s[-1];
- if (key == 'b' && *s == 'B') {
- s++;
- r= qh_DEFAULTbox;
- qh SCALEinput= True;
- qh_option("QbBound-unit-box", NULL, &r);
- break;
- }
- if (key == 'b' && *s == 'b') {
- s++;
- qh SCALElast= True;
- qh_option("Qbbound-last", NULL, NULL);
- break;
- }
- k= qh_strtol(s, &s);
- r= 0.0;
- wasproject= False;
- if (*s == ':') {
- s++;
- if ((r= qh_strtod(s, &s)) == 0.0) {
- t= s; /* need true dimension for memory allocation */
- while (*t && !isspace(*t)) {
- if (toupper(*t++) == 'B'
- && k == qh_strtol(t, &t)
- && *t++ == ':'
- && qh_strtod(t, &t) == 0.0) {
- qh PROJECTinput++;
- trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
- qh_option("Qb-project-dim", &k, NULL);
- wasproject= True;
- lastproject= k;
- break;
- }
- }
- }
- }
- if (!wasproject) {
- if (lastproject == k && r == 0.0)
- lastproject= -1; /* doesn't catch all possible sequences */
- else if (key == 'b') {
- qh SCALEinput= True;
- if (r == 0.0)
- r= -qh_DEFAULTbox;
- qh_option("Qbound-dim-low", &k, &r);
- }else {
- qh SCALEinput= True;
- if (r == 0.0)
- r= qh_DEFAULTbox;
- qh_option("QBound-dim-high", &k, &r);
- }
- }
- break;
- case 'c':
- qh_option("Qcoplanar-keep", NULL, NULL);
- qh KEEPcoplanar= True;
- break;
- case 'f':
- qh_option("Qfurthest-outside", NULL, NULL);
- qh BESToutside= True;
- break;
- case 'g':
- qh_option("Qgood-facets-only", NULL, NULL);
- qh ONLYgood= True;
- break;
- case 'i':
- qh_option("Qinterior-keep", NULL, NULL);
- qh KEEPinside= True;
- break;
- case 'm':
- qh_option("Qmax-outside-only", NULL, NULL);
- qh ONLYmax= True;
- break;
- case 'r':
- qh_option("Qrandom-outside", NULL, NULL);
- qh RANDOMoutside= True;
- break;
- case 's':
- qh_option("Qsearch-initial-simplex", NULL, NULL);
- qh ALLpoints= True;
- break;
- case 't':
- qh_option("Qtriangulate", NULL, NULL);
- qh TRIangulate= True;
- break;
- case 'T':
- qh_option("QTestPoints", NULL, NULL);
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
- else {
- qh TESTpoints= qh_strtol(s, &s);
- qh_option("QTestPoints", &qh TESTpoints, NULL);
- }
- break;
- case 'u':
- qh_option("QupperDelaunay", NULL, NULL);
- qh UPPERdelaunay= True;
- break;
- case 'v':
- qh_option("Qvertex-neighbors-convex", NULL, NULL);
- qh TESTvneighbors= True;
- break;
- case 'x':
- qh_option("Qxact-merge", NULL, NULL);
- qh MERGEexact= True;
- break;
- case 'z':
- qh_option("Qz-infinity-point", NULL, NULL);
- qh ATinfinity= True;
- break;
- case '0':
- qh_option("Q0-no-premerge", NULL, NULL);
- qh NOpremerge= True;
- break;
- case '1':
- if (!isdigit(*s)) {
- qh_option("Q1-no-angle-sort", NULL, NULL);
- qh ANGLEmerge= False;
- break;
- }
- switch (*s++) {
- case '0':
- qh_option("Q10-no-narrow", NULL, NULL);
- qh NOnarrow= True;
- break;
- case '1':
- qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
- qh TRInormals= True;
- qh TRIangulate= True;
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- break;
- case '2':
- qh_option("Q2-no-merge-independent", NULL, NULL);
- qh MERGEindependent= False;
- goto LABELcheckdigit;
- break; /* no warnings */
- case '3':
- qh_option("Q3-no-merge-vertices", NULL, NULL);
- qh MERGEvertices= False;
- LABELcheckdigit:
- if (isdigit(*s))
- qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit. '%c' skipped.\n",
- *s++);
- break;
- case '4':
- qh_option("Q4-avoid-old-into-new", NULL, NULL);
- qh AVOIDold= True;
- break;
- case '5':
- qh_option("Q5-no-check-outer", NULL, NULL);
- qh SKIPcheckmax= True;
- break;
- case '6':
- qh_option("Q6-no-concave-merge", NULL, NULL);
- qh SKIPconvex= True;
- break;
- case '7':
- qh_option("Q7-no-breadth-first", NULL, NULL);
- qh VIRTUALmemory= True;
- break;
- case '8':
- qh_option("Q8-no-near-inside", NULL, NULL);
- qh NOnearinside= True;
- break;
- case '9':
- qh_option("Q9-pick-furthest", NULL, NULL);
- qh PICKfurthest= True;
- break;
- case 'G':
- i= qh_strtol(s, &t);
- if (qh GOODpoint)
- qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'. Ignored\n");
- else if (s == t)
- qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'. Ignored\n");
- else if (i < 0 || *s == '-') {
- qh GOODpoint= i-1;
- qh_option("QGood-if-dont-see-point", &i, NULL);
- }else {
- qh GOODpoint= i+1;
- qh_option("QGood-if-see-point", &i, NULL);
- }
- s= t;
- break;
- case 'J':
- if (!isdigit(*s) && *s != '-')
- qh JOGGLEmax= 0.0;
- else {
- qh JOGGLEmax= (realT) qh_strtod(s, &s);
- qh_option("QJoggle", NULL, &qh JOGGLEmax);
- }
- break;
- case 'R':
- if (!isdigit(*s) && *s != '-')
- qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'. Ignored\n");
- else {
- qh ROTATErandom= i= qh_strtol(s, &s);
- if (i > 0)
- qh_option("QRotate-id", &i, NULL );
- else if (i < -1)
- qh_option("QRandom-seed", &i, NULL );
- }
- break;
- case 'V':
- i= qh_strtol(s, &t);
- if (qh GOODvertex)
- qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'. Ignored\n");
- else if (s == t)
- qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'. Ignored\n");
- else if (i < 0) {
- qh GOODvertex= i - 1;
- qh_option("QV-good-facets-not-point", &i, NULL);
- }else {
- qh_option("QV-good-facets-point", &i, NULL);
- qh GOODvertex= i + 1;
- }
- s= t;
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- }
- break;
- case 'T':
- while (*s && !isspace(*s)) {
- if (isdigit(*s) || *s == '-')
- qh IStracing= qh_strtol(s, &s);
- else switch (*s++) {
- case 'a':
- qh_option("Tannotate-output", NULL, NULL);
- qh ANNOTATEoutput= True;
- break;
- case 'c':
- qh_option("Tcheck-frequently", NULL, NULL);
- qh CHECKfrequently= True;
- break;
- case 's':
- qh_option("Tstatistics", NULL, NULL);
- qh PRINTstatistics= True;
- break;
- case 'v':
- qh_option("Tverify", NULL, NULL);
- qh VERIFYoutput= True;
- break;
- case 'z':
- if (qh ferr == qh_FILEstderr) {
- /* The C++ interface captures the output in qh_fprint_qhull() */
- qh_option("Tz-stdout", NULL, NULL);
- qh USEstdout= True;
- }else if (!qh fout)
- qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout). Option 'Tz' ignored.\n");
- else {
- qh_option("Tz-stdout", NULL, NULL);
- qh USEstdout= True;
- qh ferr= qh fout;
- qhmem.ferr= qh fout;
- }
- break;
- case 'C':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'. Ignored\n");
- else {
- i= qh_strtol(s, &s);
- qh_option("TCone-stop", &i, NULL);
- qh STOPcone= i + 1;
- }
- break;
- case 'F':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'. Ignored\n");
- else {
- qh REPORTfreq= qh_strtol(s, &s);
- qh_option("TFacet-log", &qh REPORTfreq, NULL);
- qh REPORTfreq2= qh REPORTfreq/2; /* for tracemerging() */
- }
- break;
- case 'I':
- if (!isspace(*s))
- qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
- while (isspace(*s))
- s++;
- t= qh_skipfilename(s);
- {
- char filename[qh_FILENAMElen];
-
- qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
- s= t;
- if (!freopen(filename, "r", stdin)) {
- qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }else {
- qh_option("TInput-file", NULL, NULL);
- qh_option(filename, NULL, NULL);
- }
- }
- break;
- case 'O':
- if (!isspace(*s))
- qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
- while (isspace(*s))
- s++;
- t= qh_skipfilename(s);
- {
- char filename[qh_FILENAMElen];
-
- qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
- s= t;
- if (!freopen(filename, "w", stdout)) {
- qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }else {
- qh_option("TOutput-file", NULL, NULL);
- qh_option(filename, NULL, NULL);
- }
- }
- break;
- case 'P':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'. Ignored\n");
- else {
- qh TRACEpoint= qh_strtol(s, &s);
- qh_option("Trace-point", &qh TRACEpoint, NULL);
- }
- break;
- case 'M':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'. Ignored\n");
- else {
- qh TRACEmerge= qh_strtol(s, &s);
- qh_option("Trace-merge", &qh TRACEmerge, NULL);
- }
- break;
- case 'R':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'. Ignored\n");
- else {
- qh RERUN= qh_strtol(s, &s);
- qh_option("TRerun", &qh RERUN, NULL);
- }
- break;
- case 'V':
- i= qh_strtol(s, &t);
- if (s == t)
- qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'. Ignored\n");
- else if (i < 0) {
- qh STOPpoint= i - 1;
- qh_option("TV-stop-before-point", &i, NULL);
- }else {
- qh STOPpoint= i + 1;
- qh_option("TV-stop-after-point", &i, NULL);
- }
- s= t;
- break;
- case 'W':
- if (!isdigit(*s))
- qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'. Ignored\n");
- else {
- qh TRACEdist= (realT) qh_strtod(s, &s);
- qh_option("TWide-trace", NULL, &qh TRACEdist);
- }
- break;
- default:
- s--;
- qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
- while (*++s && !isspace(*s));
- break;
- }
- }
- break;
- default:
- qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
- (int)s[-1]);
- break;
- }
- if (s-1 == prev_s && *s && !isspace(*s)) {
- qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
- (int)*prev_s, (int)*prev_s);
- while (*s && !isspace(*s))
- s++;
- }
- }
- if (qh STOPcone && qh JOGGLEmax < REALmax/2)
- qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
- if (isgeom && !qh FORCEoutput && qh PRINTout[1])
- qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
- /* set derived values in qh_initqhull_globals */
-} /* initflags */
-
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_buffers">-</a>
-
- qh_initqhull_buffers()
- initialize global memory buffers
-
- notes:
- must match qh_freebuffers()
-*/
-void qh_initqhull_buffers(void) {
- int k;
-
- qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
- if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
- qh TEMPsize= 8; /* e.g., if qh_NOmem */
- qh other_points= qh_setnew(qh TEMPsize);
- qh del_vertices= qh_setnew(qh TEMPsize);
- qh coplanarfacetset= qh_setnew(qh TEMPsize);
- qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
- qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
- qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
- qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
- qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
- for (k=qh input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_ouputflags */
- qh lower_threshold[k]= -REALmax;
- qh upper_threshold[k]= REALmax;
- qh lower_bound[k]= -REALmax;
- qh upper_bound[k]= REALmax;
- }
- qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
- qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
-} /* initqhull_buffers */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_globals">-</a>
-
- qh_initqhull_globals( points, numpoints, dim, ismalloc )
- initialize globals
- if ismalloc
- points were malloc'd and qhull should free at end
-
- returns:
- sets qh.first_point, num_points, input_dim, hull_dim and others
- seeds random number generator (seed=1 if tracing)
- modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
- adjust user flags as needed
- also checks DIM3 dependencies and constants
-
- notes:
- do not use qh_point() since an input transformation may move them elsewhere
-
- see:
- qh_initqhull_start() sets default values for non-zero globals
-
- design:
- initialize points array from input arguments
- test for qh.ZEROcentrum
- (i.e., use opposite vertex instead of cetrum for convexity testing)
- initialize qh.CENTERtype, qh.normal_size,
- qh.center_size, qh.TRACEpoint/level,
- initialize and test random numbers
- qh_initqhull_outputflags() -- adjust and test output flags
-*/
-void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
- int seed, pointsneeded, extra= 0, i, randi, k;
- realT randr;
- realT factorial;
-
- time_t timedata;
-
- trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
- qh qhull_command));
- qh POINTSmalloc= ismalloc;
- qh first_point= points;
- qh num_points= numpoints;
- qh hull_dim= qh input_dim= dim;
- if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
- qh MERGING= True;
- if (qh hull_dim <= 4) {
- qh PREmerge= True;
- qh_option("_pre-merge", NULL, NULL);
- }else {
- qh MERGEexact= True;
- qh_option("Qxact_merge", NULL, NULL);
- }
- }else if (qh MERGEexact)
- qh MERGING= True;
- if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
-#ifdef qh_NOmerge
- qh JOGGLEmax= 0.0;
-#endif
- }
- if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
- qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output. Triangulated output('Qt') does nothing.\n");
- if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
- qh SCALElast= True;
- qh_option("Qbbound-last-qj", NULL, NULL);
- }
- if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
- && qh premerge_centrum == 0) {
- qh ZEROcentrum= True;
- qh ZEROall_ok= True;
- qh_option("_zero-centrum", NULL, NULL);
- }
- if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
- qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
- REALepsilon);
-#ifdef qh_NOmerge
- if (qh MERGING) {
- qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
-#endif
- if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
- qh KEEPinside= True;
- qh_option("Qinterior-keep", NULL, NULL);
- }
- if (qh DELAUNAY && qh HALFspace) {
- qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
- qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh UPPERdelaunay && qh ATinfinity) {
- qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
- qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
- qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
- qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
- && !qh NOnearinside);
- if (qh MERGING)
- qh CENTERtype= qh_AScentrum;
- else if (qh VORONOI)
- qh CENTERtype= qh_ASvoronoi;
- if (qh TESTvneighbors && !qh MERGING) {
- qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
- qh_errexit(qh_ERRinput, NULL ,NULL);
- }
- if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
- qh hull_dim -= qh PROJECTinput;
- if (qh DELAUNAY) {
- qh hull_dim++;
- if (qh ATinfinity)
- extra= 1;
- }
- }
- if (qh hull_dim <= 1) {
- qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- for (k=2, factorial=1.0; k < qh hull_dim; k++)
- factorial *= k;
- qh AREAfactor= 1.0 / factorial;
- trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals. dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
- dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
- qh normal_size= qh hull_dim * sizeof(coordT);
- qh center_size= qh normal_size - sizeof(coordT);
- pointsneeded= qh hull_dim+1;
- if (qh hull_dim > qh_DIMmergeVertex) {
- qh MERGEvertices= False;
- qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
- }
- if (qh GOODpoint)
- pointsneeded++;
-#ifdef qh_NOtrace
- if (qh IStracing) {
- qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-#endif
- if (qh RERUN > 1) {
- qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
- if (qh IStracing != -1)
- qh IStracing= 0;
- }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
- qh TRACElevel= (qh IStracing? qh IStracing : 3);
- qh IStracing= 0;
- }
- if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
- seed= (int)time(&timedata);
- if (qh ROTATErandom == -1) {
- seed= -seed;
- qh_option("QRandom-seed", &seed, NULL );
- }else
- qh_option("QRotate-random", &seed, NULL);
- qh ROTATErandom= seed;
- }
- seed= qh ROTATErandom;
- if (seed == INT_MIN) /* default value */
- seed= 1;
- else if (seed < 0)
- seed= -seed;
- qh_RANDOMseed_(seed);
- randr= 0.0;
- for (i=1000; i--; ) {
- randi= qh_RANDOMint;
- randr += randi;
- if (randi > qh_RANDOMmax) {
- qh_fprintf(qh ferr, 8036, "\
-qhull configuration error (qh_RANDOMmax in user.h):\n\
- random integer %d > qh_RANDOMmax(%.8g)\n",
- randi, qh_RANDOMmax);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- }
- qh_RANDOMseed_(seed);
- randr = randr/1000;
- if (randr < qh_RANDOMmax * 0.1
- || randr > qh_RANDOMmax * 0.9)
- qh_fprintf(qh ferr, 8037, "\
-qhull configuration warning (qh_RANDOMmax in user.h):\n\
- average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
- Is qh_RANDOMmax (%.2g) wrong?\n",
- randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
- qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
- qh RANDOMb= 1.0 - qh RANDOMfactor;
- if (qh_HASHfactor < 1.1) {
- qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
- qh_HASHfactor);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (numpoints+extra < pointsneeded) {
- qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
- numpoints, pointsneeded);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- qh_initqhull_outputflags();
-} /* initqhull_globals */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_mem">-</a>
-
- qh_initqhull_mem( )
- initialize mem.c for qhull
- qh.hull_dim and qh.normal_size determine some of the allocation sizes
- if qh.MERGING,
- includes ridgeT
- calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
- (see numsizes below)
-
- returns:
- mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
-
- notes:
- qh_produceoutput() prints memsizes
-
-*/
-void qh_initqhull_mem(void) {
- int numsizes;
- int i;
-
- numsizes= 8+10;
- qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
- qh_MEMbufsize,qh_MEMinitbuf);
- qh_memsize((int)sizeof(vertexT));
- if (qh MERGING) {
- qh_memsize((int)sizeof(ridgeT));
- qh_memsize((int)sizeof(mergeT));
- }
- qh_memsize((int)sizeof(facetT));
- i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize; /* ridge.vertices */
- qh_memsize(i);
- qh_memsize(qh normal_size); /* normal */
- i += SETelemsize; /* facet.vertices, .ridges, .neighbors */
- qh_memsize(i);
- qh_user_memsizes();
- qh_memsetup();
-} /* initqhull_mem */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_outputflags">-</a>
-
- qh_initqhull_outputflags
- initialize flags concerned with output
-
- returns:
- adjust user flags as needed
-
- see:
- qh_clear_outputflags() resets the flags
-
- design:
- test for qh.PRINTgood (i.e., only print 'good' facets)
- check for conflicting print output options
-*/
-void qh_initqhull_outputflags(void) {
- boolT printgeom= False, printmath= False, printcoplanar= False;
- int i;
-
- trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
- if (!(qh PRINTgood || qh PRINTneighbors)) {
- if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
- || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
- qh PRINTgood= True;
- qh_option("Pgood", NULL, NULL);
- }
- }
- if (qh PRINTtransparent) {
- if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
- qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- qh DROPdim = 3;
- qh PRINTridges = True;
- }
- for (i=qh_PRINTEND; i--; ) {
- if (qh PRINTout[i] == qh_PRINTgeom)
- printgeom= True;
- else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
- printmath= True;
- else if (qh PRINTout[i] == qh_PRINTcoplanars)
- printcoplanar= True;
- else if (qh PRINTout[i] == qh_PRINTpointnearest)
- printcoplanar= True;
- else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
- qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
- qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
- qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }else if (qh PRINTout[i] == qh_PRINTvertices) {
- if (qh VORONOI)
- qh_option("Fvoronoi", NULL, NULL);
- else
- qh_option("Fvertices", NULL, NULL);
- }
- }
- if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
- if (qh PRINTprecision)
- qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
- }
- if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
- qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (printgeom) {
- if (qh hull_dim > 4) {
- qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
- + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
- qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
- qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- /* can not warn about furthest-site Geomview output: no lower_threshold */
- if (qh hull_dim == 4 && qh DROPdim == -1 &&
- (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
- qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
-available for 4-d output(ignored). Could use 'GDn' instead.\n");
- qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
- }
- }
- if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
- if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
- if (qh QHULLfinished) {
- qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
- }else {
- qh KEEPcoplanar = True;
- qh_option("Qcoplanar", NULL, NULL);
- }
- }
- }
- qh PRINTdim= qh hull_dim;
- if (qh DROPdim >=0) { /* after Geomview checks */
- if (qh DROPdim < qh hull_dim) {
- qh PRINTdim--;
- if (!printgeom || qh hull_dim < 3)
- qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
- }else
- qh DROPdim= -1;
- }else if (qh VORONOI) {
- qh DROPdim= qh hull_dim-1;
- qh PRINTdim= qh hull_dim-1;
- }
-} /* qh_initqhull_outputflags */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_start">-</a>
-
- qh_initqhull_start( infile, outfile, errfile )
- allocate memory if needed and call qh_initqhull_start2()
-*/
-void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
-
-#if qh_QHpointer
- if (qh_qh) {
- qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined. Call qh_save_qhull() first\n");
- qh_exit(qh_ERRqhull); /* no error handler */
- }
- if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
- qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
- qh_exit(qh_ERRmem); /* no error handler */
- }
-#endif
- qh_initstatistics();
- qh_initqhull_start2(infile, outfile, errfile);
-} /* initqhull_start */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initqhull_start2">-</a>
-
- qh_initqhull_start2( infile, outfile, errfile )
- start initialization of qhull
- initialize statistics, stdio, default values for global variables
- assumes qh_qh is defined
- notes:
- report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
- see:
- qh_maxmin() determines the precision constants
- qh_freeqhull2()
-*/
-void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
- time_t timedata;
- int seed;
-
- qh_CPUclock; /* start the clock(for qh_clock). One-shot. */
-#if qh_QHpointer
- memset((char *)qh_qh, 0, sizeof(qhT)); /* every field is 0, FALSE, NULL */
-#else
- memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
- qh ANGLEmerge= True;
- qh DROPdim= -1;
- qh ferr= errfile;
- qh fin= infile;
- qh fout= outfile;
- qh furthest_id= -1;
- qh JOGGLEmax= REALmax;
- qh KEEPminArea = REALmax;
- qh last_low= REALmax;
- qh last_high= REALmax;
- qh last_newhigh= REALmax;
- qh max_outside= 0.0;
- qh max_vertex= 0.0;
- qh MAXabs_coord= 0.0;
- qh MAXsumcoord= 0.0;
- qh MAXwidth= -REALmax;
- qh MERGEindependent= True;
- qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
- qh MINoutside= 0.0;
- qh MINvisible= REALmax;
- qh MAXcoplanar= REALmax;
- qh outside_err= REALmax;
- qh premerge_centrum= 0.0;
- qh premerge_cos= REALmax;
- qh PRINTprecision= True;
- qh PRINTradius= 0.0;
- qh postmerge_cos= REALmax;
- qh postmerge_centrum= 0.0;
- qh ROTATErandom= INT_MIN;
- qh MERGEvertices= True;
- qh totarea= 0.0;
- qh totvol= 0.0;
- qh TRACEdist= REALmax;
- qh TRACEpoint= -1; /* recompile or use 'TPn' */
- qh tracefacet_id= UINT_MAX; /* recompile to trace a facet */
- qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
- seed= (int)time(&timedata);
- qh_RANDOMseed_(seed);
- qh run_id= qh_RANDOMint+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */
- qh_option("run-id", &qh run_id, NULL);
- strcat(qh qhull, "qhull");
-} /* initqhull_start2 */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="initthresholds">-</a>
-
- qh_initthresholds( commandString )
- set thresholds for printing and scaling from commandString
-
- returns:
- sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
-
- see:
- qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
- qh_inthresholds()
-
- design:
- for each 'Pdn' or 'PDn' option
- check syntax
- set qh.lower_threshold or qh.upper_threshold
- set qh.GOODthreshold if an unbounded threshold is used
- set qh.SPLITthreshold if a bounded threshold is used
-*/
-void qh_initthresholds(char *command) {
- realT value;
- int idx, maxdim, k;
- char *s= command; /* non-const due to strtol */
- char key;
-
- maxdim= qh input_dim;
- if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
- maxdim++;
- while (*s) {
- if (*s == '-')
- s++;
- if (*s == 'P') {
- s++;
- while (*s && !isspace(key= *s++)) {
- if (key == 'd' || key == 'D') {
- if (!isdigit(*s)) {
- qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s. Ignored\n",
- key, s-1);
- continue;
- }
- idx= qh_strtol(s, &s);
- if (idx >= qh hull_dim) {
- qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d. Ignored\n",
- idx, key, qh hull_dim);
- continue;
- }
- if (*s == ':') {
- s++;
- value= qh_strtod(s, &s);
- if (fabs((double)value) > 1.0) {
- qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1. Ignored\n",
- value, key);
- continue;
- }
- }else
- value= 0.0;
- if (key == 'd')
- qh lower_threshold[idx]= value;
- else
- qh upper_threshold[idx]= value;
- }
- }
- }else if (*s == 'Q') {
- s++;
- while (*s && !isspace(key= *s++)) {
- if (key == 'b' && *s == 'B') {
- s++;
- for (k=maxdim; k--; ) {
- qh lower_bound[k]= -qh_DEFAULTbox;
- qh upper_bound[k]= qh_DEFAULTbox;
- }
- }else if (key == 'b' && *s == 'b')
- s++;
- else if (key == 'b' || key == 'B') {
- if (!isdigit(*s)) {
- qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c. Ignored\n",
- key);
- continue;
- }
- idx= qh_strtol(s, &s);
- if (idx >= maxdim) {
- qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d. Ignored\n",
- idx, key, maxdim);
- continue;
- }
- if (*s == ':') {
- s++;
- value= qh_strtod(s, &s);
- }else if (key == 'b')
- value= -qh_DEFAULTbox;
- else
- value= qh_DEFAULTbox;
- if (key == 'b')
- qh lower_bound[idx]= value;
- else
- qh upper_bound[idx]= value;
- }
- }
- }else {
- while (*s && !isspace(*s))
- s++;
- }
- while (isspace(*s))
- s++;
- }
- for (k=qh hull_dim; k--; ) {
- if (qh lower_threshold[k] > -REALmax/2) {
- qh GOODthreshold= True;
- if (qh upper_threshold[k] < REALmax/2) {
- qh SPLITthresholds= True;
- qh GOODthreshold= False;
- break;
- }
- }else if (qh upper_threshold[k] < REALmax/2)
- qh GOODthreshold= True;
- }
-} /* initthresholds */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="option">-</a>
-
- qh_option( option, intVal, realVal )
- add an option description to qh.qhull_options
-
- notes:
- NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
- will be printed with statistics ('Ts') and errors
- strlen(option) < 40
-*/
-void qh_option(const char *option, int *i, realT *r) {
- char buf[200];
- int len, maxlen;
-
- sprintf(buf, " %s", option);
- if (i)
- sprintf(buf+strlen(buf), " %d", *i);
- if (r)
- sprintf(buf+strlen(buf), " %2.2g", *r);
- len= (int)strlen(buf); /* WARN64 */
- qh qhull_optionlen += len;
- maxlen= sizeof(qh qhull_options) - len -1;
- maximize_(maxlen, 0);
- if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
- qh qhull_optionlen= len;
- strncat(qh qhull_options, "\n", (size_t)(maxlen--));
- }
- strncat(qh qhull_options, buf, (size_t)maxlen);
-} /* option */
-
-#if qh_QHpointer
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="restore_qhull">-</a>
-
- qh_restore_qhull( oldqh )
- restores a previously saved qhull
- also restores qh_qhstat and qhmem.tempstack
- Sets *oldqh to NULL
- notes:
- errors if current qhull hasn't been saved or freed
- uses qhmem for error reporting
-
- NOTE 1998/5/11:
- Freeing memory after qh_save_qhull and qh_restore_qhull
- is complicated. The procedures will be redesigned.
-
- see:
- qh_save_qhull(), UsingLibQhull
-*/
-void qh_restore_qhull(qhT **oldqh) {
-
- if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
- qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
- *oldqh);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (qh_qh) {
- qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (!*oldqh || !(*oldqh)->old_qhstat) {
- qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
- *oldqh);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh_qh= *oldqh;
- *oldqh= NULL;
- qh_qhstat= qh old_qhstat;
- qhmem.tempstack= qh old_tempstack;
- qh old_qhstat= 0;
- qh old_tempstack= 0;
- trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
-} /* restore_qhull */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="save_qhull">-</a>
-
- qh_save_qhull( )
- saves qhull for a later qh_restore_qhull
- also saves qh_qhstat and qhmem.tempstack
-
- returns:
- qh_qh=NULL
-
- notes:
- need to initialize qhull or call qh_restore_qhull before continuing
-
- NOTE 1998/5/11:
- Freeing memory after qh_save_qhull and qh_restore_qhull
- is complicated. The procedures will be redesigned.
-
- see:
- qh_restore_qhull()
-*/
-qhT *qh_save_qhull(void) {
- qhT *oldqh;
-
- trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
- if (!qh_qh) {
- qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh old_qhstat= qh_qhstat;
- qh_qhstat= NULL;
- qh old_tempstack= qhmem.tempstack;
- qhmem.tempstack= NULL;
- oldqh= qh_qh;
- qh_qh= NULL;
- return oldqh;
-} /* save_qhull */
-
-#endif
-
diff --git a/PyMca/Object3D/Object3DQhull/src/io.c b/PyMca/Object3D/Object3DQhull/src/io.c
deleted file mode 100644
index 09a0079..0000000
--- a/PyMca/Object3D/Object3DQhull/src/io.c
+++ /dev/null
@@ -1,4060 +0,0 @@
-/*<html><pre> -<a href="qh-io.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- io.c
- Input/Output routines of qhull application
-
- see qh-io.htm and io.h
-
- see user.c for qh_errprint and qh_printfacetlist
-
- unix.c calls qh_readpoints and qh_produce_output
-
- unix.c and user.c are the only callers of io.c functions
- This allows the user to avoid loading io.o from qhull.a
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/io.c#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*========= -functions in alphabetical order after qh_produce_output() =====*/
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="produce_output">-</a>
-
- qh_produce_output()
- qh_produce_output2()
- prints out the result of qhull in desired format
- qh_produce_output2() does not call qh_prepare_output()
- if qh.GETarea
- computes and prints area and volume
- qh.PRINTout[] is an array of output formats
-
- notes:
- prints output in qh.PRINTout order
-*/
-void qh_produce_output(void) {
- int tempsize= qh_setsize(qhmem.tempstack);
-
- qh_prepare_output();
- qh_produce_output2();
- if (qh_setsize(qhmem.tempstack) != tempsize) {
- qh_fprintf(qh ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
- qh_setsize(qhmem.tempstack));
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-} /* produce_output */
-
-
-void qh_produce_output2(void) {
- int i, tempsize= qh_setsize(qhmem.tempstack), d_1;
-
- if (qh PRINTsummary)
- qh_printsummary(qh ferr);
- else if (qh PRINTout[0] == qh_PRINTnone)
- qh_printsummary(qh fout);
- for (i=0; i < qh_PRINTEND; i++)
- qh_printfacets(qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
- qh_allstatistics();
- if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
- qh_printstats(qh ferr, qhstat precision, NULL);
- if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
- qh_printstats(qh ferr, qhstat vridges, NULL);
- if (qh PRINTstatistics) {
- qh_printstatistics(qh ferr, "");
- qh_memstatistics(qh ferr);
- d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
- qh_fprintf(qh ferr, 8040, "\
- size in bytes: merge %d ridge %d vertex %d facet %d\n\
- normal %d ridge vertices %d facet vertices or neighbors %d\n",
- (int)sizeof(mergeT), (int)sizeof(ridgeT),
- (int)sizeof(vertexT), (int)sizeof(facetT),
- qh normal_size, d_1, d_1 + SETelemsize);
- }
- if (qh_setsize(qhmem.tempstack) != tempsize) {
- qh_fprintf(qh ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
- qh_setsize(qhmem.tempstack));
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-} /* produce_output2 */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="dfacet">-</a>
-
- dfacet( id )
- print facet by id, for debugging
-
-*/
-void dfacet(unsigned id) {
- facetT *facet;
-
- FORALLfacets {
- if (facet->id == id) {
- qh_printfacet(qh fout, facet);
- break;
- }
- }
-} /* dfacet */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="dvertex">-</a>
-
- dvertex( id )
- print vertex by id, for debugging
-*/
-void dvertex(unsigned id) {
- vertexT *vertex;
-
- FORALLvertices {
- if (vertex->id == id) {
- qh_printvertex(qh fout, vertex);
- break;
- }
- }
-} /* dvertex */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="compare_vertexpoint">-</a>
-
- qh_compare_vertexpoint( p1, p2 )
- used by qsort() to order vertices by point id
-*/
-int qh_compare_vertexpoint(const void *p1, const void *p2) {
- const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
-
- return((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
-} /* compare_vertexpoint */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="compare_facetarea">-</a>
-
- qh_compare_facetarea( p1, p2 )
- used by qsort() to order facets by area
-*/
-int qh_compare_facetarea(const void *p1, const void *p2) {
- const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
- if (!a->isarea)
- return -1;
- if (!b->isarea)
- return 1;
- if (a->f.area > b->f.area)
- return 1;
- else if (a->f.area == b->f.area)
- return 0;
- return -1;
-} /* compare_facetarea */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="compare_facetmerge">-</a>
-
- qh_compare_facetmerge( p1, p2 )
- used by qsort() to order facets by number of merges
-*/
-int qh_compare_facetmerge(const void *p1, const void *p2) {
- const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
- return(a->nummerge - b->nummerge);
-} /* compare_facetvisit */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="compare_facetvisit">-</a>
-
- qh_compare_facetvisit( p1, p2 )
- used by qsort() to order facets by visit id or id
-*/
-int qh_compare_facetvisit(const void *p1, const void *p2) {
- const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
- int i,j;
-
- if (!(i= a->visitid))
- i= 0 - a->id; /* do not convert to int, sign distinguishes id from visitid */
- if (!(j= b->visitid))
- j= 0 - b->id;
- return(i - j);
-} /* compare_facetvisit */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="copyfilename">-</a>
-
- qh_copyfilename( dest, size, source, length )
- copy filename identified by qh_skipfilename()
-
- notes:
- see qh_skipfilename() for syntax
-*/
-void qh_copyfilename(char *filename, int size, const char* source, int length) {
- char c= *source;
-
- if (length > size + 1) {
- qh_fprintf(qh ferr, 6040, "qhull error: filename is more than %d characters, %s\n", size-1, source);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- strncpy(filename, source, length);
- filename[length]= '\0';
- if (c == '\'' || c == '"') {
- char *s= filename + 1;
- char *t= filename;
- while (*s) {
- if (*s == c) {
- if (s[-1] == '\\')
- t[-1]= c;
- }else
- *t++= *s;
- s++;
- }
- *t= '\0';
- }
-} /* copyfilename */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="countfacets">-</a>
-
- qh_countfacets( facetlist, facets, printall,
- numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars )
- count good facets for printing and set visitid
- if allfacets, ignores qh_skipfacet()
-
- notes:
- qh_printsummary and qh_countfacets must match counts
-
- returns:
- numfacets, numsimplicial, total neighbors, numridges, coplanars
- each facet with ->visitid indicating 1-relative position
- ->visitid==0 indicates not good
-
- notes
- numfacets >= numsimplicial
- if qh.NEWfacets,
- does not count visible facets (matches qh_printafacet)
-
- design:
- for all facets on facetlist and in facets set
- unless facet is skipped or visible (i.e., will be deleted)
- mark facet->visitid
- update counts
-*/
-void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
- int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
- facetT *facet, **facetp;
- int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
-
- FORALLfacet_(facetlist) {
- if ((facet->visible && qh NEWfacets)
- || (!printall && qh_skipfacet(facet)))
- facet->visitid= 0;
- else {
- facet->visitid= ++numfacets;
- totneighbors += qh_setsize(facet->neighbors);
- if (facet->simplicial) {
- numsimplicial++;
- if (facet->keepcentrum && facet->tricoplanar)
- numtricoplanars++;
- }else
- numridges += qh_setsize(facet->ridges);
- if (facet->coplanarset)
- numcoplanars += qh_setsize(facet->coplanarset);
- }
- }
-
- FOREACHfacet_(facets) {
- if ((facet->visible && qh NEWfacets)
- || (!printall && qh_skipfacet(facet)))
- facet->visitid= 0;
- else {
- facet->visitid= ++numfacets;
- totneighbors += qh_setsize(facet->neighbors);
- if (facet->simplicial){
- numsimplicial++;
- if (facet->keepcentrum && facet->tricoplanar)
- numtricoplanars++;
- }else
- numridges += qh_setsize(facet->ridges);
- if (facet->coplanarset)
- numcoplanars += qh_setsize(facet->coplanarset);
- }
- }
- qh visit_id += numfacets+1;
- *numfacetsp= numfacets;
- *numsimplicialp= numsimplicial;
- *totneighborsp= totneighbors;
- *numridgesp= numridges;
- *numcoplanarsp= numcoplanars;
- *numtricoplanarsp= numtricoplanars;
-} /* countfacets */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="detvnorm">-</a>
-
- qh_detvnorm( vertex, vertexA, centers, offset )
- compute separating plane of the Voronoi diagram for a pair of input sites
- centers= set of facets (i.e., Voronoi vertices)
- facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
-
- assumes:
- qh_ASvoronoi and qh_vertexneighbors() already set
-
- returns:
- norm
- a pointer into qh.gm_matrix to qh.hull_dim-1 reals
- copy the data before reusing qh.gm_matrix
- offset
- if 'QVn'
- sign adjusted so that qh.GOODvertexp is inside
- else
- sign adjusted so that vertex is inside
-
- qh.gm_matrix= simplex of points from centers relative to first center
-
- notes:
- in io.c so that code for 'v Tv' can be removed by removing io.c
- returns pointer into qh.gm_matrix to avoid tracking of temporary memory
-
- design:
- determine midpoint of input sites
- build points as the set of Voronoi vertices
- select a simplex from points (if necessary)
- include midpoint if the Voronoi region is unbounded
- relocate the first vertex of the simplex to the origin
- compute the normalized hyperplane through the simplex
- orient the hyperplane toward 'QVn' or 'vertex'
- if 'Tv' or 'Ts'
- if bounded
- test that hyperplane is the perpendicular bisector of the input sites
- test that Voronoi vertices not in the simplex are still on the hyperplane
- free up temporary memory
-*/
-pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
- facetT *facet, **facetp;
- int i, k, pointid, pointidA, point_i, point_n;
- setT *simplex= NULL;
- pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
- coordT *coord, *gmcoord, *normalp;
- setT *points= qh_settemp(qh TEMPsize);
- boolT nearzero= False;
- boolT unbounded= False;
- int numcenters= 0;
- int dim= qh hull_dim - 1;
- realT dist, offset, angle, zero= 0.0;
-
- midpoint= qh gm_matrix + qh hull_dim * qh hull_dim; /* last row */
- for (k=0; k < dim; k++)
- midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
- FOREACHfacet_(centers) {
- numcenters++;
- if (!facet->visitid)
- unbounded= True;
- else {
- if (!facet->center)
- facet->center= qh_facetcenter(facet->vertices);
- qh_setappend(&points, facet->center);
- }
- }
- if (numcenters > dim) {
- simplex= qh_settemp(qh TEMPsize);
- qh_setappend(&simplex, vertex->point);
- if (unbounded)
- qh_setappend(&simplex, midpoint);
- qh_maxsimplex(dim, points, NULL, 0, &simplex);
- qh_setdelnth(simplex, 0);
- }else if (numcenters == dim) {
- if (unbounded)
- qh_setappend(&points, midpoint);
- simplex= points;
- }else {
- qh_fprintf(qh ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- i= 0;
- gmcoord= qh gm_matrix;
- point0= SETfirstt_(simplex, pointT);
- FOREACHpoint_(simplex) {
- if (qh IStracing >= 4)
- qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
- &point, 1, dim);
- if (point != point0) {
- qh gm_row[i++]= gmcoord;
- coord= point0;
- for (k=dim; k--; )
- *(gmcoord++)= *point++ - *coord++;
- }
- }
- qh gm_row[i]= gmcoord; /* does not overlap midpoint, may be used later for qh_areasimplex */
- normal= gmcoord;
- qh_sethyperplane_gauss(dim, qh gm_row, point0, True,
- normal, &offset, &nearzero);
- if (qh GOODvertexp == vertexA->point)
- inpoint= vertexA->point;
- else
- inpoint= vertex->point;
- zinc_(Zdistio);
- dist= qh_distnorm(dim, inpoint, normal, &offset);
- if (dist > 0) {
- offset= -offset;
- normalp= normal;
- for (k=dim; k--; ) {
- *normalp= -(*normalp);
- normalp++;
- }
- }
- if (qh VERIFYoutput || qh PRINTstatistics) {
- pointid= qh_pointid(vertex->point);
- pointidA= qh_pointid(vertexA->point);
- if (!unbounded) {
- zinc_(Zdiststat);
- dist= qh_distnorm(dim, midpoint, normal, &offset);
- if (dist < 0)
- dist= -dist;
- zzinc_(Zridgemid);
- wwmax_(Wridgemidmax, dist);
- wwadd_(Wridgemid, dist);
- trace4((qh ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
- pointid, pointidA, dist));
- for (k=0; k < dim; k++)
- midpoint[k]= vertexA->point[k] - vertex->point[k]; /* overwrites midpoint! */
- qh_normalize(midpoint, dim, False);
- angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
- if (angle < 0.0)
- angle= angle + 1.0;
- else
- angle= angle - 1.0;
- if (angle < 0.0)
- angle -= angle;
- trace4((qh ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
- pointid, pointidA, angle, nearzero));
- if (nearzero) {
- zzinc_(Zridge0);
- wwmax_(Wridge0max, angle);
- wwadd_(Wridge0, angle);
- }else {
- zzinc_(Zridgeok)
- wwmax_(Wridgeokmax, angle);
- wwadd_(Wridgeok, angle);
- }
- }
- if (simplex != points) {
- FOREACHpoint_i_(points) {
- if (!qh_setin(simplex, point)) {
- facet= SETelemt_(centers, point_i, facetT);
- zinc_(Zdiststat);
- dist= qh_distnorm(dim, point, normal, &offset);
- if (dist < 0)
- dist= -dist;
- zzinc_(Zridge);
- wwmax_(Wridgemax, dist);
- wwadd_(Wridge, dist);
- trace4((qh ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
- pointid, pointidA, facet->visitid, dist));
- }
- }
- }
- }
- *offsetp= offset;
- if (simplex != points)
- qh_settempfree(&simplex);
- qh_settempfree(&points);
- return normal;
-} /* detvnorm */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="detvridge">-</a>
-
- qh_detvridge( vertexA )
- determine Voronoi ridge from 'seen' neighbors of vertexA
- include one vertex-at-infinite if an !neighbor->visitid
-
- returns:
- temporary set of centers (facets, i.e., Voronoi vertices)
- sorted by center id
-*/
-setT *qh_detvridge(vertexT *vertex) {
- setT *centers= qh_settemp(qh TEMPsize);
- setT *tricenters= qh_settemp(qh TEMPsize);
- facetT *neighbor, **neighborp;
- boolT firstinf= True;
-
- FOREACHneighbor_(vertex) {
- if (neighbor->seen) {
- if (neighbor->visitid) {
- if (!neighbor->tricoplanar || qh_setunique(&tricenters, neighbor->center))
- qh_setappend(&centers, neighbor);
- }else if (firstinf) {
- firstinf= False;
- qh_setappend(&centers, neighbor);
- }
- }
- }
- qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(centers),
- sizeof(facetT *), qh_compare_facetvisit);
- qh_settempfree(&tricenters);
- return centers;
-} /* detvridge */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="detvridge3">-</a>
-
- qh_detvridge3( atvertex, vertex )
- determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
- include one vertex-at-infinite for !neighbor->visitid
- assumes all facet->seen2= True
-
- returns:
- temporary set of centers (facets, i.e., Voronoi vertices)
- listed in adjacency order (!oriented)
- all facet->seen2= True
-
- design:
- mark all neighbors of atvertex
- for each adjacent neighbor of both atvertex and vertex
- if neighbor selected
- add neighbor to set of Voronoi vertices
-*/
-setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
- setT *centers= qh_settemp(qh TEMPsize);
- setT *tricenters= qh_settemp(qh TEMPsize);
- facetT *neighbor, **neighborp, *facet= NULL;
- boolT firstinf= True;
-
- FOREACHneighbor_(atvertex)
- neighbor->seen2= False;
- FOREACHneighbor_(vertex) {
- if (!neighbor->seen2) {
- facet= neighbor;
- break;
- }
- }
- while (facet) {
- facet->seen2= True;
- if (neighbor->seen) {
- if (facet->visitid) {
- if (!facet->tricoplanar || qh_setunique(&tricenters, facet->center))
- qh_setappend(&centers, facet);
- }else if (firstinf) {
- firstinf= False;
- qh_setappend(&centers, facet);
- }
- }
- FOREACHneighbor_(facet) {
- if (!neighbor->seen2) {
- if (qh_setin(vertex->neighbors, neighbor))
- break;
- else
- neighbor->seen2= True;
- }
- }
- facet= neighbor;
- }
- if (qh CHECKfrequently) {
- FOREACHneighbor_(vertex) {
- if (!neighbor->seen2) {
- qh_fprintf(qh ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
- qh_pointid(vertex->point), neighbor->id);
- qh_errexit(qh_ERRqhull, neighbor, NULL);
- }
- }
- }
- FOREACHneighbor_(atvertex)
- neighbor->seen2= True;
- qh_settempfree(&tricenters);
- return centers;
-} /* detvridge3 */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="eachvoronoi">-</a>
-
- qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
- if visitall,
- visit all Voronoi ridges for vertex (i.e., an input site)
- else
- visit all unvisited Voronoi ridges for vertex
- all vertex->seen= False if unvisited
- assumes
- all facet->seen= False
- all facet->seen2= True (for qh_detvridge3)
- all facet->visitid == 0 if vertex_at_infinity
- == index of Voronoi vertex
- >= qh.num_facets if ignored
- innerouter:
- qh_RIDGEall-- both inner (bounded) and outer(unbounded) ridges
- qh_RIDGEinner- only inner
- qh_RIDGEouter- only outer
-
- if inorder
- orders vertices for 3-d Voronoi diagrams
-
- returns:
- number of visited ridges (does not include previously visited ridges)
-
- if printvridge,
- calls printvridge( fp, vertex, vertexA, centers)
- fp== any pointer (assumes FILE*)
- vertex,vertexA= pair of input sites that define a Voronoi ridge
- centers= set of facets (i.e., Voronoi vertices)
- ->visitid == index or 0 if vertex_at_infinity
- ordered for 3-d Voronoi diagram
- notes:
- uses qh.vertex_visit
-
- see:
- qh_eachvoronoi_all()
-
- design:
- mark selected neighbors of atvertex
- for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
- for each unvisited vertex
- if atvertex and vertex share more than d-1 neighbors
- bump totalcount
- if printvridge defined
- build the set of shared neighbors (i.e., Voronoi vertices)
- call printvridge
-*/
-int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
- boolT unbounded;
- int count;
- facetT *neighbor, **neighborp, *neighborA, **neighborAp;
- setT *centers;
- setT *tricenters= qh_settemp(qh TEMPsize);
-
- vertexT *vertex, **vertexp;
- boolT firstinf;
- unsigned int numfacets= (unsigned int)qh num_facets;
- int totridges= 0;
-
- qh vertex_visit++;
- atvertex->seen= True;
- if (visitall) {
- FORALLvertices
- vertex->seen= False;
- }
- FOREACHneighbor_(atvertex) {
- if (neighbor->visitid < numfacets)
- neighbor->seen= True;
- }
- FOREACHneighbor_(atvertex) {
- if (neighbor->seen) {
- FOREACHvertex_(neighbor->vertices) {
- if (vertex->visitid != qh vertex_visit && !vertex->seen) {
- vertex->visitid= qh vertex_visit;
- count= 0;
- firstinf= True;
- qh_settruncate(tricenters, 0);
- FOREACHneighborA_(vertex) {
- if (neighborA->seen) {
- if (neighborA->visitid) {
- if (!neighborA->tricoplanar || qh_setunique(&tricenters, neighborA->center))
- count++;
- }else if (firstinf) {
- count++;
- firstinf= False;
- }
- }
- }
- if (count >= qh hull_dim - 1) { /* e.g., 3 for 3-d Voronoi */
- if (firstinf) {
- if (innerouter == qh_RIDGEouter)
- continue;
- unbounded= False;
- }else {
- if (innerouter == qh_RIDGEinner)
- continue;
- unbounded= True;
- }
- totridges++;
- trace4((qh ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
- count, qh_pointid(atvertex->point), qh_pointid(vertex->point)));
- if (printvridge && fp) {
- if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
- centers= qh_detvridge3 (atvertex, vertex);
- else
- centers= qh_detvridge(vertex);
- (*printvridge) (fp, atvertex, vertex, centers, unbounded);
- qh_settempfree(&centers);
- }
- }
- }
- }
- }
- }
- FOREACHneighbor_(atvertex)
- neighbor->seen= False;
- qh_settempfree(&tricenters);
- return totridges;
-} /* eachvoronoi */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="eachvoronoi_all">-</a>
-
- qh_eachvoronoi_all( fp, printvridge, isUpper, innerouter, inorder )
- visit all Voronoi ridges
-
- innerouter:
- see qh_eachvoronoi()
-
- if inorder
- orders vertices for 3-d Voronoi diagrams
-
- returns
- total number of ridges
-
- if isUpper == facet->upperdelaunay (i.e., a Vornoi vertex)
- facet->visitid= Voronoi vertex index(same as 'o' format)
- else
- facet->visitid= 0
-
- if printvridge,
- calls printvridge( fp, vertex, vertexA, centers)
- [see qh_eachvoronoi]
-
- notes:
- Not used for qhull.exe
- same effect as qh_printvdiagram but ridges not sorted by point id
-*/
-int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
- facetT *facet;
- vertexT *vertex;
- int numcenters= 1; /* vertex 0 is vertex-at-infinity */
- int totridges= 0;
-
- qh_clearcenters(qh_ASvoronoi);
- qh_vertexneighbors();
- maximize_(qh visit_id, (unsigned) qh num_facets);
- FORALLfacets {
- facet->visitid= 0;
- facet->seen= False;
- facet->seen2= True;
- }
- FORALLfacets {
- if (facet->upperdelaunay == isUpper)
- facet->visitid= numcenters++;
- }
- FORALLvertices
- vertex->seen= False;
- FORALLvertices {
- if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
- continue;
- totridges += qh_eachvoronoi(fp, printvridge, vertex,
- !qh_ALL, innerouter, inorder);
- }
- return totridges;
-} /* eachvoronoi_all */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="facet2point">-</a>
-
- qh_facet2point( facet, point0, point1, mindist )
- return two projected temporary vertices for a 2-d facet
- may be non-simplicial
-
- returns:
- point0 and point1 oriented and projected to the facet
- returns mindist (maximum distance below plane)
-*/
-void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
- vertexT *vertex0, *vertex1;
- realT dist;
-
- if (facet->toporient ^ qh_ORIENTclock) {
- vertex0= SETfirstt_(facet->vertices, vertexT);
- vertex1= SETsecondt_(facet->vertices, vertexT);
- }else {
- vertex1= SETfirstt_(facet->vertices, vertexT);
- vertex0= SETsecondt_(facet->vertices, vertexT);
- }
- zadd_(Zdistio, 2);
- qh_distplane(vertex0->point, facet, &dist);
- *mindist= dist;
- *point0= qh_projectpoint(vertex0->point, facet, dist);
- qh_distplane(vertex1->point, facet, &dist);
- minimize_(*mindist, dist);
- *point1= qh_projectpoint(vertex1->point, facet, dist);
-} /* facet2point */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="facetvertices">-</a>
-
- qh_facetvertices( facetlist, facets, allfacets )
- returns temporary set of vertices in a set and/or list of facets
- if allfacets, ignores qh_skipfacet()
-
- returns:
- vertices with qh.vertex_visit
-
- notes:
- optimized for allfacets of facet_list
-
- design:
- if allfacets of facet_list
- create vertex set from vertex_list
- else
- for each selected facet in facets or facetlist
- append unvisited vertices to vertex set
-*/
-setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets) {
- setT *vertices;
- facetT *facet, **facetp;
- vertexT *vertex, **vertexp;
-
- qh vertex_visit++;
- if (facetlist == qh facet_list && allfacets && !facets) {
- vertices= qh_settemp(qh num_vertices);
- FORALLvertices {
- vertex->visitid= qh vertex_visit;
- qh_setappend(&vertices, vertex);
- }
- }else {
- vertices= qh_settemp(qh TEMPsize);
- FORALLfacet_(facetlist) {
- if (!allfacets && qh_skipfacet(facet))
- continue;
- FOREACHvertex_(facet->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- vertex->visitid= qh vertex_visit;
- qh_setappend(&vertices, vertex);
- }
- }
- }
- }
- FOREACHfacet_(facets) {
- if (!allfacets && qh_skipfacet(facet))
- continue;
- FOREACHvertex_(facet->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- vertex->visitid= qh vertex_visit;
- qh_setappend(&vertices, vertex);
- }
- }
- }
- return vertices;
-} /* facetvertices */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="geomplanes">-</a>
-
- qh_geomplanes( facet, outerplane, innerplane )
- return outer and inner planes for Geomview
- qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
-
- notes:
- assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-*/
-void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane) {
- realT radius;
-
- if (qh MERGING || qh JOGGLEmax < REALmax/2) {
- qh_outerinner(facet, outerplane, innerplane);
- radius= qh PRINTradius;
- if (qh JOGGLEmax < REALmax/2)
- radius -= qh JOGGLEmax * sqrt((realT)qh hull_dim); /* already accounted for in qh_outerinner() */
- *outerplane += radius;
- *innerplane -= radius;
- if (qh PRINTcoplanar || qh PRINTspheres) {
- *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
- *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
- }
- }else
- *innerplane= *outerplane= 0;
-} /* geomplanes */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="markkeep">-</a>
-
- qh_markkeep( facetlist )
- mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
- ignores visible facets (!part of convex hull)
-
- returns:
- may clear facet->good
- recomputes qh.num_good
-
- design:
- get set of good facets
- if qh.KEEParea
- sort facets by area
- clear facet->good for all but n largest facets
- if qh.KEEPmerge
- sort facets by merge count
- clear facet->good for all but n most merged facets
- if qh.KEEPminarea
- clear facet->good if area too small
- update qh.num_good
-*/
-void qh_markkeep(facetT *facetlist) {
- facetT *facet, **facetp;
- setT *facets= qh_settemp(qh num_facets);
- int size, count;
-
- trace2((qh ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
- qh KEEParea, qh KEEPmerge, qh KEEPminArea));
- FORALLfacet_(facetlist) {
- if (!facet->visible && facet->good)
- qh_setappend(&facets, facet);
- }
- size= qh_setsize(facets);
- if (qh KEEParea) {
- qsort(SETaddr_(facets, facetT), (size_t)size,
- sizeof(facetT *), qh_compare_facetarea);
- if ((count= size - qh KEEParea) > 0) {
- FOREACHfacet_(facets) {
- facet->good= False;
- if (--count == 0)
- break;
- }
- }
- }
- if (qh KEEPmerge) {
- qsort(SETaddr_(facets, facetT), (size_t)size,
- sizeof(facetT *), qh_compare_facetmerge);
- if ((count= size - qh KEEPmerge) > 0) {
- FOREACHfacet_(facets) {
- facet->good= False;
- if (--count == 0)
- break;
- }
- }
- }
- if (qh KEEPminArea < REALmax/2) {
- FOREACHfacet_(facets) {
- if (!facet->isarea || facet->f.area < qh KEEPminArea)
- facet->good= False;
- }
- }
- qh_settempfree(&facets);
- count= 0;
- FORALLfacet_(facetlist) {
- if (facet->good)
- count++;
- }
- qh num_good= count;
-} /* markkeep */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="markvoronoi">-</a>
-
- qh_markvoronoi( facetlist, facets, printall, isLower, numcenters )
- mark voronoi vertices for printing by site pairs
-
- returns:
- temporary set of vertices indexed by pointid
- isLower set if printing lower hull (i.e., at least one facet is lower hull)
- numcenters= total number of Voronoi vertices
- bumps qh.printoutnum for vertex-at-infinity
- clears all facet->seen and sets facet->seen2
-
- if selected
- facet->visitid= Voronoi vertex id
- else if upper hull (or 'Qu' and lower hull)
- facet->visitid= 0
- else
- facet->visitid >= qh num_facets
-
- notes:
- ignores qh.ATinfinity, if defined
-*/
-setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
- int numcenters=0;
- facetT *facet, **facetp;
- setT *vertices;
- boolT isLower= False;
-
- qh printoutnum++;
- qh_clearcenters(qh_ASvoronoi); /* in case, qh_printvdiagram2 called by user */
- qh_vertexneighbors();
- vertices= qh_pointvertex();
- if (qh ATinfinity)
- SETelem_(vertices, qh num_points-1)= NULL;
- qh visit_id++;
- maximize_(qh visit_id, (unsigned) qh num_facets);
- FORALLfacet_(facetlist) {
- if (printall || !qh_skipfacet(facet)) {
- if (!facet->upperdelaunay) {
- isLower= True;
- break;
- }
- }
- }
- FOREACHfacet_(facets) {
- if (printall || !qh_skipfacet(facet)) {
- if (!facet->upperdelaunay) {
- isLower= True;
- break;
- }
- }
- }
- FORALLfacets {
- if (facet->normal && (facet->upperdelaunay == isLower))
- facet->visitid= 0; /* facetlist or facets may overwrite */
- else
- facet->visitid= qh visit_id;
- facet->seen= False;
- facet->seen2= True;
- }
- numcenters++; /* qh_INFINITE */
- FORALLfacet_(facetlist) {
- if (printall || !qh_skipfacet(facet))
- facet->visitid= numcenters++;
- }
- FOREACHfacet_(facets) {
- if (printall || !qh_skipfacet(facet))
- facet->visitid= numcenters++;
- }
- *isLowerp= isLower;
- *numcentersp= numcenters;
- trace2((qh ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
- return vertices;
-} /* markvoronoi */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="order_vertexneighbors">-</a>
-
- qh_order_vertexneighbors( vertex )
- order facet neighbors of a 2-d or 3-d vertex by adjacency
-
- notes:
- does not orient the neighbors
-
- design:
- initialize a new neighbor set with the first facet in vertex->neighbors
- while vertex->neighbors non-empty
- select next neighbor in the previous facet's neighbor set
- set vertex->neighbors to the new neighbor set
-*/
-void qh_order_vertexneighbors(vertexT *vertex) {
- setT *newset;
- facetT *facet, *neighbor, **neighborp;
-
- trace4((qh ferr, 4018, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
- newset= qh_settemp(qh_setsize(vertex->neighbors));
- facet= (facetT*)qh_setdellast(vertex->neighbors);
- qh_setappend(&newset, facet);
- while (qh_setsize(vertex->neighbors)) {
- FOREACHneighbor_(vertex) {
- if (qh_setin(facet->neighbors, neighbor)) {
- qh_setdel(vertex->neighbors, neighbor);
- qh_setappend(&newset, neighbor);
- facet= neighbor;
- break;
- }
- }
- if (!neighbor) {
- qh_fprintf(qh ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
- vertex->id, facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- }
- qh_setfree(&vertex->neighbors);
- qh_settemppop();
- vertex->neighbors= newset;
-} /* order_vertexneighbors */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="prepare_output">-</a>
-
- qh_prepare_output( )
- prepare for qh_produce_output2() according to
- qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
- does not reset facet->good
-
- notes
- except for PRINTstatistics, no-op if previously called with same options
-*/
-void qh_prepare_output(void) {
- if (qh VORONOI) {
- qh_clearcenters (qh_ASvoronoi);
- qh_vertexneighbors();
- }
- if (qh TRIangulate && !qh hasTriangulation) {
- qh_triangulate();
- if (qh VERIFYoutput && !qh CHECKfrequently)
- qh_checkpolygon (qh facet_list);
- }
- qh_findgood_all (qh facet_list);
- if (qh GETarea)
- qh_getarea(qh facet_list);
- if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
- qh_markkeep (qh facet_list);
- if (qh PRINTstatistics)
- qh_collectstatistics();
-}
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printafacet">-</a>
-
- qh_printafacet( fp, format, facet, printall )
- print facet to fp in given output format (see qh.PRINTout)
-
- returns:
- nop if !printall and qh_skipfacet()
- nop if visible facet and NEWfacets and format != PRINTfacets
- must match qh_countfacets
-
- notes
- preserves qh.visit_id
- facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
-
- see
- qh_printbegin() and qh_printend()
-
- design:
- test for printing facet
- call appropriate routine for format
- or output results directly
-*/
-void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
- realT color[4], offset, dist, outerplane, innerplane;
- boolT zerodiv;
- coordT *point, *normp, *coordp, **pointp, *feasiblep;
- int k;
- vertexT *vertex, **vertexp;
- facetT *neighbor, **neighborp;
-
- if (!printall && qh_skipfacet(facet))
- return;
- if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
- return;
- qh printoutnum++;
- switch (format) {
- case qh_PRINTarea:
- if (facet->isarea) {
- qh_fprintf(fp, 9009, qh_REAL_1, facet->f.area);
- qh_fprintf(fp, 9010, "\n");
- }else
- qh_fprintf(fp, 9011, "0\n");
- break;
- case qh_PRINTcoplanars:
- qh_fprintf(fp, 9012, "%d", qh_setsize(facet->coplanarset));
- FOREACHpoint_(facet->coplanarset)
- qh_fprintf(fp, 9013, " %d", qh_pointid(point));
- qh_fprintf(fp, 9014, "\n");
- break;
- case qh_PRINTcentrums:
- qh_printcenter(fp, format, NULL, facet);
- break;
- case qh_PRINTfacets:
- qh_printfacet(fp, facet);
- break;
- case qh_PRINTfacets_xridge:
- qh_printfacetheader(fp, facet);
- break;
- case qh_PRINTgeom: /* either 2 , 3, or 4-d by qh_printbegin */
- if (!facet->normal)
- break;
- for (k=qh hull_dim; k--; ) {
- color[k]= (facet->normal[k]+1.0)/2.0;
- maximize_(color[k], -1.0);
- minimize_(color[k], +1.0);
- }
- qh_projectdim3 (color, color);
- if (qh PRINTdim != qh hull_dim)
- qh_normalize2 (color, 3, True, NULL, NULL);
- if (qh hull_dim <= 2)
- qh_printfacet2geom(fp, facet, color);
- else if (qh hull_dim == 3) {
- if (facet->simplicial)
- qh_printfacet3geom_simplicial(fp, facet, color);
- else
- qh_printfacet3geom_nonsimplicial(fp, facet, color);
- }else {
- if (facet->simplicial)
- qh_printfacet4geom_simplicial(fp, facet, color);
- else
- qh_printfacet4geom_nonsimplicial(fp, facet, color);
- }
- break;
- case qh_PRINTids:
- qh_fprintf(fp, 9015, "%d\n", facet->id);
- break;
- case qh_PRINTincidences:
- case qh_PRINToff:
- case qh_PRINTtriangles:
- if (qh hull_dim == 3 && format != qh_PRINTtriangles)
- qh_printfacet3vertex(fp, facet, format);
- else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
- qh_printfacetNvertex_simplicial(fp, facet, format);
- else
- qh_printfacetNvertex_nonsimplicial(fp, facet, qh printoutvar++, format);
- break;
- case qh_PRINTinner:
- qh_outerinner(facet, NULL, &innerplane);
- offset= facet->offset - innerplane;
- goto LABELprintnorm;
- break; /* prevent warning */
- case qh_PRINTmerges:
- qh_fprintf(fp, 9016, "%d\n", facet->nummerge);
- break;
- case qh_PRINTnormals:
- offset= facet->offset;
- goto LABELprintnorm;
- break; /* prevent warning */
- case qh_PRINTouter:
- qh_outerinner(facet, &outerplane, NULL);
- offset= facet->offset - outerplane;
- LABELprintnorm:
- if (!facet->normal) {
- qh_fprintf(fp, 9017, "no normal for facet f%d\n", facet->id);
- break;
- }
- if (qh CDDoutput) {
- qh_fprintf(fp, 9018, qh_REAL_1, -offset);
- for (k=0; k < qh hull_dim; k++)
- qh_fprintf(fp, 9019, qh_REAL_1, -facet->normal[k]);
- }else {
- for (k=0; k < qh hull_dim; k++)
- qh_fprintf(fp, 9020, qh_REAL_1, facet->normal[k]);
- qh_fprintf(fp, 9021, qh_REAL_1, offset);
- }
- qh_fprintf(fp, 9022, "\n");
- break;
- case qh_PRINTmathematica: /* either 2 or 3-d by qh_printbegin */
- case qh_PRINTmaple:
- if (qh hull_dim == 2)
- qh_printfacet2math(fp, facet, format, qh printoutvar++);
- else
- qh_printfacet3math(fp, facet, format, qh printoutvar++);
- break;
- case qh_PRINTneighbors:
- qh_fprintf(fp, 9023, "%d", qh_setsize(facet->neighbors));
- FOREACHneighbor_(facet)
- qh_fprintf(fp, 9024, " %d",
- neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
- qh_fprintf(fp, 9025, "\n");
- break;
- case qh_PRINTpointintersect:
- if (!qh feasible_point) {
- qh_fprintf(qh ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
- qh_errexit( qh_ERRinput, NULL, NULL);
- }
- if (facet->offset > 0)
- goto LABELprintinfinite;
- point= coordp= (coordT*)qh_memalloc(qh normal_size);
- normp= facet->normal;
- feasiblep= qh feasible_point;
- if (facet->offset < -qh MINdenom) {
- for (k=qh hull_dim; k--; )
- *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
- }else {
- for (k=qh hull_dim; k--; ) {
- *(coordp++)= qh_divzero(*(normp++), facet->offset, qh MINdenom_1,
- &zerodiv) + *(feasiblep++);
- if (zerodiv) {
- qh_memfree(point, qh normal_size);
- goto LABELprintinfinite;
- }
- }
- }
- qh_printpoint(fp, NULL, point);
- qh_memfree(point, qh normal_size);
- break;
- LABELprintinfinite:
- for (k=qh hull_dim; k--; )
- qh_fprintf(fp, 9026, qh_REAL_1, qh_INFINITE);
- qh_fprintf(fp, 9027, "\n");
- break;
- case qh_PRINTpointnearest:
- FOREACHpoint_(facet->coplanarset) {
- int id, id2;
- vertex= qh_nearvertex(facet, point, &dist);
- id= qh_pointid(vertex->point);
- id2= qh_pointid(point);
- qh_fprintf(fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
- }
- break;
- case qh_PRINTpoints: /* VORONOI only by qh_printbegin */
- if (qh CDDoutput)
- qh_fprintf(fp, 9029, "1 ");
- qh_printcenter(fp, format, NULL, facet);
- break;
- case qh_PRINTvertices:
- qh_fprintf(fp, 9030, "%d", qh_setsize(facet->vertices));
- FOREACHvertex_(facet->vertices)
- qh_fprintf(fp, 9031, " %d", qh_pointid(vertex->point));
- qh_fprintf(fp, 9032, "\n");
- break;
- default:
- break;
- }
-} /* printafacet */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printbegin">-</a>
-
- qh_printbegin( )
- prints header for all output formats
-
- returns:
- checks for valid format
-
- notes:
- uses qh.visit_id for 3/4off
- changes qh.interior_point if printing centrums
- qh_countfacets clears facet->visitid for non-good facets
-
- see
- qh_printend() and qh_printafacet()
-
- design:
- count facets and related statistics
- print header for format
-*/
-void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
- int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
- int i, num;
- facetT *facet, **facetp;
- vertexT *vertex, **vertexp;
- setT *vertices;
- pointT *point, **pointp, *pointtemp;
-
- qh printoutnum= 0;
- qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
- &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
- switch (format) {
- case qh_PRINTnone:
- break;
- case qh_PRINTarea:
- qh_fprintf(fp, 9033, "%d\n", numfacets);
- break;
- case qh_PRINTcoplanars:
- qh_fprintf(fp, 9034, "%d\n", numfacets);
- break;
- case qh_PRINTcentrums:
- if (qh CENTERtype == qh_ASnone)
- qh_clearcenters(qh_AScentrum);
- qh_fprintf(fp, 9035, "%d\n%d\n", qh hull_dim, numfacets);
- break;
- case qh_PRINTfacets:
- case qh_PRINTfacets_xridge:
- if (facetlist)
- qh_printvertexlist(fp, "Vertices and facets:\n", facetlist, facets, printall);
- break;
- case qh_PRINTgeom:
- if (qh hull_dim > 4) /* qh_initqhull_globals also checks */
- goto LABELnoformat;
- if (qh VORONOI && qh hull_dim > 3) /* PRINTdim == DROPdim == hull_dim-1 */
- goto LABELnoformat;
- if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
- qh_fprintf(qh ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
- if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
- (qh PRINTdim == 4 && qh PRINTcentrums)))
- qh_fprintf(qh ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
- if (qh PRINTdim == 4 && (qh PRINTspheres))
- qh_fprintf(qh ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
- if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
- qh_fprintf(qh ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
- if (qh PRINTdim == 2) {
- qh_fprintf(fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
- qh rbox_command, qh qhull_command);
- }else if (qh PRINTdim == 3) {
- qh_fprintf(fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
- qh rbox_command, qh qhull_command);
- }else if (qh PRINTdim == 4) {
- qh visit_id++;
- num= 0;
- FORALLfacet_(facetlist) /* get number of ridges to be printed */
- qh_printend4geom(NULL, facet, &num, printall);
- FOREACHfacet_(facets)
- qh_printend4geom(NULL, facet, &num, printall);
- qh ridgeoutnum= num;
- qh printoutvar= 0; /* counts number of ridges in output */
- qh_fprintf(fp, 9038, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
- }
-
- if (qh PRINTdots) {
- qh printoutnum++;
- num= qh num_points + qh_setsize(qh other_points);
- if (qh DELAUNAY && qh ATinfinity)
- num--;
- if (qh PRINTdim == 4)
- qh_fprintf(fp, 9039, "4VECT %d %d 1\n", num, num);
- else
- qh_fprintf(fp, 9040, "VECT %d %d 1\n", num, num);
-
- for (i=num; i--; ) {
- if (i % 20 == 0)
- qh_fprintf(fp, 9041, "\n");
- qh_fprintf(fp, 9042, "1 ");
- }
- qh_fprintf(fp, 9043, "# 1 point per line\n1 ");
- for (i=num-1; i--; ) { /* num at least 3 for D2 */
- if (i % 20 == 0)
- qh_fprintf(fp, 9044, "\n");
- qh_fprintf(fp, 9045, "0 ");
- }
- qh_fprintf(fp, 9046, "# 1 color for all\n");
- FORALLpoints {
- if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
- if (qh PRINTdim == 4)
- qh_printpoint(fp, NULL, point);
- else
- qh_printpoint3 (fp, point);
- }
- }
- FOREACHpoint_(qh other_points) {
- if (qh PRINTdim == 4)
- qh_printpoint(fp, NULL, point);
- else
- qh_printpoint3 (fp, point);
- }
- qh_fprintf(fp, 9047, "0 1 1 1 # color of points\n");
- }
-
- if (qh PRINTdim == 4 && !qh PRINTnoplanes)
- /* 4dview loads up multiple 4OFF objects slowly */
- qh_fprintf(fp, 9048, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
- qh PRINTcradius= 2 * qh DISTround; /* include test DISTround */
- if (qh PREmerge) {
- maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
- }else if (qh POSTmerge)
- maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
- qh PRINTradius= qh PRINTcradius;
- if (qh PRINTspheres + qh PRINTcoplanar)
- maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
- if (qh premerge_cos < REALmax/2) {
- maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
- }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
- maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
- }
- maximize_(qh PRINTradius, qh MINvisible);
- if (qh JOGGLEmax < REALmax/2)
- qh PRINTradius += qh JOGGLEmax * sqrt((realT)qh hull_dim);
- if (qh PRINTdim != 4 &&
- (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
- vertices= qh_facetvertices(facetlist, facets, printall);
- if (qh PRINTspheres && qh PRINTdim <= 3)
- qh_printspheres(fp, vertices, qh PRINTradius);
- if (qh PRINTcoplanar || qh PRINTcentrums) {
- qh firstcentrum= True;
- if (qh PRINTcoplanar&& !qh PRINTspheres) {
- FOREACHvertex_(vertices)
- qh_printpointvect2 (fp, vertex->point, NULL, qh interior_point, qh PRINTradius);
- }
- FORALLfacet_(facetlist) {
- if (!printall && qh_skipfacet(facet))
- continue;
- if (!facet->normal)
- continue;
- if (qh PRINTcentrums && qh PRINTdim <= 3)
- qh_printcentrum(fp, facet, qh PRINTcradius);
- if (!qh PRINTcoplanar)
- continue;
- FOREACHpoint_(facet->coplanarset)
- qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
- FOREACHpoint_(facet->outsideset)
- qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
- }
- FOREACHfacet_(facets) {
- if (!printall && qh_skipfacet(facet))
- continue;
- if (!facet->normal)
- continue;
- if (qh PRINTcentrums && qh PRINTdim <= 3)
- qh_printcentrum(fp, facet, qh PRINTcradius);
- if (!qh PRINTcoplanar)
- continue;
- FOREACHpoint_(facet->coplanarset)
- qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
- FOREACHpoint_(facet->outsideset)
- qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
- }
- }
- qh_settempfree(&vertices);
- }
- qh visit_id++; /* for printing hyperplane intersections */
- break;
- case qh_PRINTids:
- qh_fprintf(fp, 9049, "%d\n", numfacets);
- break;
- case qh_PRINTincidences:
- if (qh VORONOI && qh PRINTprecision)
- qh_fprintf(qh ferr, 7053, "qhull warning: writing Delaunay. Use 'p' or 'o' for Voronoi centers\n");
- qh printoutvar= qh vertex_id; /* centrum id for non-simplicial facets */
- if (qh hull_dim <= 3)
- qh_fprintf(fp, 9050, "%d\n", numfacets);
- else
- qh_fprintf(fp, 9051, "%d\n", numsimplicial+numridges);
- break;
- case qh_PRINTinner:
- case qh_PRINTnormals:
- case qh_PRINTouter:
- if (qh CDDoutput)
- qh_fprintf(fp, 9052, "%s | %s\nbegin\n %d %d real\n", qh rbox_command,
- qh qhull_command, numfacets, qh hull_dim+1);
- else
- qh_fprintf(fp, 9053, "%d\n%d\n", qh hull_dim+1, numfacets);
- break;
- case qh_PRINTmathematica:
- case qh_PRINTmaple:
- if (qh hull_dim > 3) /* qh_initbuffers also checks */
- goto LABELnoformat;
- if (qh VORONOI)
- qh_fprintf(qh ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
- if (format == qh_PRINTmaple) {
- if (qh hull_dim == 2)
- qh_fprintf(fp, 9054, "PLOT(CURVES(\n");
- else
- qh_fprintf(fp, 9055, "PLOT3D(POLYGONS(\n");
- }else
- qh_fprintf(fp, 9056, "{\n");
- qh printoutvar= 0; /* counts number of facets for notfirst */
- break;
- case qh_PRINTmerges:
- qh_fprintf(fp, 9057, "%d\n", numfacets);
- break;
- case qh_PRINTpointintersect:
- qh_fprintf(fp, 9058, "%d\n%d\n", qh hull_dim, numfacets);
- break;
- case qh_PRINTneighbors:
- qh_fprintf(fp, 9059, "%d\n", numfacets);
- break;
- case qh_PRINToff:
- case qh_PRINTtriangles:
- if (qh VORONOI)
- goto LABELnoformat;
- num = qh hull_dim;
- if (format == qh_PRINToff || qh hull_dim == 2)
- qh_fprintf(fp, 9060, "%d\n%d %d %d\n", num,
- qh num_points+qh_setsize(qh other_points), numfacets, totneighbors/2);
- else { /* qh_PRINTtriangles */
- qh printoutvar= qh num_points+qh_setsize(qh other_points); /* first centrum */
- if (qh DELAUNAY)
- num--; /* drop last dimension */
- qh_fprintf(fp, 9061, "%d\n%d %d %d\n", num, qh printoutvar
- + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
- }
- FORALLpoints
- qh_printpointid(qh fout, NULL, num, point, -1);
- FOREACHpoint_(qh other_points)
- qh_printpointid(qh fout, NULL, num, point, -1);
- if (format == qh_PRINTtriangles && qh hull_dim > 2) {
- FORALLfacets {
- if (!facet->simplicial && facet->visitid)
- qh_printcenter(qh fout, format, NULL, facet);
- }
- }
- break;
- case qh_PRINTpointnearest:
- qh_fprintf(fp, 9062, "%d\n", numcoplanars);
- break;
- case qh_PRINTpoints:
- if (!qh VORONOI)
- goto LABELnoformat;
- if (qh CDDoutput)
- qh_fprintf(fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
- qh qhull_command, numfacets, qh hull_dim);
- else
- qh_fprintf(fp, 9064, "%d\n%d\n", qh hull_dim-1, numfacets);
- break;
- case qh_PRINTvertices:
- qh_fprintf(fp, 9065, "%d\n", numfacets);
- break;
- case qh_PRINTsummary:
- default:
- LABELnoformat:
- qh_fprintf(qh ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
- qh hull_dim);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-} /* printbegin */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printcenter">-</a>
-
- qh_printcenter( fp, string, facet )
- print facet->center as centrum or Voronoi center
- string may be NULL. Don't include '%' codes.
- nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
- if upper envelope of Delaunay triangulation and point at-infinity
- prints qh_INFINITE instead;
-
- notes:
- defines facet->center if needed
- if format=PRINTgeom, adds a 0 if would otherwise be 2-d
- Same as QhullFacet::printCenter
-*/
-void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
- int k, num;
-
- if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
- return;
- if (string)
- qh_fprintf(fp, 9066, string);
- if (qh CENTERtype == qh_ASvoronoi) {
- num= qh hull_dim-1;
- if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
- if (!facet->center)
- facet->center= qh_facetcenter(facet->vertices);
- for (k=0; k < num; k++)
- qh_fprintf(fp, 9067, qh_REAL_1, facet->center[k]);
- }else {
- for (k=0; k < num; k++)
- qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE);
- }
- }else /* qh CENTERtype == qh_AScentrum */ {
- num= qh hull_dim;
- if (format == qh_PRINTtriangles && qh DELAUNAY)
- num--;
- if (!facet->center)
- facet->center= qh_getcentrum(facet);
- for (k=0; k < num; k++)
- qh_fprintf(fp, 9069, qh_REAL_1, facet->center[k]);
- }
- if (format == qh_PRINTgeom && num == 2)
- qh_fprintf(fp, 9070, " 0\n");
- else
- qh_fprintf(fp, 9071, "\n");
-} /* printcenter */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printcentrum">-</a>
-
- qh_printcentrum( fp, facet, radius )
- print centrum for a facet in OOGL format
- radius defines size of centrum
- 2-d or 3-d only
-
- returns:
- defines facet->center if needed
-*/
-void qh_printcentrum(FILE *fp, facetT *facet, realT radius) {
- pointT *centrum, *projpt;
- boolT tempcentrum= False;
- realT xaxis[4], yaxis[4], normal[4], dist;
- realT green[3]={0, 1, 0};
- vertexT *apex;
- int k;
-
- if (qh CENTERtype == qh_AScentrum) {
- if (!facet->center)
- facet->center= qh_getcentrum(facet);
- centrum= facet->center;
- }else {
- centrum= qh_getcentrum(facet);
- tempcentrum= True;
- }
- qh_fprintf(fp, 9072, "{appearance {-normal -edge normscale 0} ");
- if (qh firstcentrum) {
- qh firstcentrum= False;
- qh_fprintf(fp, 9073, "{INST geom { define centrum CQUAD # f%d\n\
--0.3 -0.3 0.0001 0 0 1 1\n\
- 0.3 -0.3 0.0001 0 0 1 1\n\
- 0.3 0.3 0.0001 0 0 1 1\n\
--0.3 0.3 0.0001 0 0 1 1 } transform { \n", facet->id);
- }else
- qh_fprintf(fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
- apex= SETfirstt_(facet->vertices, vertexT);
- qh_distplane(apex->point, facet, &dist);
- projpt= qh_projectpoint(apex->point, facet, dist);
- for (k=qh hull_dim; k--; ) {
- xaxis[k]= projpt[k] - centrum[k];
- normal[k]= facet->normal[k];
- }
- if (qh hull_dim == 2) {
- xaxis[2]= 0;
- normal[2]= 0;
- }else if (qh hull_dim == 4) {
- qh_projectdim3 (xaxis, xaxis);
- qh_projectdim3 (normal, normal);
- qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
- }
- qh_crossproduct(3, xaxis, normal, yaxis);
- qh_fprintf(fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
- qh_fprintf(fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
- qh_fprintf(fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
- qh_printpoint3 (fp, centrum);
- qh_fprintf(fp, 9078, "1 }}}\n");
- qh_memfree(projpt, qh normal_size);
- qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green);
- if (tempcentrum)
- qh_memfree(centrum, qh normal_size);
-} /* printcentrum */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printend">-</a>
-
- qh_printend( fp, format )
- prints trailer for all output formats
-
- see:
- qh_printbegin() and qh_printafacet()
-
-*/
-void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
- int num;
- facetT *facet, **facetp;
-
- if (!qh printoutnum)
- qh_fprintf(qh ferr, 7055, "qhull warning: no facets printed\n");
- switch (format) {
- case qh_PRINTgeom:
- if (qh hull_dim == 4 && qh DROPdim < 0 && !qh PRINTnoplanes) {
- qh visit_id++;
- num= 0;
- FORALLfacet_(facetlist)
- qh_printend4geom(fp, facet,&num, printall);
- FOREACHfacet_(facets)
- qh_printend4geom(fp, facet, &num, printall);
- if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
- qh_fprintf(qh ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- }else
- qh_fprintf(fp, 9079, "}\n");
- break;
- case qh_PRINTinner:
- case qh_PRINTnormals:
- case qh_PRINTouter:
- if (qh CDDoutput)
- qh_fprintf(fp, 9080, "end\n");
- break;
- case qh_PRINTmaple:
- qh_fprintf(fp, 9081, "));\n");
- break;
- case qh_PRINTmathematica:
- qh_fprintf(fp, 9082, "}\n");
- break;
- case qh_PRINTpoints:
- if (qh CDDoutput)
- qh_fprintf(fp, 9083, "end\n");
- break;
- default:
- break;
- }
-} /* printend */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printend4geom">-</a>
-
- qh_printend4geom( fp, facet, numridges, printall )
- helper function for qh_printbegin/printend
-
- returns:
- number of printed ridges
-
- notes:
- just counts printed ridges if fp=NULL
- uses facet->visitid
- must agree with qh_printfacet4geom...
-
- design:
- computes color for facet from its normal
- prints each ridge of facet
-*/
-void qh_printend4geom(FILE *fp, facetT *facet, int *nump, boolT printall) {
- realT color[3];
- int i, num= *nump;
- facetT *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
-
- if (!printall && qh_skipfacet(facet))
- return;
- if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
- return;
- if (!facet->normal)
- return;
- if (fp) {
- for (i=0; i < 3; i++) {
- color[i]= (facet->normal[i]+1.0)/2.0;
- maximize_(color[i], -1.0);
- minimize_(color[i], +1.0);
- }
- }
- facet->visitid= qh visit_id;
- if (facet->simplicial) {
- FOREACHneighbor_(facet) {
- if (neighbor->visitid != qh visit_id) {
- if (fp)
- qh_fprintf(fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
- 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
- facet->id, neighbor->id);
- num++;
- }
- }
- }else {
- FOREACHridge_(facet->ridges) {
- neighbor= otherfacet_(ridge, facet);
- if (neighbor->visitid != qh visit_id) {
- if (fp)
- qh_fprintf(fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
- 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
- ridge->id, facet->id, neighbor->id);
- num++;
- }
- }
- }
- *nump= num;
-} /* printend4geom */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printextremes">-</a>
-
- qh_printextremes( fp, facetlist, facets, printall )
- print extreme points for convex hulls or halfspace intersections
-
- notes:
- #points, followed by ids, one per line
-
- sorted by id
- same order as qh_printpoints_out if no coplanar/interior points
-*/
-void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
- setT *vertices, *points;
- pointT *point;
- vertexT *vertex, **vertexp;
- int id;
- int numpoints=0, point_i, point_n;
- int allpoints= qh num_points + qh_setsize(qh other_points);
-
- points= qh_settemp(allpoints);
- qh_setzero(points, 0, allpoints);
- vertices= qh_facetvertices(facetlist, facets, printall);
- FOREACHvertex_(vertices) {
- id= qh_pointid(vertex->point);
- if (id >= 0) {
- SETelem_(points, id)= vertex->point;
- numpoints++;
- }
- }
- qh_settempfree(&vertices);
- qh_fprintf(fp, 9086, "%d\n", numpoints);
- FOREACHpoint_i_(points) {
- if (point)
- qh_fprintf(fp, 9087, "%d\n", point_i);
- }
- qh_settempfree(&points);
-} /* printextremes */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printextremes_2d">-</a>
-
- qh_printextremes_2d( fp, facetlist, facets, printall )
- prints point ids for facets in qh_ORIENTclock order
-
- notes:
- #points, followed by ids, one per line
- if facetlist/facets are disjoint than the output includes skips
- errors if facets form a loop
- does not print coplanar points
-*/
-void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
- int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
- setT *vertices;
- facetT *facet, *startfacet, *nextfacet;
- vertexT *vertexA, *vertexB;
-
- qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
- &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
- vertices= qh_facetvertices(facetlist, facets, printall);
- qh_fprintf(fp, 9088, "%d\n", qh_setsize(vertices));
- qh_settempfree(&vertices);
- if (!numfacets)
- return;
- facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
- qh vertex_visit++;
- qh visit_id++;
- do {
- if (facet->toporient ^ qh_ORIENTclock) {
- vertexA= SETfirstt_(facet->vertices, vertexT);
- vertexB= SETsecondt_(facet->vertices, vertexT);
- nextfacet= SETfirstt_(facet->neighbors, facetT);
- }else {
- vertexA= SETsecondt_(facet->vertices, vertexT);
- vertexB= SETfirstt_(facet->vertices, vertexT);
- nextfacet= SETsecondt_(facet->neighbors, facetT);
- }
- if (facet->visitid == qh visit_id) {
- qh_fprintf(qh ferr, 6218, "Qhull internal error (qh_printextremes_2d): loop in facet list. facet %d nextfacet %d\n",
- facet->id, nextfacet->id);
- qh_errexit2 (qh_ERRqhull, facet, nextfacet);
- }
- if (facet->visitid) {
- if (vertexA->visitid != qh vertex_visit) {
- vertexA->visitid= qh vertex_visit;
- qh_fprintf(fp, 9089, "%d\n", qh_pointid(vertexA->point));
- }
- if (vertexB->visitid != qh vertex_visit) {
- vertexB->visitid= qh vertex_visit;
- qh_fprintf(fp, 9090, "%d\n", qh_pointid(vertexB->point));
- }
- }
- facet->visitid= qh visit_id;
- facet= nextfacet;
- }while (facet && facet != startfacet);
-} /* printextremes_2d */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printextremes_d">-</a>
-
- qh_printextremes_d( fp, facetlist, facets, printall )
- print extreme points of input sites for Delaunay triangulations
-
- notes:
- #points, followed by ids, one per line
-
- unordered
-*/
-void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
- setT *vertices;
- vertexT *vertex, **vertexp;
- boolT upperseen, lowerseen;
- facetT *neighbor, **neighborp;
- int numpoints=0;
-
- vertices= qh_facetvertices(facetlist, facets, printall);
- qh_vertexneighbors();
- FOREACHvertex_(vertices) {
- upperseen= lowerseen= False;
- FOREACHneighbor_(vertex) {
- if (neighbor->upperdelaunay)
- upperseen= True;
- else
- lowerseen= True;
- }
- if (upperseen && lowerseen) {
- vertex->seen= True;
- numpoints++;
- }else
- vertex->seen= False;
- }
- qh_fprintf(fp, 9091, "%d\n", numpoints);
- FOREACHvertex_(vertices) {
- if (vertex->seen)
- qh_fprintf(fp, 9092, "%d\n", qh_pointid(vertex->point));
- }
- qh_settempfree(&vertices);
-} /* printextremes_d */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet">-</a>
-
- qh_printfacet( fp, facet )
- prints all fields of a facet to fp
-
- notes:
- ridges printed in neighbor order
-*/
-void qh_printfacet(FILE *fp, facetT *facet) {
-
- qh_printfacetheader(fp, facet);
- if (facet->ridges)
- qh_printfacetridges(fp, facet);
-} /* printfacet */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet2geom">-</a>
-
- qh_printfacet2geom( fp, facet, color )
- print facet as part of a 2-d VECT for Geomview
-
- notes:
- assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
- mindist is calculated within io.c. maxoutside is calculated elsewhere
- so a DISTround error may have occured.
-*/
-void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
- pointT *point0, *point1;
- realT mindist, innerplane, outerplane;
- int k;
-
- qh_facet2point(facet, &point0, &point1, &mindist);
- qh_geomplanes(facet, &outerplane, &innerplane);
- if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
- qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
- if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
- outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
- for (k=3; k--; )
- color[k]= 1.0 - color[k];
- qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
- }
- qh_memfree(point1, qh normal_size);
- qh_memfree(point0, qh normal_size);
-} /* printfacet2geom */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet2geom_points">-</a>
-
- qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
- prints a 2-d facet as a VECT with 2 points at some offset.
- The points are on the facet's plane.
-*/
-void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
- facetT *facet, realT offset, realT color[3]) {
- pointT *p1= point1, *p2= point2;
-
- qh_fprintf(fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
- if (offset != 0.0) {
- p1= qh_projectpoint(p1, facet, -offset);
- p2= qh_projectpoint(p2, facet, -offset);
- }
- qh_fprintf(fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
- p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
- if (offset != 0.0) {
- qh_memfree(p1, qh normal_size);
- qh_memfree(p2, qh normal_size);
- }
- qh_fprintf(fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printfacet2geom_points */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet2math">-</a>
-
- qh_printfacet2math( fp, facet, format, notfirst )
- print 2-d Maple or Mathematica output for a facet
- may be non-simplicial
-
- notes:
- use %16.8f since Mathematica 2.2 does not handle exponential format
- see qh_printfacet3math
-*/
-void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
- pointT *point0, *point1;
- realT mindist;
- const char *pointfmt;
-
- qh_facet2point(facet, &point0, &point1, &mindist);
- if (notfirst)
- qh_fprintf(fp, 9096, ",");
- if (format == qh_PRINTmaple)
- pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
- else
- pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
- qh_fprintf(fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
- qh_memfree(point1, qh normal_size);
- qh_memfree(point0, qh normal_size);
-} /* printfacet2math */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
-
- qh_printfacet3geom_nonsimplicial( fp, facet, color )
- print Geomview OFF for a 3-d nonsimplicial facet.
- if DOintersections, prints ridges to unvisited neighbors(qh visit_id)
-
- notes
- uses facet->visitid for intersections and ridges
-*/
-void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
- ridgeT *ridge, **ridgep;
- setT *projectedpoints, *vertices;
- vertexT *vertex, **vertexp, *vertexA, *vertexB;
- pointT *projpt, *point, **pointp;
- facetT *neighbor;
- realT dist, outerplane, innerplane;
- int cntvertices, k;
- realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-
- qh_geomplanes(facet, &outerplane, &innerplane);
- vertices= qh_facet3vertex(facet); /* oriented */
- cntvertices= qh_setsize(vertices);
- projectedpoints= qh_settemp(cntvertices);
- FOREACHvertex_(vertices) {
- zinc_(Zdistio);
- qh_distplane(vertex->point, facet, &dist);
- projpt= qh_projectpoint(vertex->point, facet, dist);
- qh_setappend(&projectedpoints, projpt);
- }
- if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
- qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
- if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
- outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
- for (k=3; k--; )
- color[k]= 1.0 - color[k];
- qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
- }
- FOREACHpoint_(projectedpoints)
- qh_memfree(point, qh normal_size);
- qh_settempfree(&projectedpoints);
- qh_settempfree(&vertices);
- if ((qh DOintersections || qh PRINTridges)
- && (!facet->visible || !qh NEWfacets)) {
- facet->visitid= qh visit_id;
- FOREACHridge_(facet->ridges) {
- neighbor= otherfacet_(ridge, facet);
- if (neighbor->visitid != qh visit_id) {
- if (qh DOintersections)
- qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
- if (qh PRINTridges) {
- vertexA= SETfirstt_(ridge->vertices, vertexT);
- vertexB= SETsecondt_(ridge->vertices, vertexT);
- qh_printline3geom(fp, vertexA->point, vertexB->point, green);
- }
- }
- }
- }
-} /* printfacet3geom_nonsimplicial */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet3geom_points">-</a>
-
- qh_printfacet3geom_points( fp, points, facet, offset )
- prints a 3-d facet as OFF Geomview object.
- offset is relative to the facet's hyperplane
- Facet is determined as a list of points
-*/
-void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
- int k, n= qh_setsize(points), i;
- pointT *point, **pointp;
- setT *printpoints;
-
- qh_fprintf(fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
- if (offset != 0.0) {
- printpoints= qh_settemp(n);
- FOREACHpoint_(points)
- qh_setappend(&printpoints, qh_projectpoint(point, facet, -offset));
- }else
- printpoints= points;
- FOREACHpoint_(printpoints) {
- for (k=0; k < qh hull_dim; k++) {
- if (k == qh DROPdim)
- qh_fprintf(fp, 9099, "0 ");
- else
- qh_fprintf(fp, 9100, "%8.4g ", point[k]);
- }
- if (printpoints != points)
- qh_memfree(point, qh normal_size);
- qh_fprintf(fp, 9101, "\n");
- }
- if (printpoints != points)
- qh_settempfree(&printpoints);
- qh_fprintf(fp, 9102, "%d ", n);
- for (i=0; i < n; i++)
- qh_fprintf(fp, 9103, "%d ", i);
- qh_fprintf(fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
-} /* printfacet3geom_points */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
-
- qh_printfacet3geom_simplicial( )
- print Geomview OFF for a 3-d simplicial facet.
-
- notes:
- may flip color
- uses facet->visitid for intersections and ridges
-
- assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
- innerplane may be off by qh DISTround. Maxoutside is calculated elsewhere
- so a DISTround error may have occured.
-*/
-void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
- setT *points, *vertices;
- vertexT *vertex, **vertexp, *vertexA, *vertexB;
- facetT *neighbor, **neighborp;
- realT outerplane, innerplane;
- realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
- int k;
-
- qh_geomplanes(facet, &outerplane, &innerplane);
- vertices= qh_facet3vertex(facet);
- points= qh_settemp(qh TEMPsize);
- FOREACHvertex_(vertices)
- qh_setappend(&points, vertex->point);
- if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
- qh_printfacet3geom_points(fp, points, facet, outerplane, color);
- if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
- outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
- for (k=3; k--; )
- color[k]= 1.0 - color[k];
- qh_printfacet3geom_points(fp, points, facet, innerplane, color);
- }
- qh_settempfree(&points);
- qh_settempfree(&vertices);
- if ((qh DOintersections || qh PRINTridges)
- && (!facet->visible || !qh NEWfacets)) {
- facet->visitid= qh visit_id;
- FOREACHneighbor_(facet) {
- if (neighbor->visitid != qh visit_id) {
- vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
- SETindex_(facet->neighbors, neighbor), 0);
- if (qh DOintersections)
- qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
- if (qh PRINTridges) {
- vertexA= SETfirstt_(vertices, vertexT);
- vertexB= SETsecondt_(vertices, vertexT);
- qh_printline3geom(fp, vertexA->point, vertexB->point, green);
- }
- qh_setfree(&vertices);
- }
- }
- }
-} /* printfacet3geom_simplicial */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet3math">-</a>
-
- qh_printfacet3math( fp, facet, notfirst )
- print 3-d Maple or Mathematica output for a facet
-
- notes:
- may be non-simplicial
- use %16.8f since Mathematica 2.2 does not handle exponential format
- see qh_printfacet2math
-*/
-void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
- vertexT *vertex, **vertexp;
- setT *points, *vertices;
- pointT *point, **pointp;
- boolT firstpoint= True;
- realT dist;
- const char *pointfmt, *endfmt;
-
- if (notfirst)
- qh_fprintf(fp, 9105, ",\n");
- vertices= qh_facet3vertex(facet);
- points= qh_settemp(qh_setsize(vertices));
- FOREACHvertex_(vertices) {
- zinc_(Zdistio);
- qh_distplane(vertex->point, facet, &dist);
- point= qh_projectpoint(vertex->point, facet, dist);
- qh_setappend(&points, point);
- }
- if (format == qh_PRINTmaple) {
- qh_fprintf(fp, 9106, "[");
- pointfmt= "[%16.8f, %16.8f, %16.8f]";
- endfmt= "]";
- }else {
- qh_fprintf(fp, 9107, "Polygon[{");
- pointfmt= "{%16.8f, %16.8f, %16.8f}";
- endfmt= "}]";
- }
- FOREACHpoint_(points) {
- if (firstpoint)
- firstpoint= False;
- else
- qh_fprintf(fp, 9108, ",\n");
- qh_fprintf(fp, 9109, pointfmt, point[0], point[1], point[2]);
- }
- FOREACHpoint_(points)
- qh_memfree(point, qh normal_size);
- qh_settempfree(&points);
- qh_settempfree(&vertices);
- qh_fprintf(fp, 9110, endfmt);
-} /* printfacet3math */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet3vertex">-</a>
-
- qh_printfacet3vertex( fp, facet, format )
- print vertices in a 3-d facet as point ids
-
- notes:
- prints number of vertices first if format == qh_PRINToff
- the facet may be non-simplicial
-*/
-void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format) {
- vertexT *vertex, **vertexp;
- setT *vertices;
-
- vertices= qh_facet3vertex(facet);
- if (format == qh_PRINToff)
- qh_fprintf(fp, 9111, "%d ", qh_setsize(vertices));
- FOREACHvertex_(vertices)
- qh_fprintf(fp, 9112, "%d ", qh_pointid(vertex->point));
- qh_fprintf(fp, 9113, "\n");
- qh_settempfree(&vertices);
-} /* printfacet3vertex */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
-
- qh_printfacet4geom_nonsimplicial( )
- print Geomview 4OFF file for a 4d nonsimplicial facet
- prints all ridges to unvisited neighbors (qh.visit_id)
- if qh.DROPdim
- prints in OFF format
-
- notes:
- must agree with printend4geom()
-*/
-void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
- facetT *neighbor;
- ridgeT *ridge, **ridgep;
- vertexT *vertex, **vertexp;
- pointT *point;
- int k;
- realT dist;
-
- facet->visitid= qh visit_id;
- if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
- return;
- FOREACHridge_(facet->ridges) {
- neighbor= otherfacet_(ridge, facet);
- if (neighbor->visitid == qh visit_id)
- continue;
- if (qh PRINTtransparent && !neighbor->good)
- continue;
- if (qh DOintersections)
- qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
- else {
- if (qh DROPdim >= 0)
- qh_fprintf(fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
- else {
- qh printoutvar++;
- qh_fprintf(fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
- }
- FOREACHvertex_(ridge->vertices) {
- zinc_(Zdistio);
- qh_distplane(vertex->point,facet, &dist);
- point=qh_projectpoint(vertex->point,facet, dist);
- for (k=0; k < qh hull_dim; k++) {
- if (k != qh DROPdim)
- qh_fprintf(fp, 9116, "%8.4g ", point[k]);
- }
- qh_fprintf(fp, 9117, "\n");
- qh_memfree(point, qh normal_size);
- }
- if (qh DROPdim >= 0)
- qh_fprintf(fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
- }
- }
-} /* printfacet4geom_nonsimplicial */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
-
- qh_printfacet4geom_simplicial( fp, facet, color )
- print Geomview 4OFF file for a 4d simplicial facet
- prints triangles for unvisited neighbors (qh.visit_id)
-
- notes:
- must agree with printend4geom()
-*/
-void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
- setT *vertices;
- facetT *neighbor, **neighborp;
- vertexT *vertex, **vertexp;
- int k;
-
- facet->visitid= qh visit_id;
- if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
- return;
- FOREACHneighbor_(facet) {
- if (neighbor->visitid == qh visit_id)
- continue;
- if (qh PRINTtransparent && !neighbor->good)
- continue;
- vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
- SETindex_(facet->neighbors, neighbor), 0);
- if (qh DOintersections)
- qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
- else {
- if (qh DROPdim >= 0)
- qh_fprintf(fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
- facet->id, neighbor->id);
- else {
- qh printoutvar++;
- qh_fprintf(fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
- }
- FOREACHvertex_(vertices) {
- for (k=0; k < qh hull_dim; k++) {
- if (k != qh DROPdim)
- qh_fprintf(fp, 9121, "%8.4g ", vertex->point[k]);
- }
- qh_fprintf(fp, 9122, "\n");
- }
- if (qh DROPdim >= 0)
- qh_fprintf(fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
- }
- qh_setfree(&vertices);
- }
-} /* printfacet4geom_simplicial */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
-
- qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
- print vertices for an N-d non-simplicial facet
- triangulates each ridge to the id
-*/
-void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format) {
- vertexT *vertex, **vertexp;
- ridgeT *ridge, **ridgep;
-
- if (facet->visible && qh NEWfacets)
- return;
- FOREACHridge_(facet->ridges) {
- if (format == qh_PRINTtriangles)
- qh_fprintf(fp, 9124, "%d ", qh hull_dim);
- qh_fprintf(fp, 9125, "%d ", id);
- if ((ridge->top == facet) ^ qh_ORIENTclock) {
- FOREACHvertex_(ridge->vertices)
- qh_fprintf(fp, 9126, "%d ", qh_pointid(vertex->point));
- }else {
- FOREACHvertexreverse12_(ridge->vertices)
- qh_fprintf(fp, 9127, "%d ", qh_pointid(vertex->point));
- }
- qh_fprintf(fp, 9128, "\n");
- }
-} /* printfacetNvertex_nonsimplicial */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
-
- qh_printfacetNvertex_simplicial( fp, facet, format )
- print vertices for an N-d simplicial facet
- prints vertices for non-simplicial facets
- 2-d facets (orientation preserved by qh_mergefacet2d)
- PRINToff ('o') for 4-d and higher
-*/
-void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format) {
- vertexT *vertex, **vertexp;
-
- if (format == qh_PRINToff || format == qh_PRINTtriangles)
- qh_fprintf(fp, 9129, "%d ", qh_setsize(facet->vertices));
- if ((facet->toporient ^ qh_ORIENTclock)
- || (qh hull_dim > 2 && !facet->simplicial)) {
- FOREACHvertex_(facet->vertices)
- qh_fprintf(fp, 9130, "%d ", qh_pointid(vertex->point));
- }else {
- FOREACHvertexreverse12_(facet->vertices)
- qh_fprintf(fp, 9131, "%d ", qh_pointid(vertex->point));
- }
- qh_fprintf(fp, 9132, "\n");
-} /* printfacetNvertex_simplicial */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacetheader">-</a>
-
- qh_printfacetheader( fp, facet )
- prints header fields of a facet to fp
-
- notes:
- for 'f' output and debugging
- Same as QhullFacet::printHeader()
-*/
-void qh_printfacetheader(FILE *fp, facetT *facet) {
- pointT *point, **pointp, *furthest;
- facetT *neighbor, **neighborp;
- realT dist;
-
- if (facet == qh_MERGEridge) {
- qh_fprintf(fp, 9133, " MERGEridge\n");
- return;
- }else if (facet == qh_DUPLICATEridge) {
- qh_fprintf(fp, 9134, " DUPLICATEridge\n");
- return;
- }else if (!facet) {
- qh_fprintf(fp, 9135, " NULLfacet\n");
- return;
- }
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- qh_fprintf(fp, 9136, "- f%d\n", facet->id);
- qh_fprintf(fp, 9137, " - flags:");
- if (facet->toporient)
- qh_fprintf(fp, 9138, " top");
- else
- qh_fprintf(fp, 9139, " bottom");
- if (facet->simplicial)
- qh_fprintf(fp, 9140, " simplicial");
- if (facet->tricoplanar)
- qh_fprintf(fp, 9141, " tricoplanar");
- if (facet->upperdelaunay)
- qh_fprintf(fp, 9142, " upperDelaunay");
- if (facet->visible)
- qh_fprintf(fp, 9143, " visible");
- if (facet->newfacet)
- qh_fprintf(fp, 9144, " new");
- if (facet->tested)
- qh_fprintf(fp, 9145, " tested");
- if (!facet->good)
- qh_fprintf(fp, 9146, " notG");
- if (facet->seen)
- qh_fprintf(fp, 9147, " seen");
- if (facet->coplanar)
- qh_fprintf(fp, 9148, " coplanar");
- if (facet->mergehorizon)
- qh_fprintf(fp, 9149, " mergehorizon");
- if (facet->keepcentrum)
- qh_fprintf(fp, 9150, " keepcentrum");
- if (facet->dupridge)
- qh_fprintf(fp, 9151, " dupridge");
- if (facet->mergeridge && !facet->mergeridge2)
- qh_fprintf(fp, 9152, " mergeridge1");
- if (facet->mergeridge2)
- qh_fprintf(fp, 9153, " mergeridge2");
- if (facet->newmerge)
- qh_fprintf(fp, 9154, " newmerge");
- if (facet->flipped)
- qh_fprintf(fp, 9155, " flipped");
- if (facet->notfurthest)
- qh_fprintf(fp, 9156, " notfurthest");
- if (facet->degenerate)
- qh_fprintf(fp, 9157, " degenerate");
- if (facet->redundant)
- qh_fprintf(fp, 9158, " redundant");
- qh_fprintf(fp, 9159, "\n");
- if (facet->isarea)
- qh_fprintf(fp, 9160, " - area: %2.2g\n", facet->f.area);
- else if (qh NEWfacets && facet->visible && facet->f.replace)
- qh_fprintf(fp, 9161, " - replacement: f%d\n", facet->f.replace->id);
- else if (facet->newfacet) {
- if (facet->f.samecycle && facet->f.samecycle != facet)
- qh_fprintf(fp, 9162, " - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
- }else if (facet->tricoplanar /* !isarea */) {
- if (facet->f.triowner)
- qh_fprintf(fp, 9163, " - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
- }else if (facet->f.newcycle)
- qh_fprintf(fp, 9164, " - was horizon to f%d\n", facet->f.newcycle->id);
- if (facet->nummerge)
- qh_fprintf(fp, 9165, " - merges: %d\n", facet->nummerge);
- qh_printpointid(fp, " - normal: ", qh hull_dim, facet->normal, -1);
- qh_fprintf(fp, 9166, " - offset: %10.7g\n", facet->offset);
- if (qh CENTERtype == qh_ASvoronoi || facet->center)
- qh_printcenter(fp, qh_PRINTfacets, " - center: ", facet);
-#if qh_MAXoutside
- if (facet->maxoutside > qh DISTround)
- qh_fprintf(fp, 9167, " - maxoutside: %10.7g\n", facet->maxoutside);
-#endif
- if (!SETempty_(facet->outsideset)) {
- furthest= (pointT*)qh_setlast(facet->outsideset);
- if (qh_setsize(facet->outsideset) < 6) {
- qh_fprintf(fp, 9168, " - outside set(furthest p%d):\n", qh_pointid(furthest));
- FOREACHpoint_(facet->outsideset)
- qh_printpoint(fp, " ", point);
- }else if (qh_setsize(facet->outsideset) < 21) {
- qh_printpoints(fp, " - outside set:", facet->outsideset);
- }else {
- qh_fprintf(fp, 9169, " - outside set: %d points.", qh_setsize(facet->outsideset));
- qh_printpoint(fp, " Furthest", furthest);
- }
-#if !qh_COMPUTEfurthest
- qh_fprintf(fp, 9170, " - furthest distance= %2.2g\n", facet->furthestdist);
-#endif
- }
- if (!SETempty_(facet->coplanarset)) {
- furthest= (pointT*)qh_setlast(facet->coplanarset);
- if (qh_setsize(facet->coplanarset) < 6) {
- qh_fprintf(fp, 9171, " - coplanar set(furthest p%d):\n", qh_pointid(furthest));
- FOREACHpoint_(facet->coplanarset)
- qh_printpoint(fp, " ", point);
- }else if (qh_setsize(facet->coplanarset) < 21) {
- qh_printpoints(fp, " - coplanar set:", facet->coplanarset);
- }else {
- qh_fprintf(fp, 9172, " - coplanar set: %d points.", qh_setsize(facet->coplanarset));
- qh_printpoint(fp, " Furthest", furthest);
- }
- zinc_(Zdistio);
- qh_distplane(furthest, facet, &dist);
- qh_fprintf(fp, 9173, " furthest distance= %2.2g\n", dist);
- }
- qh_printvertices(fp, " - vertices:", facet->vertices);
- qh_fprintf(fp, 9174, " - neighboring facets:");
- FOREACHneighbor_(facet) {
- if (neighbor == qh_MERGEridge)
- qh_fprintf(fp, 9175, " MERGE");
- else if (neighbor == qh_DUPLICATEridge)
- qh_fprintf(fp, 9176, " DUP");
- else
- qh_fprintf(fp, 9177, " f%d", neighbor->id);
- }
- qh_fprintf(fp, 9178, "\n");
- qh RANDOMdist= qh old_randomdist;
-} /* printfacetheader */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacetridges">-</a>
-
- qh_printfacetridges( fp, facet )
- prints ridges of a facet to fp
-
- notes:
- ridges printed in neighbor order
- assumes the ridges exist
- for 'f' output
- same as QhullFacet::printRidges
-*/
-void qh_printfacetridges(FILE *fp, facetT *facet) {
- facetT *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
- int numridges= 0;
-
-
- if (facet->visible && qh NEWfacets) {
- qh_fprintf(fp, 9179, " - ridges(ids may be garbage):");
- FOREACHridge_(facet->ridges)
- qh_fprintf(fp, 9180, " r%d", ridge->id);
- qh_fprintf(fp, 9181, "\n");
- }else {
- qh_fprintf(fp, 9182, " - ridges:\n");
- FOREACHridge_(facet->ridges)
- ridge->seen= False;
- if (qh hull_dim == 3) {
- ridge= SETfirstt_(facet->ridges, ridgeT);
- while (ridge && !ridge->seen) {
- ridge->seen= True;
- qh_printridge(fp, ridge);
- numridges++;
- ridge= qh_nextridge3d(ridge, facet, NULL);
- }
- }else {
- FOREACHneighbor_(facet) {
- FOREACHridge_(facet->ridges) {
- if (otherfacet_(ridge,facet) == neighbor) {
- ridge->seen= True;
- qh_printridge(fp, ridge);
- numridges++;
- }
- }
- }
- }
- if (numridges != qh_setsize(facet->ridges)) {
- qh_fprintf(fp, 9183, " - all ridges:");
- FOREACHridge_(facet->ridges)
- qh_fprintf(fp, 9184, " r%d", ridge->id);
- qh_fprintf(fp, 9185, "\n");
- }
- FOREACHridge_(facet->ridges) {
- if (!ridge->seen)
- qh_printridge(fp, ridge);
- }
- }
-} /* printfacetridges */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printfacets">-</a>
-
- qh_printfacets( fp, format, facetlist, facets, printall )
- prints facetlist and/or facet set in output format
-
- notes:
- also used for specialized formats ('FO' and summary)
- turns off 'Rn' option since want actual numbers
-*/
-void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
- int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
- facetT *facet, **facetp;
- setT *vertices;
- coordT *center;
- realT outerplane, innerplane;
-
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
- qh_fprintf(qh ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
- if (format == qh_PRINTnone)
- ; /* print nothing */
- else if (format == qh_PRINTaverage) {
- vertices= qh_facetvertices(facetlist, facets, printall);
- center= qh_getcenter(vertices);
- qh_fprintf(fp, 9186, "%d 1\n", qh hull_dim);
- qh_printpointid(fp, NULL, qh hull_dim, center, -1);
- qh_memfree(center, qh normal_size);
- qh_settempfree(&vertices);
- }else if (format == qh_PRINTextremes) {
- if (qh DELAUNAY)
- qh_printextremes_d(fp, facetlist, facets, printall);
- else if (qh hull_dim == 2)
- qh_printextremes_2d(fp, facetlist, facets, printall);
- else
- qh_printextremes(fp, facetlist, facets, printall);
- }else if (format == qh_PRINToptions)
- qh_fprintf(fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
- else if (format == qh_PRINTpoints && !qh VORONOI)
- qh_printpoints_out(fp, facetlist, facets, printall);
- else if (format == qh_PRINTqhull)
- qh_fprintf(fp, 9188, "%s | %s\n", qh rbox_command, qh qhull_command);
- else if (format == qh_PRINTsize) {
- qh_fprintf(fp, 9189, "0\n2 ");
- qh_fprintf(fp, 9190, qh_REAL_1, qh totarea);
- qh_fprintf(fp, 9191, qh_REAL_1, qh totvol);
- qh_fprintf(fp, 9192, "\n");
- }else if (format == qh_PRINTsummary) {
- qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
- &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
- vertices= qh_facetvertices(facetlist, facets, printall);
- qh_fprintf(fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
- qh num_points + qh_setsize(qh other_points),
- qh num_vertices, qh num_facets - qh num_visible,
- qh_setsize(vertices), numfacets, numcoplanars,
- numfacets - numsimplicial, zzval_(Zdelvertextot),
- numtricoplanars);
- qh_settempfree(&vertices);
- qh_outerinner(NULL, &outerplane, &innerplane);
- qh_fprintf(fp, 9194, qh_REAL_2n, outerplane, innerplane);
- }else if (format == qh_PRINTvneighbors)
- qh_printvneighbors(fp, facetlist, facets, printall);
- else if (qh VORONOI && format == qh_PRINToff)
- qh_printvoronoi(fp, format, facetlist, facets, printall);
- else if (qh VORONOI && format == qh_PRINTgeom) {
- qh_printbegin(fp, format, facetlist, facets, printall);
- qh_printvoronoi(fp, format, facetlist, facets, printall);
- qh_printend(fp, format, facetlist, facets, printall);
- }else if (qh VORONOI
- && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
- qh_printvdiagram(fp, format, facetlist, facets, printall);
- else {
- qh_printbegin(fp, format, facetlist, facets, printall);
- FORALLfacet_(facetlist)
- qh_printafacet(fp, format, facet, printall);
- FOREACHfacet_(facets)
- qh_printafacet(fp, format, facet, printall);
- qh_printend(fp, format, facetlist, facets, printall);
- }
- qh RANDOMdist= qh old_randomdist;
-} /* printfacets */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printhyperplaneintersection">-</a>
-
- qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
- print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
-*/
-void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
- setT *vertices, realT color[3]) {
- realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
- vertexT *vertex, **vertexp;
- int i, k;
- boolT nearzero1, nearzero2;
-
- costheta= qh_getangle(facet1->normal, facet2->normal);
- denominator= 1 - costheta * costheta;
- i= qh_setsize(vertices);
- if (qh hull_dim == 3)
- qh_fprintf(fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
- else if (qh hull_dim == 4 && qh DROPdim >= 0)
- qh_fprintf(fp, 9196, "OFF 3 1 1 ");
- else
- qh printoutvar++;
- qh_fprintf(fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
- mindenom= 1 / (10.0 * qh MAXabs_coord);
- FOREACHvertex_(vertices) {
- zadd_(Zdistio, 2);
- qh_distplane(vertex->point, facet1, &dist1);
- qh_distplane(vertex->point, facet2, &dist2);
- s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
- t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
- if (nearzero1 || nearzero2)
- s= t= 0.0;
- for (k=qh hull_dim; k--; )
- p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
- if (qh PRINTdim <= 3) {
- qh_projectdim3 (p, p);
- qh_fprintf(fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
- }else
- qh_fprintf(fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
- if (nearzero1+nearzero2)
- qh_fprintf(fp, 9200, "p%d(coplanar facets)\n", qh_pointid(vertex->point));
- else
- qh_fprintf(fp, 9201, "projected p%d\n", qh_pointid(vertex->point));
- }
- if (qh hull_dim == 3)
- qh_fprintf(fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
- else if (qh hull_dim == 4 && qh DROPdim >= 0)
- qh_fprintf(fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printhyperplaneintersection */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printline3geom">-</a>
-
- qh_printline3geom( fp, pointA, pointB, color )
- prints a line as a VECT
- prints 0's for qh.DROPdim
-
- notes:
- if pointA == pointB,
- it's a 1 point VECT
-*/
-void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
- int k;
- realT pA[4], pB[4];
-
- qh_projectdim3(pointA, pA);
- qh_projectdim3(pointB, pB);
- if ((fabs(pA[0] - pB[0]) > 1e-3) ||
- (fabs(pA[1] - pB[1]) > 1e-3) ||
- (fabs(pA[2] - pB[2]) > 1e-3)) {
- qh_fprintf(fp, 9204, "VECT 1 2 1 2 1\n");
- for (k=0; k < 3; k++)
- qh_fprintf(fp, 9205, "%8.4g ", pB[k]);
- qh_fprintf(fp, 9206, " # p%d\n", qh_pointid(pointB));
- }else
- qh_fprintf(fp, 9207, "VECT 1 1 1 1 1\n");
- for (k=0; k < 3; k++)
- qh_fprintf(fp, 9208, "%8.4g ", pA[k]);
- qh_fprintf(fp, 9209, " # p%d\n", qh_pointid(pointA));
- qh_fprintf(fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
-}
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printneighborhood">-</a>
-
- qh_printneighborhood( fp, format, facetA, facetB, printall )
- print neighborhood of one or two facets
-
- notes:
- calls qh_findgood_all()
- bumps qh.visit_id
-*/
-void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
- facetT *neighbor, **neighborp, *facet;
- setT *facets;
-
- if (format == qh_PRINTnone)
- return;
- qh_findgood_all(qh facet_list);
- if (facetA == facetB)
- facetB= NULL;
- facets= qh_settemp(2*(qh_setsize(facetA->neighbors)+1));
- qh visit_id++;
- for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
- if (facet->visitid != qh visit_id) {
- facet->visitid= qh visit_id;
- qh_setappend(&facets, facet);
- }
- FOREACHneighbor_(facet) {
- if (neighbor->visitid == qh visit_id)
- continue;
- neighbor->visitid= qh visit_id;
- if (printall || !qh_skipfacet(neighbor))
- qh_setappend(&facets, neighbor);
- }
- }
- qh_printfacets(fp, format, NULL, facets, printall);
- qh_settempfree(&facets);
-} /* printneighborhood */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printpoint">-</a>
-
- qh_printpoint( fp, string, point )
- qh_printpointid( fp, string, dim, point, id )
- prints the coordinates of a point
-
- returns:
- if string is defined
- prints 'string p%d' (skips p%d if id=-1)
-
- notes:
- nop if point is NULL
- prints id unless it is undefined (-1)
- Same as QhullPoint's printPoint
-*/
-void qh_printpoint(FILE *fp, const char *string, pointT *point) {
- int id= qh_pointid( point);
-
- qh_printpointid( fp, string, qh hull_dim, point, id);
-} /* printpoint */
-
-void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id) {
- int k;
- realT r; /*bug fix*/
-
- if (!point)
- return;
- if (string) {
- qh_fprintf(fp, 9211, "%s", string);
- if (id != -1)
- qh_fprintf(fp, 9212, " p%d: ", id);
- }
- for (k=dim; k--; ) {
- r= *point++;
- if (string)
- qh_fprintf(fp, 9213, " %8.4g", r);
- else
- qh_fprintf(fp, 9214, qh_REAL_1, r);
- }
- qh_fprintf(fp, 9215, "\n");
-} /* printpointid */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printpoint3">-</a>
-
- qh_printpoint3( fp, point )
- prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
-*/
-void qh_printpoint3 (FILE *fp, pointT *point) {
- int k;
- realT p[4];
-
- qh_projectdim3 (point, p);
- for (k=0; k < 3; k++)
- qh_fprintf(fp, 9216, "%8.4g ", p[k]);
- qh_fprintf(fp, 9217, " # p%d\n", qh_pointid(point));
-} /* printpoint3 */
-
-/*----------------------------------------
--printpoints- print pointids for a set of points starting at index
- see geom.c
-*/
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printpoints_out">-</a>
-
- qh_printpoints_out( fp, facetlist, facets, printall )
- prints vertices, coplanar/inside points, for facets by their point coordinates
- allows qh.CDDoutput
-
- notes:
- same format as qhull input
- if no coplanar/interior points,
- same order as qh_printextremes
-*/
-void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
- int allpoints= qh num_points + qh_setsize(qh other_points);
- int numpoints=0, point_i, point_n;
- setT *vertices, *points;
- facetT *facet, **facetp;
- pointT *point, **pointp;
- vertexT *vertex, **vertexp;
- int id;
-
- points= qh_settemp(allpoints);
- qh_setzero(points, 0, allpoints);
- vertices= qh_facetvertices(facetlist, facets, printall);
- FOREACHvertex_(vertices) {
- id= qh_pointid(vertex->point);
- if (id >= 0)
- SETelem_(points, id)= vertex->point;
- }
- if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
- FORALLfacet_(facetlist) {
- if (!printall && qh_skipfacet(facet))
- continue;
- FOREACHpoint_(facet->coplanarset) {
- id= qh_pointid(point);
- if (id >= 0)
- SETelem_(points, id)= point;
- }
- }
- FOREACHfacet_(facets) {
- if (!printall && qh_skipfacet(facet))
- continue;
- FOREACHpoint_(facet->coplanarset) {
- id= qh_pointid(point);
- if (id >= 0)
- SETelem_(points, id)= point;
- }
- }
- }
- qh_settempfree(&vertices);
- FOREACHpoint_i_(points) {
- if (point)
- numpoints++;
- }
- if (qh CDDoutput)
- qh_fprintf(fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
- qh qhull_command, numpoints, qh hull_dim + 1);
- else
- qh_fprintf(fp, 9219, "%d\n%d\n", qh hull_dim, numpoints);
- FOREACHpoint_i_(points) {
- if (point) {
- if (qh CDDoutput)
- qh_fprintf(fp, 9220, "1 ");
- qh_printpoint(fp, NULL, point);
- }
- }
- if (qh CDDoutput)
- qh_fprintf(fp, 9221, "end\n");
- qh_settempfree(&points);
-} /* printpoints_out */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printpointvect">-</a>
-
- qh_printpointvect( fp, point, normal, center, radius, color )
- prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
-*/
-void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
- realT diff[4], pointA[4];
- int k;
-
- for (k=qh hull_dim; k--; ) {
- if (center)
- diff[k]= point[k]-center[k];
- else if (normal)
- diff[k]= normal[k];
- else
- diff[k]= 0;
- }
- if (center)
- qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
- for (k=qh hull_dim; k--; )
- pointA[k]= point[k]+diff[k] * radius;
- qh_printline3geom(fp, point, pointA, color);
-} /* printpointvect */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printpointvect2">-</a>
-
- qh_printpointvect2( fp, point, normal, center, radius )
- prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
-*/
-void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
- realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
-
- qh_printpointvect(fp, point, normal, center, radius, red);
- qh_printpointvect(fp, point, normal, center, -radius, yellow);
-} /* printpointvect2 */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printridge">-</a>
-
- qh_printridge( fp, ridge )
- prints the information in a ridge
-
- notes:
- for qh_printfacetridges()
- same as operator<< [QhullRidge.cpp]
-*/
-void qh_printridge(FILE *fp, ridgeT *ridge) {
-
- qh_fprintf(fp, 9222, " - r%d", ridge->id);
- if (ridge->tested)
- qh_fprintf(fp, 9223, " tested");
- if (ridge->nonconvex)
- qh_fprintf(fp, 9224, " nonconvex");
- qh_fprintf(fp, 9225, "\n");
- qh_printvertices(fp, " vertices:", ridge->vertices);
- if (ridge->top && ridge->bottom)
- qh_fprintf(fp, 9226, " between f%d and f%d\n",
- ridge->top->id, ridge->bottom->id);
-} /* printridge */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printspheres">-</a>
-
- qh_printspheres( fp, vertices, radius )
- prints 3-d vertices as OFF spheres
-
- notes:
- inflated octahedron from Stuart Levy earth/mksphere2
-*/
-void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
- vertexT *vertex, **vertexp;
-
- qh printoutnum++;
- qh_fprintf(fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
-INST geom {define vsphere OFF\n\
-18 32 48\n\
-\n\
-0 0 1\n\
-1 0 0\n\
-0 1 0\n\
--1 0 0\n\
-0 -1 0\n\
-0 0 -1\n\
-0.707107 0 0.707107\n\
-0 -0.707107 0.707107\n\
-0.707107 -0.707107 0\n\
--0.707107 0 0.707107\n\
--0.707107 -0.707107 0\n\
-0 0.707107 0.707107\n\
--0.707107 0.707107 0\n\
-0.707107 0.707107 0\n\
-0.707107 0 -0.707107\n\
-0 0.707107 -0.707107\n\
--0.707107 0 -0.707107\n\
-0 -0.707107 -0.707107\n\
-\n\
-3 0 6 11\n\
-3 0 7 6 \n\
-3 0 9 7 \n\
-3 0 11 9\n\
-3 1 6 8 \n\
-3 1 8 14\n\
-3 1 13 6\n\
-3 1 14 13\n\
-3 2 11 13\n\
-3 2 12 11\n\
-3 2 13 15\n\
-3 2 15 12\n\
-3 3 9 12\n\
-3 3 10 9\n\
-3 3 12 16\n\
-3 3 16 10\n\
-3 4 7 10\n\
-3 4 8 7\n\
-3 4 10 17\n\
-3 4 17 8\n\
-3 5 14 17\n\
-3 5 15 14\n\
-3 5 16 15\n\
-3 5 17 16\n\
-3 6 13 11\n\
-3 7 8 6\n\
-3 9 10 7\n\
-3 11 12 9\n\
-3 14 8 17\n\
-3 15 13 14\n\
-3 16 12 15\n\
-3 17 10 16\n} transforms { TLIST\n");
- FOREACHvertex_(vertices) {
- qh_fprintf(fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
- radius, vertex->id, radius, radius);
- qh_printpoint3 (fp, vertex->point);
- qh_fprintf(fp, 9229, "1\n");
- }
- qh_fprintf(fp, 9230, "}}}\n");
-} /* printspheres */
-
-
-/*----------------------------------------------
--printsummary-
- see libqhull.c
-*/
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvdiagram">-</a>
-
- qh_printvdiagram( fp, format, facetlist, facets, printall )
- print voronoi diagram
- # of pairs of input sites
- #indices site1 site2 vertex1 ...
-
- sites indexed by input point id
- point 0 is the first input point
- vertices indexed by 'o' and 'p' order
- vertex 0 is the 'vertex-at-infinity'
- vertex 1 is the first Voronoi vertex
-
- see:
- qh_printvoronoi()
- qh_eachvoronoi_all()
-
- notes:
- if all facets are upperdelaunay,
- prints upper hull (furthest-site Voronoi diagram)
-*/
-void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
- setT *vertices;
- int totcount, numcenters;
- boolT isLower;
- qh_RIDGE innerouter= qh_RIDGEall;
- printvridgeT printvridge= NULL;
-
- if (format == qh_PRINTvertices) {
- innerouter= qh_RIDGEall;
- printvridge= qh_printvridge;
- }else if (format == qh_PRINTinner) {
- innerouter= qh_RIDGEinner;
- printvridge= qh_printvnorm;
- }else if (format == qh_PRINTouter) {
- innerouter= qh_RIDGEouter;
- printvridge= qh_printvnorm;
- }else {
- qh_fprintf(qh ferr, 6219, "Qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
- totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
- qh_fprintf(fp, 9231, "%d\n", totcount);
- totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
- qh_settempfree(&vertices);
-#if 0 /* for testing qh_eachvoronoi_all */
- qh_fprintf(fp, 9232, "\n");
- totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
- qh_fprintf(fp, 9233, "%d\n", totcount);
-#endif
-} /* printvdiagram */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvdiagram2">-</a>
-
- qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
- visit all pairs of input sites (vertices) for selected Voronoi vertices
- vertices may include NULLs
-
- innerouter:
- qh_RIDGEall print inner ridges(bounded) and outer ridges(unbounded)
- qh_RIDGEinner print only inner ridges
- qh_RIDGEouter print only outer ridges
-
- inorder:
- print 3-d Voronoi vertices in order
-
- assumes:
- qh_markvoronoi marked facet->visitid for Voronoi vertices
- all facet->seen= False
- all facet->seen2= True
-
- returns:
- total number of Voronoi ridges
- if printvridge,
- calls printvridge( fp, vertex, vertexA, centers) for each ridge
- [see qh_eachvoronoi()]
-
- see:
- qh_eachvoronoi_all()
-*/
-int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
- int totcount= 0;
- int vertex_i, vertex_n;
- vertexT *vertex;
-
- FORALLvertices
- vertex->seen= False;
- FOREACHvertex_i_(vertices) {
- if (vertex) {
- if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
- continue;
- totcount += qh_eachvoronoi(fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
- }
- }
- return totcount;
-} /* printvdiagram2 */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvertex">-</a>
-
- qh_printvertex( fp, vertex )
- prints the information in a vertex
- Duplicated as operator<< [QhullVertex.cpp]
-*/
-void qh_printvertex(FILE *fp, vertexT *vertex) {
- pointT *point;
- int k, count= 0;
- facetT *neighbor, **neighborp;
- realT r; /*bug fix*/
-
- if (!vertex) {
- qh_fprintf(fp, 9234, " NULLvertex\n");
- return;
- }
- qh_fprintf(fp, 9235, "- p%d(v%d):", qh_pointid(vertex->point), vertex->id);
- point= vertex->point;
- if (point) {
- for (k=qh hull_dim; k--; ) {
- r= *point++;
- qh_fprintf(fp, 9236, " %5.2g", r);
- }
- }
- if (vertex->deleted)
- qh_fprintf(fp, 9237, " deleted");
- if (vertex->delridge)
- qh_fprintf(fp, 9238, " ridgedeleted");
- qh_fprintf(fp, 9239, "\n");
- if (vertex->neighbors) {
- qh_fprintf(fp, 9240, " neighbors:");
- FOREACHneighbor_(vertex) {
- if (++count % 100 == 0)
- qh_fprintf(fp, 9241, "\n ");
- qh_fprintf(fp, 9242, " f%d", neighbor->id);
- }
- qh_fprintf(fp, 9243, "\n");
- }
-} /* printvertex */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvertexlist">-</a>
-
- qh_printvertexlist( fp, string, facetlist, facets, printall )
- prints vertices used by a facetlist or facet set
- tests qh_skipfacet() if !printall
-*/
-void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
- setT *facets, boolT printall) {
- vertexT *vertex, **vertexp;
- setT *vertices;
-
- vertices= qh_facetvertices(facetlist, facets, printall);
- qh_fprintf(fp, 9244, "%s", string);
- FOREACHvertex_(vertices)
- qh_printvertex(fp, vertex);
- qh_settempfree(&vertices);
-} /* printvertexlist */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvertices">-</a>
-
- qh_printvertices( fp, string, vertices )
- prints vertices in a set
- duplicated as printVertexSet [QhullVertex.cpp]
-*/
-void qh_printvertices(FILE *fp, const char* string, setT *vertices) {
- vertexT *vertex, **vertexp;
-
- qh_fprintf(fp, 9245, "%s", string);
- FOREACHvertex_(vertices)
- qh_fprintf(fp, 9246, " p%d(v%d)", qh_pointid(vertex->point), vertex->id);
- qh_fprintf(fp, 9247, "\n");
-} /* printvertices */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvneighbors">-</a>
-
- qh_printvneighbors( fp, facetlist, facets, printall )
- print vertex neighbors of vertices in facetlist and facets ('FN')
-
- notes:
- qh_countfacets clears facet->visitid for non-printed facets
-
- design:
- collect facet count and related statistics
- if necessary, build neighbor sets for each vertex
- collect vertices in facetlist and facets
- build a point array for point->vertex and point->coplanar facet
- for each point
- list vertex neighbors or coplanar facet
-*/
-void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
- int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
- setT *vertices, *vertex_points, *coplanar_points;
- int numpoints= qh num_points + qh_setsize(qh other_points);
- vertexT *vertex, **vertexp;
- int vertex_i, vertex_n;
- facetT *facet, **facetp, *neighbor, **neighborp;
- pointT *point, **pointp;
-
- qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
- &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* sets facet->visitid */
- qh_fprintf(fp, 9248, "%d\n", numpoints);
- qh_vertexneighbors();
- vertices= qh_facetvertices(facetlist, facets, printall);
- vertex_points= qh_settemp(numpoints);
- coplanar_points= qh_settemp(numpoints);
- qh_setzero(vertex_points, 0, numpoints);
- qh_setzero(coplanar_points, 0, numpoints);
- FOREACHvertex_(vertices)
- qh_point_add(vertex_points, vertex->point, vertex);
- FORALLfacet_(facetlist) {
- FOREACHpoint_(facet->coplanarset)
- qh_point_add(coplanar_points, point, facet);
- }
- FOREACHfacet_(facets) {
- FOREACHpoint_(facet->coplanarset)
- qh_point_add(coplanar_points, point, facet);
- }
- FOREACHvertex_i_(vertex_points) {
- if (vertex) {
- numneighbors= qh_setsize(vertex->neighbors);
- qh_fprintf(fp, 9249, "%d", numneighbors);
- if (qh hull_dim == 3)
- qh_order_vertexneighbors(vertex);
- else if (qh hull_dim >= 4)
- qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
- sizeof(facetT *), qh_compare_facetvisit);
- FOREACHneighbor_(vertex)
- qh_fprintf(fp, 9250, " %d",
- neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
- qh_fprintf(fp, 9251, "\n");
- }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
- qh_fprintf(fp, 9252, "1 %d\n",
- facet->visitid ? facet->visitid - 1 : 0 - facet->id);
- else
- qh_fprintf(fp, 9253, "0\n");
- }
- qh_settempfree(&coplanar_points);
- qh_settempfree(&vertex_points);
- qh_settempfree(&vertices);
-} /* printvneighbors */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvoronoi">-</a>
-
- qh_printvoronoi( fp, format, facetlist, facets, printall )
- print voronoi diagram in 'o' or 'G' format
- for 'o' format
- prints voronoi centers for each facet and for infinity
- for each vertex, lists ids of printed facets or infinity
- assumes facetlist and facets are disjoint
- for 'G' format
- prints an OFF object
- adds a 0 coordinate to center
- prints infinity but does not list in vertices
-
- see:
- qh_printvdiagram()
-
- notes:
- if 'o',
- prints a line for each point except "at-infinity"
- if all facets are upperdelaunay,
- reverses lower and upper hull
-*/
-void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
- int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
- facetT *facet, **facetp, *neighbor, **neighborp;
- setT *vertices;
- vertexT *vertex;
- boolT isLower;
- unsigned int numfacets= (unsigned int) qh num_facets;
-
- vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
- FOREACHvertex_i_(vertices) {
- if (vertex) {
- numvertices++;
- numneighbors = numinf = 0;
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid == 0)
- numinf= 1;
- else if (neighbor->visitid < numfacets)
- numneighbors++;
- }
- if (numinf && !numneighbors) {
- SETelem_(vertices, vertex_i)= NULL;
- numvertices--;
- }
- }
- }
- if (format == qh_PRINTgeom)
- qh_fprintf(fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
- numcenters, numvertices);
- else
- qh_fprintf(fp, 9255, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
- if (format == qh_PRINTgeom) {
- for (k=qh hull_dim-1; k--; )
- qh_fprintf(fp, 9256, qh_REAL_1, 0.0);
- qh_fprintf(fp, 9257, " 0 # infinity not used\n");
- }else {
- for (k=qh hull_dim-1; k--; )
- qh_fprintf(fp, 9258, qh_REAL_1, qh_INFINITE);
- qh_fprintf(fp, 9259, "\n");
- }
- FORALLfacet_(facetlist) {
- if (facet->visitid && facet->visitid < numfacets) {
- if (format == qh_PRINTgeom)
- qh_fprintf(fp, 9260, "# %d f%d\n", vid++, facet->id);
- qh_printcenter(fp, format, NULL, facet);
- }
- }
- FOREACHfacet_(facets) {
- if (facet->visitid && facet->visitid < numfacets) {
- if (format == qh_PRINTgeom)
- qh_fprintf(fp, 9261, "# %d f%d\n", vid++, facet->id);
- qh_printcenter(fp, format, NULL, facet);
- }
- }
- FOREACHvertex_i_(vertices) {
- numneighbors= 0;
- numinf=0;
- if (vertex) {
- if (qh hull_dim == 3)
- qh_order_vertexneighbors(vertex);
- else if (qh hull_dim >= 4)
- qsort(SETaddr_(vertex->neighbors, facetT),
- (size_t)qh_setsize(vertex->neighbors),
- sizeof(facetT *), qh_compare_facetvisit);
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid == 0)
- numinf= 1;
- else if (neighbor->visitid < numfacets)
- numneighbors++;
- }
- }
- if (format == qh_PRINTgeom) {
- if (vertex) {
- qh_fprintf(fp, 9262, "%d", numneighbors);
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid && neighbor->visitid < numfacets)
- qh_fprintf(fp, 9263, " %d", neighbor->visitid);
- }
- qh_fprintf(fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
- }else
- qh_fprintf(fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
- }else {
- if (numinf)
- numneighbors++;
- qh_fprintf(fp, 9266, "%d", numneighbors);
- if (vertex) {
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid == 0) {
- if (numinf) {
- numinf= 0;
- qh_fprintf(fp, 9267, " %d", neighbor->visitid);
- }
- }else if (neighbor->visitid < numfacets)
- qh_fprintf(fp, 9268, " %d", neighbor->visitid);
- }
- }
- qh_fprintf(fp, 9269, "\n");
- }
- }
- if (format == qh_PRINTgeom)
- qh_fprintf(fp, 9270, "}\n");
- qh_settempfree(&vertices);
-} /* printvoronoi */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvnorm">-</a>
-
- qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
- print one separating plane of the Voronoi diagram for a pair of input sites
- unbounded==True if centers includes vertex-at-infinity
-
- assumes:
- qh_ASvoronoi and qh_vertexneighbors() already set
-
- note:
- parameter unbounded is UNUSED by this callback
-
- see:
- qh_printvdiagram()
- qh_eachvoronoi()
-*/
-void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
- pointT *normal;
- realT offset;
- int k;
- QHULL_UNUSED(unbounded);
-
- normal= qh_detvnorm(vertex, vertexA, centers, &offset);
- qh_fprintf(fp, 9271, "%d %d %d ",
- 2+qh hull_dim, qh_pointid(vertex->point), qh_pointid(vertexA->point));
- for (k=0; k< qh hull_dim-1; k++)
- qh_fprintf(fp, 9272, qh_REAL_1, normal[k]);
- qh_fprintf(fp, 9273, qh_REAL_1, offset);
- qh_fprintf(fp, 9274, "\n");
-} /* printvnorm */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printvridge">-</a>
-
- qh_printvridge( fp, vertex, vertexA, centers, unbounded )
- print one ridge of the Voronoi diagram for a pair of input sites
- unbounded==True if centers includes vertex-at-infinity
-
- see:
- qh_printvdiagram()
-
- notes:
- the user may use a different function
- parameter unbounded is UNUSED
-*/
-void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
- facetT *facet, **facetp;
- QHULL_UNUSED(unbounded);
-
- qh_fprintf(fp, 9275, "%d %d %d", qh_setsize(centers)+2,
- qh_pointid(vertex->point), qh_pointid(vertexA->point));
- FOREACHfacet_(centers)
- qh_fprintf(fp, 9276, " %d", facet->visitid);
- qh_fprintf(fp, 9277, "\n");
-} /* printvridge */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="projectdim3">-</a>
-
- qh_projectdim3( source, destination )
- project 2-d 3-d or 4-d point to a 3-d point
- uses qh.DROPdim and qh.hull_dim
- source and destination may be the same
-
- notes:
- allocate 4 elements to destination just in case
-*/
-void qh_projectdim3 (pointT *source, pointT *destination) {
- int i,k;
-
- for (k=0, i=0; k < qh hull_dim; k++) {
- if (qh hull_dim == 4) {
- if (k != qh DROPdim)
- destination[i++]= source[k];
- }else if (k == qh DROPdim)
- destination[i++]= 0;
- else
- destination[i++]= source[k];
- }
- while (i < 3)
- destination[i++]= 0.0;
-} /* projectdim3 */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="readfeasible">-</a>
-
- qh_readfeasible( dim, curline )
- read feasible point from current line and qh.fin
-
- returns:
- number of lines read from qh.fin
- sets qh.FEASIBLEpoint with malloc'd coordinates
-
- notes:
- checks for qh.HALFspace
- assumes dim > 1
-
- see:
- qh_setfeasible
-*/
-int qh_readfeasible(int dim, const char *curline) {
- boolT isfirst= True;
- int linecount= 0, tokcount= 0;
- const char *s;
- char *t, firstline[qh_MAXfirst+1];
- coordT *coords, value;
-
- if (!qh HALFspace) {
- qh_fprintf(qh ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh feasible_string)
- qh_fprintf(qh ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
- if (!(qh feasible_point= (coordT*)qh_malloc(dim* sizeof(coordT)))) {
- qh_fprintf(qh ferr, 6071, "qhull error: insufficient memory for feasible point\n");
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- coords= qh feasible_point;
- while ((s= (isfirst ? curline : fgets(firstline, qh_MAXfirst, qh fin)))) {
- if (isfirst)
- isfirst= False;
- else
- linecount++;
- while (*s) {
- while (isspace(*s))
- s++;
- value= qh_strtod(s, &t);
- if (s == t)
- break;
- s= t;
- *(coords++)= value;
- if (++tokcount == dim) {
- while (isspace(*s))
- s++;
- qh_strtod(s, &t);
- if (s != t) {
- qh_fprintf(qh ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
- s);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- return linecount;
- }
- }
- }
- qh_fprintf(qh ferr, 6073, "qhull input error: only %d coordinates. Could not read %d-d feasible point.\n",
- tokcount, dim);
- qh_errexit(qh_ERRinput, NULL, NULL);
- return 0;
-} /* readfeasible */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="readpoints">-</a>
-
- qh_readpoints( numpoints, dimension, ismalloc )
- read points from qh.fin into qh.first_point, qh.num_points
- qh.fin is lines of coordinates, one per vertex, first line number of points
- if 'rbox D4',
- gives message
- if qh.ATinfinity,
- adds point-at-infinity for Delaunay triangulations
-
- returns:
- number of points, array of point coordinates, dimension, ismalloc True
- if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
- and clears qh.PROJECTdelaunay
- if qh.HALFspace, reads optional feasible point, reads halfspaces,
- converts to dual.
-
- for feasible point in "cdd format" in 3-d:
- 3 1
- coordinates
- comments
- begin
- n 4 real/integer
- ...
- end
-
- notes:
- dimension will change in qh_initqhull_globals if qh.PROJECTinput
- uses malloc() since qh_mem not initialized
- FIXUP QH11012: qh_readpoints needs rewriting, too long
-*/
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
- coordT *points, *coords, *infinity= NULL;
- realT paraboloid, maxboloid= -REALmax, value;
- realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
- char *s= 0, *t, firstline[qh_MAXfirst+1];
- int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
- int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
- int tokcount= 0, linecount=0, maxcount, coordcount=0;
- boolT islong, isfirst= True, wasbegin= False;
- boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
-
- if (qh CDDinput) {
- while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
- linecount++;
- if (qh HALFspace && linecount == 1 && isdigit(*s)) {
- dimfeasible= qh_strtol(s, &s);
- while (isspace(*s))
- s++;
- if (qh_strtol(s, &s) == 1)
- linecount += qh_readfeasible(dimfeasible, s);
- else
- dimfeasible= 0;
- }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
- break;
- else if (!*qh rbox_command)
- strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
- }
- if (!s) {
- qh_fprintf(qh ferr, 6074, "qhull input error: missing \"begin\" for cdd-formated input\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- }
- while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
- linecount++;
- if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
- wasbegin= True;
- while (*s) {
- while (isspace(*s))
- s++;
- if (!*s)
- break;
- if (!isdigit(*s)) {
- if (!*qh rbox_command) {
- strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
- firsttext= linecount;
- }
- break;
- }
- if (!diminput)
- diminput= qh_strtol(s, &s);
- else {
- numinput= qh_strtol(s, &s);
- if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
- linecount += qh_readfeasible(diminput, s); /* checks if ok */
- dimfeasible= diminput;
- diminput= numinput= 0;
- }else
- break;
- }
- }
- }
- if (!s) {
- qh_fprintf(qh ferr, 6075, "qhull input error: short input file. Did not find dimension and number of points\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (diminput > numinput) {
- tempi= diminput; /* exchange dim and n, e.g., for cdd input format */
- diminput= numinput;
- numinput= tempi;
- }
- if (diminput < 2) {
- qh_fprintf(qh ferr, 6220,"qhull input error: dimension %d(first number) should be at least 2\n",
- diminput);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (isdelaunay) {
- qh PROJECTdelaunay= False;
- if (qh CDDinput)
- *dimension= diminput;
- else
- *dimension= diminput+1;
- *numpoints= numinput;
- if (qh ATinfinity)
- (*numpoints)++;
- }else if (qh HALFspace) {
- *dimension= diminput - 1;
- *numpoints= numinput;
- if (diminput < 3) {
- qh_fprintf(qh ferr, 6221,"qhull input error: dimension %d(first number, includes offset) should be at least 3 for halfspaces\n",
- diminput);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (dimfeasible) {
- if (dimfeasible != *dimension) {
- qh_fprintf(qh ferr, 6222,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
- dimfeasible, diminput);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- }else
- qh_setfeasible(*dimension);
- }else {
- if (qh CDDinput)
- *dimension= diminput-1;
- else
- *dimension= diminput;
- *numpoints= numinput;
- }
- qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
- if (qh HALFspace) {
- qh half_space= coordp= (coordT*)qh_malloc(qh normal_size + sizeof(coordT));
- if (qh CDDinput) {
- offsetp= qh half_space;
- normalp= offsetp + 1;
- }else {
- normalp= qh half_space;
- offsetp= normalp + *dimension;
- }
- }
- qh maxline= diminput * (qh_REALdigits + 5);
- maximize_(qh maxline, 500);
- qh line= (char*)qh_malloc((qh maxline+1) * sizeof(char));
- *ismalloc= True; /* use malloc since memory not setup */
- coords= points= qh temp_malloc=
- (coordT*)qh_malloc((*numpoints)*(*dimension)*sizeof(coordT));
- if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
- qh_fprintf(qh ferr, 6076, "qhull error: insufficient memory to read %d points\n",
- numinput);
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- if (isdelaunay && qh ATinfinity) {
- infinity= points + numinput * (*dimension);
- for (k= (*dimension) - 1; k--; )
- infinity[k]= 0.0;
- }
- maxcount= numinput * diminput;
- paraboloid= 0.0;
- while ((s= (isfirst ? s : fgets(qh line, qh maxline, qh fin)))) {
- if (!isfirst) {
- linecount++;
- if (*s == 'e' || *s == 'E') {
- if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
- if (qh CDDinput )
- break;
- else if (wasbegin)
- qh_fprintf(qh ferr, 7058, "qhull input warning: the input appears to be in cdd format. If so, use 'Fd'\n");
- }
- }
- }
- islong= False;
- while (*s) {
- while (isspace(*s))
- s++;
- value= qh_strtod(s, &t);
- if (s == t) {
- if (!*qh rbox_command)
- strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
- if (*s && !firsttext)
- firsttext= linecount;
- if (!islong && !firstshort && coordcount)
- firstshort= linecount;
- break;
- }
- if (!firstpoint)
- firstpoint= linecount;
- s= t;
- if (++tokcount > maxcount)
- continue;
- if (qh HALFspace) {
- if (qh CDDinput)
- *(coordp++)= -value; /* both coefficients and offset */
- else
- *(coordp++)= value;
- }else {
- *(coords++)= value;
- if (qh CDDinput && !coordcount) {
- if (value != 1.0) {
- qh_fprintf(qh ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
- linecount);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- coords--;
- }else if (isdelaunay) {
- paraboloid += value * value;
- if (qh ATinfinity) {
- if (qh CDDinput)
- infinity[coordcount-1] += value;
- else
- infinity[coordcount] += value;
- }
- }
- }
- if (++coordcount == diminput) {
- coordcount= 0;
- if (isdelaunay) {
- *(coords++)= paraboloid;
- maximize_(maxboloid, paraboloid);
- paraboloid= 0.0;
- }else if (qh HALFspace) {
- if (!qh_sethalfspace(*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
- qh_fprintf(qh ferr, 8048, "The halfspace was on line %d\n", linecount);
- if (wasbegin)
- qh_fprintf(qh ferr, 8049, "The input appears to be in cdd format. If so, you should use option 'Fd'\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- coordp= qh half_space;
- }
- while (isspace(*s))
- s++;
- if (*s) {
- islong= True;
- if (!firstlong)
- firstlong= linecount;
- }
- }
- }
- if (!islong && !firstshort && coordcount)
- firstshort= linecount;
- if (!isfirst && s - qh line >= qh maxline) {
- qh_fprintf(qh ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
- linecount, (int) (s - qh line)); /* WARN64 */
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- isfirst= False;
- }
- if (tokcount != maxcount) {
- newnum= fmin_(numinput, tokcount/diminput);
- qh_fprintf(qh ferr, 7073,"\
-qhull warning: instead of %d %d-dimensional points, input contains\n\
-%d points and %d extra coordinates. Line %d is the first\npoint",
- numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
- if (firsttext)
- qh_fprintf(qh ferr, 8051, ", line %d is the first comment", firsttext);
- if (firstshort)
- qh_fprintf(qh ferr, 8052, ", line %d is the first short\nline", firstshort);
- if (firstlong)
- qh_fprintf(qh ferr, 8053, ", line %d is the first long line", firstlong);
- qh_fprintf(qh ferr, 8054, ". Continue with %d points.\n", newnum);
- numinput= newnum;
- if (isdelaunay && qh ATinfinity) {
- for (k= tokcount % diminput; k--; )
- infinity[k] -= *(--coords);
- *numpoints= newnum+1;
- }else {
- coords -= tokcount % diminput;
- *numpoints= newnum;
- }
- }
- if (isdelaunay && qh ATinfinity) {
- for (k= (*dimension) -1; k--; )
- infinity[k] /= numinput;
- if (coords == infinity)
- coords += (*dimension) -1;
- else {
- for (k=0; k < (*dimension) -1; k++)
- *(coords++)= infinity[k];
- }
- *(coords++)= maxboloid * 1.1;
- }
- if (qh rbox_command[0]) {
- qh rbox_command[strlen(qh rbox_command)-1]= '\0';
- if (!strcmp(qh rbox_command, "./rbox D4"))
- qh_fprintf(qh ferr, 8055, "\n\
-This is the qhull test case. If any errors or core dumps occur,\n\
-recompile qhull with 'make new'. If errors still occur, there is\n\
-an incompatibility. You should try a different compiler. You can also\n\
-change the choices in user.h. If you discover the source of the problem,\n\
-please send mail to qhull_bug@qhull.org.\n\
-\n\
-Type 'qhull' for a short list of options.\n");
- }
- qh_free(qh line);
- qh line= NULL;
- if (qh half_space) {
- qh_free(qh half_space);
- qh half_space= NULL;
- }
- qh temp_malloc= NULL;
- trace1((qh ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
- numinput, diminput));
- return(points);
-} /* readpoints */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="setfeasible">-</a>
-
- qh_setfeasible( dim )
- set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
-
- notes:
- "n,n,n" already checked by qh_initflags()
- see qh_readfeasible()
-*/
-void qh_setfeasible(int dim) {
- int tokcount= 0;
- char *s;
- coordT *coords, value;
-
- if (!(s= qh feasible_string)) {
- qh_fprintf(qh ferr, 6223, "\
-qhull input error: halfspace intersection needs a feasible point.\n\
-Either prepend the input with 1 point or use 'Hn,n,n'. See manual.\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (!(qh feasible_point= (pointT*)qh_malloc(dim * sizeof(coordT)))) {
- qh_fprintf(qh ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
- qh_errexit(qh_ERRmem, NULL, NULL);
- }
- coords= qh feasible_point;
- while (*s) {
- value= qh_strtod(s, &s);
- if (++tokcount > dim) {
- qh_fprintf(qh ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
- qh feasible_string, dim);
- break;
- }
- *(coords++)= value;
- if (*s)
- s++;
- }
- while (++tokcount <= dim)
- *(coords++)= 0.0;
-} /* setfeasible */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="skipfacet">-</a>
-
- qh_skipfacet( facet )
- returns 'True' if this facet is not to be printed
-
- notes:
- based on the user provided slice thresholds and 'good' specifications
-*/
-boolT qh_skipfacet(facetT *facet) {
- facetT *neighbor, **neighborp;
-
- if (qh PRINTneighbors) {
- if (facet->good)
- return !qh PRINTgood;
- FOREACHneighbor_(facet) {
- if (neighbor->good)
- return False;
- }
- return True;
- }else if (qh PRINTgood)
- return !facet->good;
- else if (!facet->normal)
- return True;
- return(!qh_inthresholds(facet->normal, NULL));
-} /* skipfacet */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="skipfilename">-</a>
-
- qh_skipfilename( string )
- returns pointer to character after filename
-
- notes:
- skips leading spaces
- ends with spacing or eol
- if starts with ' or " ends with the same, skipping \' or \"
- For qhull, qh_argv_to_command() only uses double quotes
-*/
-char *qh_skipfilename(char *filename) {
- char *s= filename; /* non-const due to return */
- char c;
-
- while (*s && isspace(*s))
- s++;
- c= *s++;
- if (c == '\0') {
- qh_fprintf(qh ferr, 6204, "qhull input error: filename expected, none found.\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (c == '\'' || c == '"') {
- while (*s !=c || s[-1] == '\\') {
- if (!*s) {
- qh_fprintf(qh ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- s++;
- }
- s++;
- }
- else while (*s && !isspace(*s))
- s++;
- return s;
-} /* skipfilename */
-
diff --git a/PyMca/Object3D/Object3DQhull/src/io.h b/PyMca/Object3D/Object3DQhull/src/io.h
deleted file mode 100644
index 580d51b..0000000
--- a/PyMca/Object3D/Object3DQhull/src/io.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*<html><pre> -<a href="qh-io.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- io.h
- declarations of Input/Output functions
-
- see README, libqhull.h and io.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/io.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFio
-#define qhDEFio 1
-
-#include "libqhull.h"
-
-/*============ constants and flags ==================*/
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="qh_MAXfirst">-</a>
-
- qh_MAXfirst
- maximum length of first two lines of stdin
-*/
-#define qh_MAXfirst 200
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="qh_MINradius">-</a>
-
- qh_MINradius
- min radius for Gp and Gv, fraction of maxcoord
-*/
-#define qh_MINradius 0.02
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="qh_GEOMepsilon">-</a>
-
- qh_GEOMepsilon
- adjust outer planes for 'lines closer' and geomview roundoff.
- This prevents bleed through.
-*/
-#define qh_GEOMepsilon 2e-3
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="qh_WHITESPACE">-</a>
-
- qh_WHITESPACE
- possible values of white space
-*/
-#define qh_WHITESPACE " \n\t\v\r\f"
-
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="RIDGE">-</a>
-
- qh_RIDGE
- to select which ridges to print in qh_eachvoronoi
-*/
-typedef enum
-{
- qh_RIDGEall = 0, qh_RIDGEinner, qh_RIDGEouter
-}
-qh_RIDGE;
-
-/*-<a href="qh-io.htm#TOC"
- >--------------------------------</a><a name="printvridgeT">-</a>
-
- printvridgeT
- prints results of qh_printvdiagram
-
- see:
- <a href="io.c#printvridge">qh_printvridge</a> for an example
-*/
-typedef void (*printvridgeT)(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-
-/*============== -prototypes in alphabetical order =========*/
-
-void dfacet(unsigned id);
-void dvertex(unsigned id);
-int qh_compare_facetarea(const void *p1, const void *p2);
-int qh_compare_facetmerge(const void *p1, const void *p2);
-int qh_compare_facetvisit(const void *p1, const void *p2);
-int qh_compare_vertexpoint(const void *p1, const void *p2); /* not used */
-void qh_copyfilename(char *filename, int size, const char* source, int length);
-void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
- int *numfacetsp, int *numsimplicialp, int *totneighborsp,
- int *numridgesp, int *numcoplanarsp, int *numnumtricoplanarsp);
-pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp);
-setT *qh_detvridge(vertexT *vertex);
-setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex);
-int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder);
-int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder);
-void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist);
-setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
-void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane);
-void qh_markkeep(facetT *facetlist);
-setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp);
-void qh_order_vertexneighbors(vertexT *vertex);
-void qh_prepare_output(void);
-void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall);
-void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet);
-void qh_printcentrum(FILE *fp, facetT *facet, realT radius);
-void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void qh_printend4geom(FILE *fp, facetT *facet, int *num, boolT printall);
-void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void qh_printfacet(FILE *fp, facetT *facet);
-void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
-void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]);
-void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
- facetT *facet, realT offset, realT color[3]);
-void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst);
-void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]);
-void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format);
-void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]);
-void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]);
-void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format);
-void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format);
-void qh_printfacetheader(FILE *fp, facetT *facet);
-void qh_printfacetridges(FILE *fp, facetT *facet);
-void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
- setT *vertices, realT color[3]);
-void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
-void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]);
-void qh_printpoint(FILE *fp, const char *string, pointT *point);
-void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id);
-void qh_printpoint3 (FILE *fp, pointT *point);
-void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall);
-void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]);
-void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius);
-void qh_printridge(FILE *fp, ridgeT *ridge);
-void qh_printspheres(FILE *fp, setT *vertices, realT radius);
-void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder);
-void qh_printvertex(FILE *fp, vertexT *vertex);
-void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
- setT *facets, boolT printall);
-void qh_printvertices(FILE *fp, const char* string, setT *vertices);
-void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall);
-void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall);
-void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded);
-void qh_produce_output(void);
-void qh_produce_output2(void);
-void qh_projectdim3 (pointT *source, pointT *destination);
-int qh_readfeasible(int dim, const char *curline);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-void qh_setfeasible(int dim);
-boolT qh_skipfacet(facetT *facet);
-char *qh_skipfilename(char *filename);
-
-#endif /* qhDEFio */
diff --git a/PyMca/Object3D/Object3DQhull/src/libqhull.c b/PyMca/Object3D/Object3DQhull/src/libqhull.c
deleted file mode 100644
index a7d86ce..0000000
--- a/PyMca/Object3D/Object3DQhull/src/libqhull.c
+++ /dev/null
@@ -1,1401 +0,0 @@
-/*<html><pre> -<a href="qh-qhull.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- libqhull.c
- Quickhull algorithm for convex hulls
-
- qhull() and top-level routines
-
- see qh-qhull.htm, libqhull.h, unix.c
-
- see qhull_a.h for internal functions
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/libqhull.c#4 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*============= functions in alphabetic order after qhull() =======*/
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="qhull">-</a>
-
- qh_qhull()
- compute DIM3 convex hull of qh.num_points starting at qh.first_point
- qh contains all global options and variables
-
- returns:
- returns polyhedron
- qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices,
-
- returns global variables
- qh.hulltime, qh.max_outside, qh.interior_point, qh.max_vertex, qh.min_vertex
-
- returns precision constants
- qh.ANGLEround, centrum_radius, cos_max, DISTround, MAXabs_coord, ONEmerge
-
- notes:
- unless needed for output
- qh.max_vertex and qh.min_vertex are max/min due to merges
-
- see:
- to add individual points to either qh.num_points
- use qh_addpoint()
-
- if qh.GETarea
- qh_produceoutput() returns qh.totarea and qh.totvol via qh_getarea()
-
- design:
- record starting time
- initialize hull and partition points
- build convex hull
- unless early termination
- update facet->maxoutside for vertices, coplanar, and near-inside points
- error if temporary sets exist
- record end time
-*/
-
-void qh_qhull(void) {
- int numoutside;
-
- qh hulltime= qh_CPUclock;
- if (qh RERUN || qh JOGGLEmax < REALmax/2)
- qh_build_withrestart();
- else {
- qh_initbuild();
- qh_buildhull();
- }
- if (!qh STOPpoint && !qh STOPcone) {
- if (qh ZEROall_ok && !qh TESTvneighbors && qh MERGEexact)
- qh_checkzero( qh_ALL);
- if (qh ZEROall_ok && !qh TESTvneighbors && !qh WAScoplanar) {
- trace2((qh ferr, 2055, "qh_qhull: all facets are clearly convex and no coplanar points. Post-merging and check of maxout not needed.\n"));
- qh DOcheckmax= False;
- }else {
- if (qh MERGEexact || (qh hull_dim > qh_DIMreduceBuild && qh PREmerge))
- qh_postmerge("First post-merge", qh premerge_centrum, qh premerge_cos,
- (qh POSTmerge ? False : qh TESTvneighbors));
- else if (!qh POSTmerge && qh TESTvneighbors)
- qh_postmerge("For testing vertex neighbors", qh premerge_centrum,
- qh premerge_cos, True);
- if (qh POSTmerge)
- qh_postmerge("For post-merging", qh postmerge_centrum,
- qh postmerge_cos, qh TESTvneighbors);
- if (qh visible_list == qh facet_list) { /* i.e., merging done */
- qh findbestnew= True;
- qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numoutside);
- qh findbestnew= False;
- qh_deletevisible(/*qh visible_list*/);
- qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
- }
- }
- if (qh DOcheckmax){
- if (qh REPORTfreq) {
- qh_buildtracing(NULL, NULL);
- qh_fprintf(qh ferr, 8115, "\nTesting all coplanar points.\n");
- }
- qh_check_maxout();
- }
- if (qh KEEPnearinside && !qh maxoutdone)
- qh_nearcoplanar();
- }
- if (qh_setsize(qhmem.tempstack) != 0) {
- qh_fprintf(qh ferr, 6164, "qhull internal error (qh_qhull): temporary sets not empty(%d)\n",
- qh_setsize(qhmem.tempstack));
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh hulltime= qh_CPUclock - qh hulltime;
- qh QHULLfinished= True;
- trace1((qh ferr, 1036, "Qhull: algorithm completed\n"));
-} /* qhull */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="addpoint">-</a>
-
- qh_addpoint( furthest, facet, checkdist )
- add point (usually furthest point) above facet to hull
- if checkdist,
- check that point is above facet.
- if point is not outside of the hull, uses qh_partitioncoplanar()
- assumes that facet is defined by qh_findbestfacet()
- else if facet specified,
- assumes that point is above facet (major damage if below)
- for Delaunay triangulations,
- Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
- Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
- returns:
- returns False if user requested an early termination
- qh.visible_list, newfacet_list, delvertex_list, NEWfacets may be defined
- updates qh.facet_list, qh.num_facets, qh.vertex_list, qh.num_vertices
- clear qh.maxoutdone (will need to call qh_check_maxout() for facet->maxoutside)
- if unknown point, adds a pointer to qh.other_points
- do not deallocate the point's coordinates
-
- notes:
- assumes point is near its best facet and not at a local minimum of a lens
- distributions. Use qh_findbestfacet to avoid this case.
- uses qh.visible_list, qh.newfacet_list, qh.delvertex_list, qh.NEWfacets
-
- see also:
- qh_triangulate() -- triangulate non-simplicial facets
-
- design:
- add point to other_points if needed
- if checkdist
- if point not above facet
- partition coplanar point
- exit
- exit if pre STOPpoint requested
- find horizon and visible facets for point
- make new facets for point to horizon
- make hyperplanes for point
- compute balance statistics
- match neighboring new facets
- update vertex neighbors and delete interior vertices
- exit if STOPcone requested
- merge non-convex new facets
- if merge found, many merges, or 'Qf'
- use qh_findbestnew() instead of qh_findbest()
- partition outside points from visible facets
- delete visible facets
- check polyhedron if requested
- exit if post STOPpoint requested
- reset working lists of facets and vertices
-*/
-boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist) {
- int goodvisible, goodhorizon;
- vertexT *vertex;
- facetT *newfacet;
- realT dist, newbalance, pbalance;
- boolT isoutside= False;
- int numpart, numpoints, numnew, firstnew;
-
- qh maxoutdone= False;
- if (qh_pointid(furthest) == -1)
- qh_setappend(&qh other_points, furthest);
- if (!facet) {
- qh_fprintf(qh ferr, 6213, "qhull internal error (qh_addpoint): NULL facet. Need to call qh_findbestfacet first\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (checkdist) {
- facet= qh_findbest(furthest, facet, !qh_ALL, !qh_ISnewfacets, !qh_NOupper,
- &dist, &isoutside, &numpart);
- zzadd_(Zpartition, numpart);
- if (!isoutside) {
- zinc_(Znotmax); /* last point of outsideset is no longer furthest. */
- facet->notfurthest= True;
- qh_partitioncoplanar(furthest, facet, &dist);
- return True;
- }
- }
- qh_buildtracing(furthest, facet);
- if (qh STOPpoint < 0 && qh furthest_id == -qh STOPpoint-1) {
- facet->notfurthest= True;
- return False;
- }
- qh_findhorizon(furthest, facet, &goodvisible, &goodhorizon);
- if (qh ONLYgood && !(goodvisible+goodhorizon) && !qh GOODclosest) {
- zinc_(Znotgood);
- facet->notfurthest= True;
- /* last point of outsideset is no longer furthest. This is ok
- since all points of the outside are likely to be bad */
- qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
- return True;
- }
- zzinc_(Zprocessed);
- firstnew= qh facet_id;
- vertex= qh_makenewfacets(furthest /*visible_list, attaches if !ONLYgood */);
- qh_makenewplanes(/* newfacet_list */);
- numnew= qh facet_id - firstnew;
- newbalance= numnew - (realT) (qh num_facets-qh num_visible)
- * qh hull_dim/qh num_vertices;
- wadd_(Wnewbalance, newbalance);
- wadd_(Wnewbalance2, newbalance * newbalance);
- if (qh ONLYgood
- && !qh_findgood(qh newfacet_list, goodhorizon) && !qh GOODclosest) {
- FORALLnew_facets
- qh_delfacet(newfacet);
- qh_delvertex(vertex);
- qh_resetlists(True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
- zinc_(Znotgoodnew);
- facet->notfurthest= True;
- return True;
- }
- if (qh ONLYgood)
- qh_attachnewfacets(/*visible_list*/);
- qh_matchnewfacets();
- qh_updatevertices();
- if (qh STOPcone && qh furthest_id == qh STOPcone-1) {
- facet->notfurthest= True;
- return False; /* visible_list etc. still defined */
- }
- qh findbestnew= False;
- if (qh PREmerge || qh MERGEexact) {
- qh_premerge(vertex, qh premerge_centrum, qh premerge_cos);
- if (qh_USEfindbestnew)
- qh findbestnew= True;
- else {
- FORALLnew_facets {
- if (!newfacet->simplicial) {
- qh findbestnew= True; /* use qh_findbestnew instead of qh_findbest*/
- break;
- }
- }
- }
- }else if (qh BESToutside)
- qh findbestnew= True;
- qh_partitionvisible(/*visible_list, newfacet_list*/ !qh_ALL, &numpoints);
- qh findbestnew= False;
- qh findbest_notsharp= False;
- zinc_(Zpbalance);
- pbalance= numpoints - (realT) qh hull_dim /* assumes all points extreme */
- * (qh num_points - qh num_vertices)/qh num_vertices;
- wadd_(Wpbalance, pbalance);
- wadd_(Wpbalance2, pbalance * pbalance);
- qh_deletevisible(/*qh visible_list*/);
- zmax_(Zmaxvertex, qh num_vertices);
- qh NEWfacets= False;
- if (qh IStracing >= 4) {
- if (qh num_facets < 2000)
- qh_printlists();
- qh_printfacetlist(qh newfacet_list, NULL, True);
- qh_checkpolygon(qh facet_list);
- }else if (qh CHECKfrequently) {
- if (qh num_facets < 50)
- qh_checkpolygon(qh facet_list);
- else
- qh_checkpolygon(qh newfacet_list);
- }
- if (qh STOPpoint > 0 && qh furthest_id == qh STOPpoint-1)
- return False;
- qh_resetlists(True, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
- /* qh_triangulate(); to test qh.TRInormals */
- trace2((qh ferr, 2056, "qh_addpoint: added p%d new facets %d new balance %2.2g point balance %2.2g\n",
- qh_pointid(furthest), numnew, newbalance, pbalance));
- return True;
-} /* addpoint */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="build_withrestart">-</a>
-
- qh_build_withrestart()
- allow restarts due to qh.JOGGLEmax while calling qh_buildhull()
- qh.FIRSTpoint/qh.NUMpoints is point array
- it may be moved by qh_joggleinput()
-*/
-void qh_build_withrestart(void) {
- int restart;
-
- qh ALLOWrestart= True;
- while (True) {
- restart= setjmp(qh restartexit); /* simple statement for CRAY J916 */
- if (restart) { /* only from qh_precision() */
- zzinc_(Zretry);
- wmax_(Wretrymax, qh JOGGLEmax);
- /* QH7078 warns about using 'TCn' with 'QJn' */
- qh STOPcone= -1; /* if break from joggle, prevents normal output */
- }
- if (!qh RERUN && qh JOGGLEmax < REALmax/2) {
- if (qh build_cnt > qh_JOGGLEmaxretry) {
- qh_fprintf(qh ferr, 6229, "qhull precision error: %d attempts to construct a convex hull\n\
- with joggled input. Increase joggle above 'QJ%2.2g'\n\
- or modify qh_JOGGLE... parameters in user.h\n",
- qh build_cnt, qh JOGGLEmax);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (qh build_cnt && !restart)
- break;
- }else if (qh build_cnt && qh build_cnt >= qh RERUN)
- break;
- qh STOPcone= 0;
- qh_freebuild(True); /* first call is a nop */
- qh build_cnt++;
- if (!qh qhull_optionsiz)
- qh qhull_optionsiz= (int)strlen(qh qhull_options); /* WARN64 */
- else {
- qh qhull_options [qh qhull_optionsiz]= '\0';
- qh qhull_optionlen= qh_OPTIONline; /* starts a new line */
- }
- qh_option("_run", &qh build_cnt, NULL);
- if (qh build_cnt == qh RERUN) {
- qh IStracing= qh TRACElastrun; /* duplicated from qh_initqhull_globals */
- if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
- qh TRACElevel= (qh IStracing? qh IStracing : 3);
- qh IStracing= 0;
- }
- qhmem.IStracing= qh IStracing;
- }
- if (qh JOGGLEmax < REALmax/2)
- qh_joggleinput();
- qh_initbuild();
- qh_buildhull();
- if (qh JOGGLEmax < REALmax/2 && !qh MERGING)
- qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
- }
- qh ALLOWrestart= False;
-} /* qh_build_withrestart */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="buildhull">-</a>
-
- qh_buildhull()
- construct a convex hull by adding outside points one at a time
-
- returns:
-
- notes:
- may be called multiple times
- checks facet and vertex lists for incorrect flags
- to recover from STOPcone, call qh_deletevisible and qh_resetlists
-
- design:
- check visible facet and newfacet flags
- check newlist vertex flags and qh.STOPcone/STOPpoint
- for each facet with a furthest outside point
- add point to facet
- exit if qh.STOPcone or qh.STOPpoint requested
- if qh.NARROWhull for initial simplex
- partition remaining outside points to coplanar sets
-*/
-void qh_buildhull(void) {
- facetT *facet;
- pointT *furthest;
- vertexT *vertex;
- int id;
-
- trace1((qh ferr, 1037, "qh_buildhull: start build hull\n"));
- FORALLfacets {
- if (facet->visible || facet->newfacet) {
- qh_fprintf(qh ferr, 6165, "qhull internal error (qh_buildhull): visible or new facet f%d in facet list\n",
- facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- }
- FORALLvertices {
- if (vertex->newlist) {
- qh_fprintf(qh ferr, 6166, "qhull internal error (qh_buildhull): new vertex f%d in vertex list\n",
- vertex->id);
- qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- id= qh_pointid(vertex->point);
- if ((qh STOPpoint>0 && id == qh STOPpoint-1) ||
- (qh STOPpoint<0 && id == -qh STOPpoint-1) ||
- (qh STOPcone>0 && id == qh STOPcone-1)) {
- trace1((qh ferr, 1038,"qh_buildhull: stop point or cone P%d in initial hull\n", id));
- return;
- }
- }
- qh facet_next= qh facet_list; /* advance facet when processed */
- while ((furthest= qh_nextfurthest(&facet))) {
- qh num_outside--; /* if ONLYmax, furthest may not be outside */
- if (!qh_addpoint(furthest, facet, qh ONLYmax))
- break;
- }
- if (qh NARROWhull) /* move points from outsideset to coplanarset */
- qh_outcoplanar( /* facet_list */ );
- if (qh num_outside && !furthest) {
- qh_fprintf(qh ferr, 6167, "qhull internal error (qh_buildhull): %d outside points were never processed.\n", qh num_outside);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- trace1((qh ferr, 1039, "qh_buildhull: completed the hull construction\n"));
-} /* buildhull */
-
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="buildtracing">-</a>
-
- qh_buildtracing( furthest, facet )
- trace an iteration of qh_buildhull() for furthest point and facet
- if !furthest, prints progress message
-
- returns:
- tracks progress with qh.lastreport
- updates qh.furthest_id (-3 if furthest is NULL)
- also resets visit_id, vertext_visit on wrap around
-
- see:
- qh_tracemerging()
-
- design:
- if !furthest
- print progress message
- exit
- if 'TFn' iteration
- print progress message
- else if tracing
- trace furthest point and facet
- reset qh.visit_id and qh.vertex_visit if overflow may occur
- set qh.furthest_id for tracing
-*/
-void qh_buildtracing(pointT *furthest, facetT *facet) {
- realT dist= 0;
- float cpu;
- int total, furthestid;
- time_t timedata;
- struct tm *tp;
- vertexT *vertex;
-
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- if (!furthest) {
- time(&timedata);
- tp= localtime(&timedata);
- cpu= (float)qh_CPUclock - (float)qh hulltime;
- cpu /= (float)qh_SECticks;
- total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
- qh_fprintf(qh ferr, 8118, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices. Last point was p%d\n",
- tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
- total, qh num_facets, qh num_vertices, qh furthest_id);
- return;
- }
- furthestid= qh_pointid(furthest);
- if (qh TRACEpoint == furthestid) {
- qh IStracing= qh TRACElevel;
- qhmem.IStracing= qh TRACElevel;
- }else if (qh TRACEpoint != -1 && qh TRACEdist < REALmax/2) {
- qh IStracing= 0;
- qhmem.IStracing= 0;
- }
- if (qh REPORTfreq && (qh facet_id-1 > qh lastreport+qh REPORTfreq)) {
- qh lastreport= qh facet_id-1;
- time(&timedata);
- tp= localtime(&timedata);
- cpu= (float)qh_CPUclock - (float)qh hulltime;
- cpu /= (float)qh_SECticks;
- total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
- zinc_(Zdistio);
- qh_distplane(furthest, facet, &dist);
- qh_fprintf(qh ferr, 8119, "\n\
-At %02d:%02d:%02d & %2.5g CPU secs, qhull has created %d facets and merged %d.\n\
- The current hull contains %d facets and %d vertices. There are %d\n\
- outside points. Next is point p%d(v%d), %2.2g above f%d.\n",
- tp->tm_hour, tp->tm_min, tp->tm_sec, cpu, qh facet_id -1,
- total, qh num_facets, qh num_vertices, qh num_outside+1,
- furthestid, qh vertex_id, dist, getid_(facet));
- }else if (qh IStracing >=1) {
- cpu= (float)qh_CPUclock - (float)qh hulltime;
- cpu /= (float)qh_SECticks;
- qh_distplane(furthest, facet, &dist);
- qh_fprintf(qh ferr, 8120, "qh_addpoint: add p%d(v%d) to hull of %d facets(%2.2g above f%d) and %d outside at %4.4g CPU secs. Previous was p%d.\n",
- furthestid, qh vertex_id, qh num_facets, dist,
- getid_(facet), qh num_outside+1, cpu, qh furthest_id);
- }
- zmax_(Zvisit2max, (int)qh visit_id/2);
- if (qh visit_id > (unsigned) INT_MAX) {
- zinc_(Zvisit);
- qh visit_id= 0;
- FORALLfacets
- facet->visitid= 0;
- }
- zmax_(Zvvisit2max, (int)qh vertex_visit/2);
- if (qh vertex_visit > (unsigned) INT_MAX/2) { /* 31 bits */
- zinc_(Zvvisit);
- qh vertex_visit= 0;
- FORALLvertices
- vertex->visitid= 0;
- }
- qh furthest_id= furthestid;
- qh RANDOMdist= qh old_randomdist;
-} /* buildtracing */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="errexit2">-</a>
-
- qh_errexit2( exitcode, facet, otherfacet )
- return exitcode to system after an error
- report two facets
-
- returns:
- assumes exitcode non-zero
-
- see:
- normally use qh_errexit() in user.c(reports a facet and a ridge)
-*/
-void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet) {
-
- qh_errprint("ERRONEOUS", facet, otherfacet, NULL, NULL);
- qh_errexit(exitcode, NULL, NULL);
-} /* errexit2 */
-
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="findhorizon">-</a>
-
- qh_findhorizon( point, facet, goodvisible, goodhorizon )
- given a visible facet, find the point's horizon and visible facets
- for all facets, !facet-visible
-
- returns:
- returns qh.visible_list/num_visible with all visible facets
- marks visible facets with ->visible
- updates count of good visible and good horizon facets
- updates qh.max_outside, qh.max_vertex, facet->maxoutside
-
- see:
- similar to qh_delpoint()
-
- design:
- move facet to qh.visible_list at end of qh.facet_list
- for all visible facets
- for each unvisited neighbor of a visible facet
- compute distance of point to neighbor
- if point above neighbor
- move neighbor to end of qh.visible_list
- else if point is coplanar with neighbor
- update qh.max_outside, qh.max_vertex, neighbor->maxoutside
- mark neighbor coplanar (will create a samecycle later)
- update horizon statistics
-*/
-void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible, int *goodhorizon) {
- facetT *neighbor, **neighborp, *visible;
- int numhorizon= 0, coplanar= 0;
- realT dist;
-
- trace1((qh ferr, 1040,"qh_findhorizon: find horizon for point p%d facet f%d\n",qh_pointid(point),facet->id));
- *goodvisible= *goodhorizon= 0;
- zinc_(Ztotvisible);
- qh_removefacet(facet); /* visible_list at end of qh facet_list */
- qh_appendfacet(facet);
- qh num_visible= 1;
- if (facet->good)
- (*goodvisible)++;
- qh visible_list= facet;
- facet->visible= True;
- facet->f.replace= NULL;
- if (qh IStracing >=4)
- qh_errprint("visible", facet, NULL, NULL, NULL);
- qh visit_id++;
- FORALLvisible_facets {
- if (visible->tricoplanar && !qh TRInormals) {
- qh_fprintf(qh ferr, 6230, "Qhull internal error (qh_findhorizon): does not work for tricoplanar facets. Use option 'Q11'\n");
- qh_errexit(qh_ERRqhull, visible, NULL);
- }
- visible->visitid= qh visit_id;
- FOREACHneighbor_(visible) {
- if (neighbor->visitid == qh visit_id)
- continue;
- neighbor->visitid= qh visit_id;
- zzinc_(Znumvisibility);
- qh_distplane(point, neighbor, &dist);
- if (dist > qh MINvisible) {
- zinc_(Ztotvisible);
- qh_removefacet(neighbor); /* append to end of qh visible_list */
- qh_appendfacet(neighbor);
- neighbor->visible= True;
- neighbor->f.replace= NULL;
- qh num_visible++;
- if (neighbor->good)
- (*goodvisible)++;
- if (qh IStracing >=4)
- qh_errprint("visible", neighbor, NULL, NULL, NULL);
- }else {
- if (dist > - qh MAXcoplanar) {
- neighbor->coplanar= True;
- zzinc_(Zcoplanarhorizon);
- qh_precision("coplanar horizon");
- coplanar++;
- if (qh MERGING) {
- if (dist > 0) {
- maximize_(qh max_outside, dist);
- maximize_(qh max_vertex, dist);
-#if qh_MAXoutside
- maximize_(neighbor->maxoutside, dist);
-#endif
- }else
- minimize_(qh min_vertex, dist); /* due to merge later */
- }
- trace2((qh ferr, 2057, "qh_findhorizon: point p%d is coplanar to horizon f%d, dist=%2.7g < qh MINvisible(%2.7g)\n",
- qh_pointid(point), neighbor->id, dist, qh MINvisible));
- }else
- neighbor->coplanar= False;
- zinc_(Ztothorizon);
- numhorizon++;
- if (neighbor->good)
- (*goodhorizon)++;
- if (qh IStracing >=4)
- qh_errprint("horizon", neighbor, NULL, NULL, NULL);
- }
- }
- }
- if (!numhorizon) {
- qh_precision("empty horizon");
- qh_fprintf(qh ferr, 6168, "qhull precision error (qh_findhorizon): empty horizon\n\
-QhullPoint p%d was above all facets.\n", qh_pointid(point));
- qh_printfacetlist(qh facet_list, NULL, True);
- qh_errexit(qh_ERRprec, NULL, NULL);
- }
- trace1((qh ferr, 1041, "qh_findhorizon: %d horizon facets(good %d), %d visible(good %d), %d coplanar\n",
- numhorizon, *goodhorizon, qh num_visible, *goodvisible, coplanar));
- if (qh IStracing >= 4 && qh num_facets < 50)
- qh_printlists();
-} /* findhorizon */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="nextfurthest">-</a>
-
- qh_nextfurthest( visible )
- returns next furthest point and visible facet for qh_addpoint()
- starts search at qh.facet_next
-
- returns:
- removes furthest point from outside set
- NULL if none available
- advances qh.facet_next over facets with empty outside sets
-
- design:
- for each facet from qh.facet_next
- if empty outside set
- advance qh.facet_next
- else if qh.NARROWhull
- determine furthest outside point
- if furthest point is not outside
- advance qh.facet_next(point will be coplanar)
- remove furthest point from outside set
-*/
-pointT *qh_nextfurthest(facetT **visible) {
- facetT *facet;
- int size, idx;
- realT randr, dist;
- pointT *furthest;
-
- while ((facet= qh facet_next) != qh facet_tail) {
- if (!facet->outsideset) {
- qh facet_next= facet->next;
- continue;
- }
- SETreturnsize_(facet->outsideset, size);
- if (!size) {
- qh_setfree(&facet->outsideset);
- qh facet_next= facet->next;
- continue;
- }
- if (qh NARROWhull) {
- if (facet->notfurthest)
- qh_furthestout(facet);
- furthest= (pointT*)qh_setlast(facet->outsideset);
-#if qh_COMPUTEfurthest
- qh_distplane(furthest, facet, &dist);
- zinc_(Zcomputefurthest);
-#else
- dist= facet->furthestdist;
-#endif
- if (dist < qh MINoutside) { /* remainder of outside set is coplanar for qh_outcoplanar */
- qh facet_next= facet->next;
- continue;
- }
- }
- if (!qh RANDOMoutside && !qh VIRTUALmemory) {
- if (qh PICKfurthest) {
- qh_furthestnext(/* qh facet_list */);
- facet= qh facet_next;
- }
- *visible= facet;
- return((pointT*)qh_setdellast(facet->outsideset));
- }
- if (qh RANDOMoutside) {
- int outcoplanar = 0;
- if (qh NARROWhull) {
- FORALLfacets {
- if (facet == qh facet_next)
- break;
- if (facet->outsideset)
- outcoplanar += qh_setsize( facet->outsideset);
- }
- }
- randr= qh_RANDOMint;
- randr= randr/(qh_RANDOMmax+1);
- idx= (int)floor((qh num_outside - outcoplanar) * randr);
- FORALLfacet_(qh facet_next) {
- if (facet->outsideset) {
- SETreturnsize_(facet->outsideset, size);
- if (!size)
- qh_setfree(&facet->outsideset);
- else if (size > idx) {
- *visible= facet;
- return((pointT*)qh_setdelnth(facet->outsideset, idx));
- }else
- idx -= size;
- }
- }
- qh_fprintf(qh ferr, 6169, "qhull internal error (qh_nextfurthest): num_outside %d is too low\nby at least %d, or a random real %g >= 1.0\n",
- qh num_outside, idx+1, randr);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }else { /* VIRTUALmemory */
- facet= qh facet_tail->previous;
- if (!(furthest= (pointT*)qh_setdellast(facet->outsideset))) {
- if (facet->outsideset)
- qh_setfree(&facet->outsideset);
- qh_removefacet(facet);
- qh_prependfacet(facet, &qh facet_list);
- continue;
- }
- *visible= facet;
- return furthest;
- }
- }
- return NULL;
-} /* nextfurthest */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="partitionall">-</a>
-
- qh_partitionall( vertices, points, numpoints )
- partitions all points in points/numpoints to the outsidesets of facets
- vertices= vertices in qh.facet_list(!partitioned)
-
- returns:
- builds facet->outsideset
- does not partition qh.GOODpoint
- if qh.ONLYgood && !qh.MERGING,
- does not partition qh.GOODvertex
-
- notes:
- faster if qh.facet_list sorted by anticipated size of outside set
-
- design:
- initialize pointset with all points
- remove vertices from pointset
- remove qh.GOODpointp from pointset (unless it's qh.STOPcone or qh.STOPpoint)
- for all facets
- for all remaining points in pointset
- compute distance from point to facet
- if point is outside facet
- remove point from pointset (by not reappending)
- update bestpoint
- append point or old bestpoint to facet's outside set
- append bestpoint to facet's outside set (furthest)
- for all points remaining in pointset
- partition point into facets' outside sets and coplanar sets
-*/
-void qh_partitionall(setT *vertices, pointT *points, int numpoints){
- setT *pointset;
- vertexT *vertex, **vertexp;
- pointT *point, **pointp, *bestpoint;
- int size, point_i, point_n, point_end, remaining, i, id;
- facetT *facet;
- realT bestdist= -REALmax, dist, distoutside;
-
- trace1((qh ferr, 1042, "qh_partitionall: partition all points into outside sets\n"));
- pointset= qh_settemp(numpoints);
- qh num_outside= 0;
- pointp= SETaddr_(pointset, pointT);
- for (i=numpoints, point= points; i--; point += qh hull_dim)
- *(pointp++)= point;
- qh_settruncate(pointset, numpoints);
- FOREACHvertex_(vertices) {
- if ((id= qh_pointid(vertex->point)) >= 0)
- SETelem_(pointset, id)= NULL;
- }
- id= qh_pointid(qh GOODpointp);
- if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
- SETelem_(pointset, id)= NULL;
- if (qh GOODvertexp && qh ONLYgood && !qh MERGING) { /* matches qhull()*/
- if ((id= qh_pointid(qh GOODvertexp)) >= 0)
- SETelem_(pointset, id)= NULL;
- }
- if (!qh BESToutside) { /* matches conditional for qh_partitionpoint below */
- distoutside= qh_DISToutside; /* multiple of qh.MINoutside & qh.max_outside, see user.h */
- zval_(Ztotpartition)= qh num_points - qh hull_dim - 1; /*misses GOOD... */
- remaining= qh num_facets;
- point_end= numpoints;
- FORALLfacets {
- size= point_end/(remaining--) + 100;
- facet->outsideset= qh_setnew(size);
- bestpoint= NULL;
- point_end= 0;
- FOREACHpoint_i_(pointset) {
- if (point) {
- zzinc_(Zpartitionall);
- qh_distplane(point, facet, &dist);
- if (dist < distoutside)
- SETelem_(pointset, point_end++)= point;
- else {
- qh num_outside++;
- if (!bestpoint) {
- bestpoint= point;
- bestdist= dist;
- }else if (dist > bestdist) {
- qh_setappend(&facet->outsideset, bestpoint);
- bestpoint= point;
- bestdist= dist;
- }else
- qh_setappend(&facet->outsideset, point);
- }
- }
- }
- if (bestpoint) {
- qh_setappend(&facet->outsideset, bestpoint);
-#if !qh_COMPUTEfurthest
- facet->furthestdist= bestdist;
-#endif
- }else
- qh_setfree(&facet->outsideset);
- qh_settruncate(pointset, point_end);
- }
- }
- /* if !qh BESToutside, pointset contains points not assigned to outsideset */
- if (qh BESToutside || qh MERGING || qh KEEPcoplanar || qh KEEPinside) {
- qh findbestnew= True;
- FOREACHpoint_i_(pointset) {
- if (point)
- qh_partitionpoint(point, qh facet_list);
- }
- qh findbestnew= False;
- }
- zzadd_(Zpartitionall, zzval_(Zpartition));
- zzval_(Zpartition)= 0;
- qh_settempfree(&pointset);
- if (qh IStracing >= 4)
- qh_printfacetlist(qh facet_list, NULL, True);
-} /* partitionall */
-
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="partitioncoplanar">-</a>
-
- qh_partitioncoplanar( point, facet, dist )
- partition coplanar point to a facet
- dist is distance from point to facet
- if dist NULL,
- searches for bestfacet and does nothing if inside
- if qh.findbestnew set,
- searches new facets instead of using qh_findbest()
-
- returns:
- qh.max_ouside updated
- if qh.KEEPcoplanar or qh.KEEPinside
- point assigned to best coplanarset
-
- notes:
- facet->maxoutside is updated at end by qh_check_maxout
-
- design:
- if dist undefined
- find best facet for point
- if point sufficiently below facet (depends on qh.NEARinside and qh.KEEPinside)
- exit
- if keeping coplanar/nearinside/inside points
- if point is above furthest coplanar point
- append point to coplanar set (it is the new furthest)
- update qh.max_outside
- else
- append point one before end of coplanar set
- else if point is clearly outside of qh.max_outside and bestfacet->coplanarset
- and bestfacet is more than perpendicular to facet
- repartition the point using qh_findbest() -- it may be put on an outsideset
- else
- update qh.max_outside
-*/
-void qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist) {
- facetT *bestfacet;
- pointT *oldfurthest;
- realT bestdist, dist2= 0, angle;
- int numpart= 0, oldfindbest;
- boolT isoutside;
-
- qh WAScoplanar= True;
- if (!dist) {
- if (qh findbestnew)
- bestfacet= qh_findbestnew(point, facet, &bestdist, qh_ALL, &isoutside, &numpart);
- else
- bestfacet= qh_findbest(point, facet, qh_ALL, !qh_ISnewfacets, qh DELAUNAY,
- &bestdist, &isoutside, &numpart);
- zinc_(Ztotpartcoplanar);
- zzadd_(Zpartcoplanar, numpart);
- if (!qh DELAUNAY && !qh KEEPinside) { /* for 'd', bestdist skips upperDelaunay facets */
- if (qh KEEPnearinside) {
- if (bestdist < -qh NEARinside) {
- zinc_(Zcoplanarinside);
- trace4((qh ferr, 4062, "qh_partitioncoplanar: point p%d is more than near-inside facet f%d dist %2.2g findbestnew %d\n",
- qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
- return;
- }
- }else if (bestdist < -qh MAXcoplanar) {
- trace4((qh ferr, 4063, "qh_partitioncoplanar: point p%d is inside facet f%d dist %2.2g findbestnew %d\n",
- qh_pointid(point), bestfacet->id, bestdist, qh findbestnew));
- zinc_(Zcoplanarinside);
- return;
- }
- }
- }else {
- bestfacet= facet;
- bestdist= *dist;
- }
- if (bestdist > qh max_outside) {
- if (!dist && facet != bestfacet) {
- zinc_(Zpartangle);
- angle= qh_getangle(facet->normal, bestfacet->normal);
- if (angle < 0) {
- /* typically due to deleted vertex and coplanar facets, e.g.,
- RBOX 1000 s Z1 G1e-13 t1001185205 | QHULL Tv */
- zinc_(Zpartflip);
- trace2((qh ferr, 2058, "qh_partitioncoplanar: repartition point p%d from f%d. It is above flipped facet f%d dist %2.2g\n",
- qh_pointid(point), facet->id, bestfacet->id, bestdist));
- oldfindbest= qh findbestnew;
- qh findbestnew= False;
- qh_partitionpoint(point, bestfacet);
- qh findbestnew= oldfindbest;
- return;
- }
- }
- qh max_outside= bestdist;
- if (bestdist > qh TRACEdist) {
- qh_fprintf(qh ferr, 8122, "qh_partitioncoplanar: ====== p%d from f%d increases max_outside to %2.2g of f%d last p%d\n",
- qh_pointid(point), facet->id, bestdist, bestfacet->id, qh furthest_id);
- qh_errprint("DISTANT", facet, bestfacet, NULL, NULL);
- }
- }
- if (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside) {
- oldfurthest= (pointT*)qh_setlast(bestfacet->coplanarset);
- if (oldfurthest) {
- zinc_(Zcomputefurthest);
- qh_distplane(oldfurthest, bestfacet, &dist2);
- }
- if (!oldfurthest || dist2 < bestdist)
- qh_setappend(&bestfacet->coplanarset, point);
- else
- qh_setappend2ndlast(&bestfacet->coplanarset, point);
- }
- trace4((qh ferr, 4064, "qh_partitioncoplanar: point p%d is coplanar with facet f%d(or inside) dist %2.2g\n",
- qh_pointid(point), bestfacet->id, bestdist));
-} /* partitioncoplanar */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="partitionpoint">-</a>
-
- qh_partitionpoint( point, facet )
- assigns point to an outside set, coplanar set, or inside set (i.e., dropt)
- if qh.findbestnew
- uses qh_findbestnew() to search all new facets
- else
- uses qh_findbest()
-
- notes:
- after qh_distplane(), this and qh_findbest() are most expensive in 3-d
-
- design:
- find best facet for point
- (either exhaustive search of new facets or directed search from facet)
- if qh.NARROWhull
- retain coplanar and nearinside points as outside points
- if point is outside bestfacet
- if point above furthest point for bestfacet
- append point to outside set (it becomes the new furthest)
- if outside set was empty
- move bestfacet to end of qh.facet_list (i.e., after qh.facet_next)
- update bestfacet->furthestdist
- else
- append point one before end of outside set
- else if point is coplanar to bestfacet
- if keeping coplanar points or need to update qh.max_outside
- partition coplanar point into bestfacet
- else if near-inside point
- partition as coplanar point into bestfacet
- else is an inside point
- if keeping inside points
- partition as coplanar point into bestfacet
-*/
-void qh_partitionpoint(pointT *point, facetT *facet) {
- realT bestdist;
- boolT isoutside;
- facetT *bestfacet;
- int numpart;
-#if qh_COMPUTEfurthest
- realT dist;
-#endif
-
- if (qh findbestnew)
- bestfacet= qh_findbestnew(point, facet, &bestdist, qh BESToutside, &isoutside, &numpart);
- else
- bestfacet= qh_findbest(point, facet, qh BESToutside, qh_ISnewfacets, !qh_NOupper,
- &bestdist, &isoutside, &numpart);
- zinc_(Ztotpartition);
- zzadd_(Zpartition, numpart);
- if (qh NARROWhull) {
- if (qh DELAUNAY && !isoutside && bestdist >= -qh MAXcoplanar)
- qh_precision("nearly incident point(narrow hull)");
- if (qh KEEPnearinside) {
- if (bestdist >= -qh NEARinside)
- isoutside= True;
- }else if (bestdist >= -qh MAXcoplanar)
- isoutside= True;
- }
-
- if (isoutside) {
- if (!bestfacet->outsideset
- || !qh_setlast(bestfacet->outsideset)) {
- qh_setappend(&(bestfacet->outsideset), point);
- if (!bestfacet->newfacet) {
- qh_removefacet(bestfacet); /* make sure it's after qh facet_next */
- qh_appendfacet(bestfacet);
- }
-#if !qh_COMPUTEfurthest
- bestfacet->furthestdist= bestdist;
-#endif
- }else {
-#if qh_COMPUTEfurthest
- zinc_(Zcomputefurthest);
- qh_distplane(oldfurthest, bestfacet, &dist);
- if (dist < bestdist)
- qh_setappend(&(bestfacet->outsideset), point);
- else
- qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#else
- if (bestfacet->furthestdist < bestdist) {
- qh_setappend(&(bestfacet->outsideset), point);
- bestfacet->furthestdist= bestdist;
- }else
- qh_setappend2ndlast(&(bestfacet->outsideset), point);
-#endif
- }
- qh num_outside++;
- trace4((qh ferr, 4065, "qh_partitionpoint: point p%d is outside facet f%d new? %d (or narrowhull)\n",
- qh_pointid(point), bestfacet->id, bestfacet->newfacet));
- }else if (qh DELAUNAY || bestdist >= -qh MAXcoplanar) { /* for 'd', bestdist skips upperDelaunay facets */
- zzinc_(Zcoplanarpart);
- if (qh DELAUNAY)
- qh_precision("nearly incident point");
- if ((qh KEEPcoplanar + qh KEEPnearinside) || bestdist > qh max_outside)
- qh_partitioncoplanar(point, bestfacet, &bestdist);
- else {
- trace4((qh ferr, 4066, "qh_partitionpoint: point p%d is coplanar to facet f%d (dropped)\n",
- qh_pointid(point), bestfacet->id));
- }
- }else if (qh KEEPnearinside && bestdist > -qh NEARinside) {
- zinc_(Zpartnear);
- qh_partitioncoplanar(point, bestfacet, &bestdist);
- }else {
- zinc_(Zpartinside);
- trace4((qh ferr, 4067, "qh_partitionpoint: point p%d is inside all facets, closest to f%d dist %2.2g\n",
- qh_pointid(point), bestfacet->id, bestdist));
- if (qh KEEPinside)
- qh_partitioncoplanar(point, bestfacet, &bestdist);
- }
-} /* partitionpoint */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="partitionvisible">-</a>
-
- qh_partitionvisible( allpoints, numoutside )
- partitions points in visible facets to qh.newfacet_list
- qh.visible_list= visible facets
- for visible facets
- 1st neighbor (if any) points to a horizon facet or a new facet
- if allpoints(!used),
- repartitions coplanar points
-
- returns:
- updates outside sets and coplanar sets of qh.newfacet_list
- updates qh.num_outside (count of outside points)
-
- notes:
- qh.findbest_notsharp should be clear (extra work if set)
-
- design:
- for all visible facets with outside set or coplanar set
- select a newfacet for visible facet
- if outside set
- partition outside set into new facets
- if coplanar set and keeping coplanar/near-inside/inside points
- if allpoints
- partition coplanar set into new facets, may be assigned outside
- else
- partition coplanar set into coplanar sets of new facets
- for each deleted vertex
- if allpoints
- partition vertex into new facets, may be assigned outside
- else
- partition vertex into coplanar sets of new facets
-*/
-void qh_partitionvisible(/*visible_list*/ boolT allpoints, int *numoutside) {
- facetT *visible, *newfacet;
- pointT *point, **pointp;
- int coplanar=0, size;
- unsigned count;
- vertexT *vertex, **vertexp;
-
- if (qh ONLYmax)
- maximize_(qh MINoutside, qh max_vertex);
- *numoutside= 0;
- FORALLvisible_facets {
- if (!visible->outsideset && !visible->coplanarset)
- continue;
- newfacet= visible->f.replace;
- count= 0;
- while (newfacet && newfacet->visible) {
- newfacet= newfacet->f.replace;
- if (count++ > qh facet_id)
- qh_infiniteloop(visible);
- }
- if (!newfacet)
- newfacet= qh newfacet_list;
- if (newfacet == qh facet_tail) {
- qh_fprintf(qh ferr, 6170, "qhull precision error (qh_partitionvisible): all new facets deleted as\n degenerate facets. Can not continue.\n");
- qh_errexit(qh_ERRprec, NULL, NULL);
- }
- if (visible->outsideset) {
- size= qh_setsize(visible->outsideset);
- *numoutside += size;
- qh num_outside -= size;
- FOREACHpoint_(visible->outsideset)
- qh_partitionpoint(point, newfacet);
- }
- if (visible->coplanarset && (qh KEEPcoplanar + qh KEEPinside + qh KEEPnearinside)) {
- size= qh_setsize(visible->coplanarset);
- coplanar += size;
- FOREACHpoint_(visible->coplanarset) {
- if (allpoints) /* not used */
- qh_partitionpoint(point, newfacet);
- else
- qh_partitioncoplanar(point, newfacet, NULL);
- }
- }
- }
- FOREACHvertex_(qh del_vertices) {
- if (vertex->point) {
- if (allpoints) /* not used */
- qh_partitionpoint(vertex->point, qh newfacet_list);
- else
- qh_partitioncoplanar(vertex->point, qh newfacet_list, NULL);
- }
- }
- trace1((qh ferr, 1043,"qh_partitionvisible: partitioned %d points from outsidesets and %d points from coplanarsets\n", *numoutside, coplanar));
-} /* partitionvisible */
-
-
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="precision">-</a>
-
- qh_precision( reason )
- restart on precision errors if not merging and if 'QJn'
-*/
-void qh_precision(const char *reason) {
-
- if (qh ALLOWrestart && !qh PREmerge && !qh MERGEexact) {
- if (qh JOGGLEmax < REALmax/2) {
- trace0((qh ferr, 26, "qh_precision: qhull restart because of %s\n", reason));
- longjmp(qh restartexit, qh_ERRprec);
- }
- }
-} /* qh_precision */
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="printsummary">-</a>
-
- qh_printsummary( fp )
- prints summary to fp
-
- notes:
- not in io.c so that user_eg.c can prevent io.c from loading
- qh_printsummary and qh_countfacets must match counts
-
- design:
- determine number of points, vertices, and coplanar points
- print summary
-*/
-void qh_printsummary(FILE *fp) {
- realT ratio, outerplane, innerplane;
- float cpu;
- int size, id, nummerged, numvertices, numcoplanars= 0, nonsimplicial=0;
- int goodused;
- facetT *facet;
- const char *s;
- int numdel= zzval_(Zdelvertextot);
- int numtricoplanars= 0;
-
- size= qh num_points + qh_setsize(qh other_points);
- numvertices= qh num_vertices - qh_setsize(qh del_vertices);
- id= qh_pointid(qh GOODpointp);
- FORALLfacets {
- if (facet->coplanarset)
- numcoplanars += qh_setsize( facet->coplanarset);
- if (facet->good) {
- if (facet->simplicial) {
- if (facet->keepcentrum && facet->tricoplanar)
- numtricoplanars++;
- }else if (qh_setsize(facet->vertices) != qh hull_dim)
- nonsimplicial++;
- }
- }
- if (id >=0 && qh STOPcone-1 != id && -qh STOPpoint-1 != id)
- size--;
- if (qh STOPcone || qh STOPpoint)
- qh_fprintf(fp, 9288, "\nAt a premature exit due to 'TVn', 'TCn', 'TRn', or precision error with 'QJn'.");
- if (qh UPPERdelaunay)
- goodused= qh GOODvertex + qh GOODpoint + qh SPLITthresholds;
- else if (qh DELAUNAY)
- goodused= qh GOODvertex + qh GOODpoint + qh GOODthreshold;
- else
- goodused= qh num_good;
- nummerged= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
- if (qh VORONOI) {
- if (qh UPPERdelaunay)
- qh_fprintf(fp, 9289, "\n\
-Furthest-site Voronoi vertices by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- else
- qh_fprintf(fp, 9290, "\n\
-Voronoi diagram by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- qh_fprintf(fp, 9291, " Number of Voronoi regions%s: %d\n",
- qh ATinfinity ? " and at-infinity" : "", numvertices);
- if (numdel)
- qh_fprintf(fp, 9292, " Total number of deleted points due to merging: %d\n", numdel);
- if (numcoplanars - numdel > 0)
- qh_fprintf(fp, 9293, " Number of nearly incident points: %d\n", numcoplanars - numdel);
- else if (size - numvertices - numdel > 0)
- qh_fprintf(fp, 9294, " Total number of nearly incident points: %d\n", size - numvertices - numdel);
- qh_fprintf(fp, 9295, " Number of%s Voronoi vertices: %d\n",
- goodused ? " 'good'" : "", qh num_good);
- if (nonsimplicial)
- qh_fprintf(fp, 9296, " Number of%s non-simplicial Voronoi vertices: %d\n",
- goodused ? " 'good'" : "", nonsimplicial);
- }else if (qh DELAUNAY) {
- if (qh UPPERdelaunay)
- qh_fprintf(fp, 9297, "\n\
-Furthest-site Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- else
- qh_fprintf(fp, 9298, "\n\
-Delaunay triangulation by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- qh_fprintf(fp, 9299, " Number of input sites%s: %d\n",
- qh ATinfinity ? " and at-infinity" : "", numvertices);
- if (numdel)
- qh_fprintf(fp, 9300, " Total number of deleted points due to merging: %d\n", numdel);
- if (numcoplanars - numdel > 0)
- qh_fprintf(fp, 9301, " Number of nearly incident points: %d\n", numcoplanars - numdel);
- else if (size - numvertices - numdel > 0)
- qh_fprintf(fp, 9302, " Total number of nearly incident points: %d\n", size - numvertices - numdel);
- qh_fprintf(fp, 9303, " Number of%s Delaunay regions: %d\n",
- goodused ? " 'good'" : "", qh num_good);
- if (nonsimplicial)
- qh_fprintf(fp, 9304, " Number of%s non-simplicial Delaunay regions: %d\n",
- goodused ? " 'good'" : "", nonsimplicial);
- }else if (qh HALFspace) {
- qh_fprintf(fp, 9305, "\n\
-Halfspace intersection by the convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- qh_fprintf(fp, 9306, " Number of halfspaces: %d\n", size);
- qh_fprintf(fp, 9307, " Number of non-redundant halfspaces: %d\n", numvertices);
- if (numcoplanars) {
- if (qh KEEPinside && qh KEEPcoplanar)
- s= "similar and redundant";
- else if (qh KEEPinside)
- s= "redundant";
- else
- s= "similar";
- qh_fprintf(fp, 9308, " Number of %s halfspaces: %d\n", s, numcoplanars);
- }
- qh_fprintf(fp, 9309, " Number of intersection points: %d\n", qh num_facets - qh num_visible);
- if (goodused)
- qh_fprintf(fp, 9310, " Number of 'good' intersection points: %d\n", qh num_good);
- if (nonsimplicial)
- qh_fprintf(fp, 9311, " Number of%s non-simplicial intersection points: %d\n",
- goodused ? " 'good'" : "", nonsimplicial);
- }else {
- qh_fprintf(fp, 9312, "\n\
-Convex hull of %d points in %d-d:\n\n", size, qh hull_dim);
- qh_fprintf(fp, 9313, " Number of vertices: %d\n", numvertices);
- if (numcoplanars) {
- if (qh KEEPinside && qh KEEPcoplanar)
- s= "coplanar and interior";
- else if (qh KEEPinside)
- s= "interior";
- else
- s= "coplanar";
- qh_fprintf(fp, 9314, " Number of %s points: %d\n", s, numcoplanars);
- }
- qh_fprintf(fp, 9315, " Number of facets: %d\n", qh num_facets - qh num_visible);
- if (goodused)
- qh_fprintf(fp, 9316, " Number of 'good' facets: %d\n", qh num_good);
- if (nonsimplicial)
- qh_fprintf(fp, 9317, " Number of%s non-simplicial facets: %d\n",
- goodused ? " 'good'" : "", nonsimplicial);
- }
- if (numtricoplanars)
- qh_fprintf(fp, 9318, " Number of triangulated facets: %d\n", numtricoplanars);
- qh_fprintf(fp, 9319, "\nStatistics for: %s | %s",
- qh rbox_command, qh qhull_command);
- if (qh ROTATErandom != INT_MIN)
- qh_fprintf(fp, 9320, " QR%d\n\n", qh ROTATErandom);
- else
- qh_fprintf(fp, 9321, "\n\n");
- qh_fprintf(fp, 9322, " Number of points processed: %d\n", zzval_(Zprocessed));
- qh_fprintf(fp, 9323, " Number of hyperplanes created: %d\n", zzval_(Zsetplane));
- if (qh DELAUNAY)
- qh_fprintf(fp, 9324, " Number of facets in hull: %d\n", qh num_facets - qh num_visible);
- qh_fprintf(fp, 9325, " Number of distance tests for qhull: %d\n", zzval_(Zpartition)+
- zzval_(Zpartitionall)+zzval_(Znumvisibility)+zzval_(Zpartcoplanar));
-#if 0 /* NOTE: must print before printstatistics() */
- {realT stddev, ave;
- qh_fprintf(fp, 9326, " average new facet balance: %2.2g\n",
- wval_(Wnewbalance)/zval_(Zprocessed));
- stddev= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
- wval_(Wnewbalance2), &ave);
- qh_fprintf(fp, 9327, " new facet standard deviation: %2.2g\n", stddev);
- qh_fprintf(fp, 9328, " average partition balance: %2.2g\n",
- wval_(Wpbalance)/zval_(Zpbalance));
- stddev= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
- wval_(Wpbalance2), &ave);
- qh_fprintf(fp, 9329, " partition standard deviation: %2.2g\n", stddev);
- }
-#endif
- if (nummerged) {
- qh_fprintf(fp, 9330," Number of distance tests for merging: %d\n",zzval_(Zbestdist)+
- zzval_(Zcentrumtests)+zzval_(Zdistconvex)+zzval_(Zdistcheck)+
- zzval_(Zdistzero));
- qh_fprintf(fp, 9331," Number of distance tests for checking: %d\n",zzval_(Zcheckpart));
- qh_fprintf(fp, 9332," Number of merged facets: %d\n", nummerged);
- }
- if (!qh RANDOMoutside && qh QHULLfinished) {
- cpu= (float)qh hulltime;
- cpu /= (float)qh_SECticks;
- wval_(Wcpu)= cpu;
- qh_fprintf(fp, 9333, " CPU seconds to compute hull (after input): %2.4g\n", cpu);
- }
- if (qh RERUN) {
- if (!qh PREmerge && !qh MERGEexact)
- qh_fprintf(fp, 9334, " Percentage of runs with precision errors: %4.1f\n",
- zzval_(Zretry)*100.0/qh build_cnt); /* careful of order */
- }else if (qh JOGGLEmax < REALmax/2) {
- if (zzval_(Zretry))
- qh_fprintf(fp, 9335, " After %d retries, input joggled by: %2.2g\n",
- zzval_(Zretry), qh JOGGLEmax);
- else
- qh_fprintf(fp, 9336, " Input joggled by: %2.2g\n", qh JOGGLEmax);
- }
- if (qh totarea != 0.0)
- qh_fprintf(fp, 9337, " %s facet area: %2.8g\n",
- zzval_(Ztotmerge) ? "Approximate" : "Total", qh totarea);
- if (qh totvol != 0.0)
- qh_fprintf(fp, 9338, " %s volume: %2.8g\n",
- zzval_(Ztotmerge) ? "Approximate" : "Total", qh totvol);
- if (qh MERGING) {
- qh_outerinner(NULL, &outerplane, &innerplane);
- if (outerplane > 2 * qh DISTround) {
- qh_fprintf(fp, 9339, " Maximum distance of %spoint above facet: %2.2g",
- (qh QHULLfinished ? "" : "merged "), outerplane);
- ratio= outerplane/(qh ONEmerge + qh DISTround);
- /* don't report ratio if MINoutside is large */
- if (ratio > 0.05 && 2* qh ONEmerge > qh MINoutside && qh JOGGLEmax > REALmax/2)
- qh_fprintf(fp, 9340, " (%.1fx)\n", ratio);
- else
- qh_fprintf(fp, 9341, "\n");
- }
- if (innerplane < -2 * qh DISTround) {
- qh_fprintf(fp, 9342, " Maximum distance of %svertex below facet: %2.2g",
- (qh QHULLfinished ? "" : "merged "), innerplane);
- ratio= -innerplane/(qh ONEmerge+qh DISTround);
- if (ratio > 0.05 && qh JOGGLEmax > REALmax/2)
- qh_fprintf(fp, 9343, " (%.1fx)\n", ratio);
- else
- qh_fprintf(fp, 9344, "\n");
- }
- }
- qh_fprintf(fp, 9345, "\n");
-} /* printsummary */
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/libqhull.h b/PyMca/Object3D/Object3DQhull/src/libqhull.h
deleted file mode 100644
index 7a13226..0000000
--- a/PyMca/Object3D/Object3DQhull/src/libqhull.h
+++ /dev/null
@@ -1,1100 +0,0 @@
-/*<html><pre> -<a href="qh-qhull.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- libqhull.h
- user-level header file for using qhull.a library
-
- see qh-qhull.htm, qhull_a.h
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/libqhull.h#7 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
- NOTE: access to qh_qh is via the 'qh' macro. This allows
- qh_qh to be either a pointer or a structure. An example
- of using qh is "qh DROPdim" which accesses the DROPdim
- field of qh_qh. Similarly, access to qh_qhstat is via
- the 'qhstat' macro.
-
- includes function prototypes for libqhull.c, geom.c, global.c, io.c, user.c
-
- use mem.h for mem.c
- use qset.h for qset.c
-
- see unix.c for an example of using libqhull.h
-
- recompile qhull if you change this file
-*/
-
-#ifndef qhDEFlibqhull
-#define qhDEFlibqhull 1
-
-/*=========================== -included files ==============*/
-
-#include "user.h" /* user definable constants (e.g., qh_QHpointer) */
-
-#include <setjmp.h>
-#include <float.h>
-#include <time.h>
-#include <stdio.h>
-
-#if __MWERKS__ && __POWERPC__
-#include <SIOUX.h>
-#include <Files.h>
-#include <Desk.h>
-#endif
-
-#ifndef __STDC__
-#ifndef __cplusplus
-#if !_MSC_VER
-#error Neither __STDC__ nor __cplusplus is defined. Please use strict ANSI C or C++ to compile
-#error Qhull. You may need to turn off compiler extensions in your project configuration. If
-#error your compiler is a standard C compiler, you can delete this warning from libqhull.h
-#endif
-#endif
-#endif
-
-/*============ constants and basic types ====================*/
-
-extern const char *qh_version; /* defined in global.c */
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="coordT">-</a>
-
- coordT
- coordinates and coefficients are stored as realT (i.e., double)
-
- notes:
- Qhull works well if realT is 'float'. If so joggle (QJ) is not effective.
-
- Could use 'float' for data and 'double' for calculations (realT vs. coordT)
- This requires many type casts, and adjusted error bounds.
- Also C compilers may do expressions in double anyway.
-*/
-#define coordT realT
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="pointT">-</a>
-
- pointT
- a point is an array of coordinates, usually qh.hull_dim
-*/
-#define pointT coordT
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="flagT">-</a>
-
- flagT
- Boolean flag as a bit
-*/
-#define flagT unsigned int
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="boolT">-</a>
-
- boolT
- boolean value, either True or False
-
- notes:
- needed for portability
- Use qh_False/qh_True as synonyms
-*/
-#define boolT unsigned int
-#ifdef False
-#undef False
-#endif
-#ifdef True
-#undef True
-#endif
-#define False 0
-#define True 1
-#define qh_False 0
-#define qh_True 1
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="CENTERtype">-</a>
-
- qh_CENTER
- to distinguish facet->center
-*/
-typedef enum
-{
- qh_ASnone = 0, qh_ASvoronoi, qh_AScentrum
-}
-qh_CENTER;
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="qh_PRINT">-</a>
-
- qh_PRINT
- output formats for printing (qh.PRINTout).
- 'Fa' 'FV' 'Fc' 'FC'
-
-
- notes:
- some of these names are similar to qh names. The similar names are only
- used in switch statements in qh_printbegin() etc.
-*/
-typedef enum {qh_PRINTnone= 0,
- qh_PRINTarea, qh_PRINTaverage, /* 'Fa' 'FV' 'Fc' 'FC' */
- qh_PRINTcoplanars, qh_PRINTcentrums,
- qh_PRINTfacets, qh_PRINTfacets_xridge, /* 'f' 'FF' 'G' 'FI' 'Fi' 'Fn' */
- qh_PRINTgeom, qh_PRINTids, qh_PRINTinner, qh_PRINTneighbors,
- qh_PRINTnormals, qh_PRINTouter, qh_PRINTmaple, /* 'n' 'Fo' 'i' 'm' 'Fm' 'FM', 'o' */
- qh_PRINTincidences, qh_PRINTmathematica, qh_PRINTmerges, qh_PRINToff,
- qh_PRINToptions, qh_PRINTpointintersect, /* 'FO' 'Fp' 'FP' 'p' 'FQ' 'FS' */
- qh_PRINTpointnearest, qh_PRINTpoints, qh_PRINTqhull, qh_PRINTsize,
- qh_PRINTsummary, qh_PRINTtriangles, /* 'Fs' 'Ft' 'Fv' 'FN' 'Fx' */
- qh_PRINTvertices, qh_PRINTvneighbors, qh_PRINTextremes,
- qh_PRINTEND} qh_PRINT;
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="qh_ALL">-</a>
-
- qh_ALL
- argument flag for selecting everything
-*/
-#define qh_ALL True
-#define qh_NOupper True /* argument for qh_findbest */
-#define qh_IScheckmax True /* argument for qh_findbesthorizon */
-#define qh_ISnewfacets True /* argument for qh_findbest */
-#define qh_RESETvisible True /* argument for qh_resetlists */
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="qh_ERR">-</a>
-
- qh_ERR
- Qhull exit codes, for indicating errors
- See: MSG_ERROR and MSG_WARNING [user.h]
-*/
-#define qh_ERRnone 0 /* no error occurred during qhull */
-#define qh_ERRinput 1 /* input inconsistency */
-#define qh_ERRsingular 2 /* singular input data */
-#define qh_ERRprec 3 /* precision error */
-#define qh_ERRmem 4 /* insufficient memory, matches mem.h */
-#define qh_ERRqhull 5 /* internal error detected, matches mem.h */
-
-/*-<a href="qh-qhull.htm#TOC"
->--------------------------------</a><a name="qh_FILEstderr">-</a>
-
-qh_FILEstderr
-Fake stderr to distinguish error output from normal output
-For C++ interface. Must redefine qh_fprintf_qhull
-*/
-#define qh_FILEstderr (FILE*)1
-
-/* ============ -structures- ====================
- each of the following structures is defined by a typedef
- all realT and coordT fields occur at the beginning of a structure
- (otherwise space may be wasted due to alignment)
- define all flags together and pack into 32-bit number
-*/
-
-typedef struct vertexT vertexT;
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT; /* defined in qset.h */
-#endif
-
-#ifndef DEFqhstatT
-#define DEFqhstatT 1
-typedef struct qhstatT qhstatT; /* defined in stat.h */
-#endif
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="facetT">-</a>
-
- facetT
- defines a facet
-
- notes:
- qhull() generates the hull as a list of facets.
-
- topological information:
- f.previous,next doubly-linked list of facets
- f.vertices set of vertices
- f.ridges set of ridges
- f.neighbors set of neighbors
- f.toporient True if facet has top-orientation (else bottom)
-
- geometric information:
- f.offset,normal hyperplane equation
- f.maxoutside offset to outer plane -- all points inside
- f.center centrum for testing convexity
- f.simplicial True if facet is simplicial
- f.flipped True if facet does not include qh.interior_point
-
- for constructing hull:
- f.visible True if facet on list of visible facets (will be deleted)
- f.newfacet True if facet on list of newly created facets
- f.coplanarset set of points coplanar with this facet
- (includes near-inside points for later testing)
- f.outsideset set of points outside of this facet
- f.furthestdist distance to furthest point of outside set
- f.visitid marks visited facets during a loop
- f.replace replacement facet for to-be-deleted, visible facets
- f.samecycle,newcycle cycle of facets for merging into horizon facet
-
- see below for other flags and fields
-*/
-struct facetT {
-#if !qh_COMPUTEfurthest
- coordT furthestdist;/* distance to furthest point of outsideset */
-#endif
-#if qh_MAXoutside
- coordT maxoutside; /* max computed distance of point to facet
- Before QHULLfinished this is an approximation
- since maxdist not always set for mergefacet
- Actual outer plane is +DISTround and
- computed outer plane is +2*DISTround */
-#endif
- coordT offset; /* exact offset of hyperplane from origin */
- coordT *normal; /* normal of hyperplane, hull_dim coefficients */
- /* if tricoplanar, shared with a neighbor */
- union { /* in order of testing */
- realT area; /* area of facet, only in io.c if ->isarea */
- facetT *replace; /* replacement facet if ->visible and NEWfacets
- is NULL only if qh_mergedegen_redundant or interior */
- facetT *samecycle; /* cycle of facets from the same visible/horizon intersection,
- if ->newfacet */
- facetT *newcycle; /* in horizon facet, current samecycle of new facets */
- facetT *trivisible; /* visible facet for ->tricoplanar facets during qh_triangulate() */
- facetT *triowner; /* owner facet for ->tricoplanar, !isarea facets w/ ->keepcentrum */
- }f;
- coordT *center; /* centrum for convexity, qh CENTERtype == qh_AScentrum */
- /* Voronoi center, qh CENTERtype == qh_ASvoronoi */
- /* if tricoplanar, shared with a neighbor */
- facetT *previous; /* previous facet in the facet_list */
- facetT *next; /* next facet in the facet_list */
- setT *vertices; /* vertices for this facet, inverse sorted by ID
- if simplicial, 1st vertex was apex/furthest */
- setT *ridges; /* explicit ridges for nonsimplicial facets.
- for simplicial facets, neighbors define the ridges */
- setT *neighbors; /* neighbors of the facet. If simplicial, the kth
- neighbor is opposite the kth vertex, and the first
- neighbor is the horizon facet for the first vertex*/
- setT *outsideset; /* set of points outside this facet
- if non-empty, last point is furthest
- if NARROWhull, includes coplanars for partitioning*/
- setT *coplanarset; /* set of points coplanar with this facet
- > qh.min_vertex and <= facet->max_outside
- a point is assigned to the furthest facet
- if non-empty, last point is furthest away */
- unsigned visitid; /* visit_id, for visiting all neighbors,
- all uses are independent */
- unsigned id; /* unique identifier from qh facet_id */
- unsigned nummerge:9; /* number of merges */
-#define qh_MAXnummerge 511 /* 2^9-1, 32 flags total, see "flags:" in io.c */
- flagT tricoplanar:1; /* True if TRIangulate and simplicial and coplanar with a neighbor */
- /* all tricoplanars share the same ->center, ->normal, ->offset, ->maxoutside */
- /* all tricoplanars share the same apex */
- /* if ->degenerate, does not span facet (one logical ridge) */
- /* one tricoplanar has ->keepcentrum and ->coplanarset */
- /* during qh_triangulate, f.trivisible points to original facet */
- flagT newfacet:1; /* True if facet on qh newfacet_list (new or merged) */
- flagT visible:1; /* True if visible facet (will be deleted) */
- flagT toporient:1; /* True if created with top orientation
- after merging, use ridge orientation */
- flagT simplicial:1;/* True if simplicial facet, ->ridges may be implicit */
- flagT seen:1; /* used to perform operations only once, like visitid */
- flagT seen2:1; /* used to perform operations only once, like visitid */
- flagT flipped:1; /* True if facet is flipped */
- flagT upperdelaunay:1; /* True if facet is upper envelope of Delaunay triangulation */
- flagT notfurthest:1; /* True if last point of outsideset is not furthest*/
-
-/*-------- flags primarily for output ---------*/
- flagT good:1; /* True if a facet marked good for output */
- flagT isarea:1; /* True if facet->f.area is defined */
-
-/*-------- flags for merging ------------------*/
- flagT dupridge:1; /* True if duplicate ridge in facet */
- flagT mergeridge:1; /* True if facet or neighbor contains a qh_MERGEridge
- ->normal defined (also defined for mergeridge2) */
- flagT mergeridge2:1; /* True if neighbor contains a qh_MERGEridge (mark_dupridges */
- flagT coplanar:1; /* True if horizon facet is coplanar at last use */
- flagT mergehorizon:1; /* True if will merge into horizon (->coplanar) */
- flagT cycledone:1;/* True if mergecycle_all already done */
- flagT tested:1; /* True if facet convexity has been tested (false after merge */
- flagT keepcentrum:1; /* True if keep old centrum after a merge, or marks owner for ->tricoplanar */
- flagT newmerge:1; /* True if facet is newly merged for reducevertices */
- flagT degenerate:1; /* True if facet is degenerate (degen_mergeset or ->tricoplanar) */
- flagT redundant:1; /* True if facet is redundant (degen_mergeset) */
-};
-
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="ridgeT">-</a>
-
- ridgeT
- defines a ridge
-
- notes:
- a ridge is hull_dim-1 simplex between two neighboring facets. If the
- facets are non-simplicial, there may be more than one ridge between
- two facets. E.G. a 4-d hypercube has two triangles between each pair
- of neighboring facets.
-
- topological information:
- vertices a set of vertices
- top,bottom neighboring facets with orientation
-
- geometric information:
- tested True if ridge is clearly convex
- nonconvex True if ridge is non-convex
-*/
-struct ridgeT {
- setT *vertices; /* vertices belonging to this ridge, inverse sorted by ID
- NULL if a degen ridge (matchsame) */
- facetT *top; /* top facet this ridge is part of */
- facetT *bottom; /* bottom facet this ridge is part of */
- unsigned id:24; /* unique identifier, =>room for 8 flags, bit field matches qh.ridge_id */
- flagT seen:1; /* used to perform operations only once */
- flagT tested:1; /* True when ridge is tested for convexity */
- flagT nonconvex:1; /* True if getmergeset detected a non-convex neighbor
- only one ridge between neighbors may have nonconvex */
-};
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="vertexT">-</a>
-
- vertexT
- defines a vertex
-
- topological information:
- next,previous doubly-linked list of all vertices
- neighbors set of adjacent facets (only if qh.VERTEXneighbors)
-
- geometric information:
- point array of DIM3 coordinates
-*/
-struct vertexT {
- vertexT *next; /* next vertex in vertex_list */
- vertexT *previous; /* previous vertex in vertex_list */
- pointT *point; /* hull_dim coordinates (coordT) */
- setT *neighbors; /* neighboring facets of vertex, qh_vertexneighbors()
- inits in io.c or after first merge */
- unsigned visitid:31; /* for use with qh vertex_visit, size must match */
- flagT seen2:1; /* another seen flag */
- unsigned id:24; /* unique identifier, bit field matches qh.vertex_id */
- unsigned dim:4; /* dimension of point if non-zero, used by cpp */
- /* =>room for 4 flags */
- flagT seen:1; /* used to perform operations only once */
- flagT delridge:1; /* vertex was part of a deleted ridge */
- flagT deleted:1; /* true if vertex on qh del_vertices */
- flagT newlist:1; /* true if vertex on qh newvertex_list */
-};
-
-#define MAX_vdim 15 /* Maximum size of vertex->dim */
-
-/*======= -global variables -qh ============================*/
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh">-</a>
-
- qh
- all global variables for qhull are in qh, qhmem, and qhstat
-
- notes:
- qhmem is defined in mem.h, qhstat is defined in stat.h, qhrbox is defined in rboxpoints.h
- Access to qh_qh is via the "qh" macro. See qh_QHpointer in user.h
-
- All global variables for qhull are in qh, qhmem, and qhstat
- qh must be unique for each instance of qhull
- qhstat may be shared between qhull instances.
- qhmem may be shared across multiple instances of Qhull.
- Rbox uses global variables rbox_inuse and rbox, but does not persist data across calls.
-
- Qhull is not multithreaded. Global state could be stored in thread-local storage.
-*/
-
-extern int qhull_inuse;
-
-typedef struct qhT qhT;
-#if qh_QHpointer_dllimport
-#define qh qh_qh->
-__declspec(dllimport) extern qhT *qh_qh; /* allocated in global.c */
-#elif qh_QHpointer
-#define qh qh_qh->
-extern qhT *qh_qh; /* allocated in global.c */
-#elif qh_dllimport
-#define qh qh_qh.
-__declspec(dllimport) extern qhT qh_qh; /* allocated in global.c */
-#else
-#define qh qh_qh.
-extern qhT qh_qh;
-#endif
-
-struct qhT {
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-const">-</a>
-
- qh constants
- configuration flags and constants for Qhull
-
- notes:
- The user configures Qhull by defining flags. They are
- copied into qh by qh_setflags(). qh-quick.htm#options defines the flags.
-*/
- boolT ALLpoints; /* true 'Qs' if search all points for initial simplex */
- boolT ANGLEmerge; /* true 'Qa' if sort potential merges by angle */
- boolT APPROXhull; /* true 'Wn' if MINoutside set */
- realT MINoutside; /* 'Wn' min. distance for an outside point */
- boolT ANNOTATEoutput; /* true 'Ta' if annotate output with message codes */
- boolT ATinfinity; /* true 'Qz' if point num_points-1 is "at-infinity"
- for improving precision in Delaunay triangulations */
- boolT AVOIDold; /* true 'Q4' if avoid old->new merges */
- boolT BESToutside; /* true 'Qf' if partition points into best outsideset */
- boolT CDDinput; /* true 'Pc' if input uses CDD format (1.0/offset first) */
- boolT CDDoutput; /* true 'PC' if print normals in CDD format (offset first) */
- boolT CHECKfrequently; /* true 'Tc' if checking frequently */
- realT premerge_cos; /* 'A-n' cos_max when pre merging */
- realT postmerge_cos; /* 'An' cos_max when post merging */
- boolT DELAUNAY; /* true 'd' if computing DELAUNAY triangulation */
- boolT DOintersections; /* true 'Gh' if print hyperplane intersections */
- int DROPdim; /* drops dim 'GDn' for 4-d -> 3-d output */
- boolT FORCEoutput; /* true 'Po' if forcing output despite degeneracies */
- int GOODpoint; /* 1+n for 'QGn', good facet if visible/not(-) from point n*/
- pointT *GOODpointp; /* the actual point */
- boolT GOODthreshold; /* true if qh lower_threshold/upper_threshold defined
- false if qh SPLITthreshold */
- int GOODvertex; /* 1+n, good facet if vertex for point n */
- pointT *GOODvertexp; /* the actual point */
- boolT HALFspace; /* true 'Hn,n,n' if halfspace intersection */
- int IStracing; /* trace execution, 0=none, 1=least, 4=most, -1=events */
- int KEEParea; /* 'PAn' number of largest facets to keep */
- boolT KEEPcoplanar; /* true 'Qc' if keeping nearest facet for coplanar points */
- boolT KEEPinside; /* true 'Qi' if keeping nearest facet for inside points
- set automatically if 'd Qc' */
- int KEEPmerge; /* 'PMn' number of facets to keep with most merges */
- realT KEEPminArea; /* 'PFn' minimum facet area to keep */
- realT MAXcoplanar; /* 'Un' max distance below a facet to be coplanar*/
- boolT MERGEexact; /* true 'Qx' if exact merges (coplanar, degen, dupridge, flipped) */
- boolT MERGEindependent; /* true 'Q2' if merging independent sets */
- boolT MERGING; /* true if exact-, pre- or post-merging, with angle and centrum tests */
- realT premerge_centrum; /* 'C-n' centrum_radius when pre merging. Default is round-off */
- realT postmerge_centrum; /* 'Cn' centrum_radius when post merging. Default is round-off */
- boolT MERGEvertices; /* true 'Q3' if merging redundant vertices */
- realT MINvisible; /* 'Vn' min. distance for a facet to be visible */
- boolT NOnarrow; /* true 'Q10' if no special processing for narrow distributions */
- boolT NOnearinside; /* true 'Q8' if ignore near-inside points when partitioning */
- boolT NOpremerge; /* true 'Q0' if no defaults for C-0 or Qx */
- boolT ONLYgood; /* true 'Qg' if process points with good visible or horizon facets */
- boolT ONLYmax; /* true 'Qm' if only process points that increase max_outside */
- boolT PICKfurthest; /* true 'Q9' if process furthest of furthest points*/
- boolT POSTmerge; /* true if merging after buildhull (Cn or An) */
- boolT PREmerge; /* true if merging during buildhull (C-n or A-n) */
- /* NOTE: some of these names are similar to qh_PRINT names */
- boolT PRINTcentrums; /* true 'Gc' if printing centrums */
- boolT PRINTcoplanar; /* true 'Gp' if printing coplanar points */
- int PRINTdim; /* print dimension for Geomview output */
- boolT PRINTdots; /* true 'Ga' if printing all points as dots */
- boolT PRINTgood; /* true 'Pg' if printing good facets */
- boolT PRINTinner; /* true 'Gi' if printing inner planes */
- boolT PRINTneighbors; /* true 'PG' if printing neighbors of good facets */
- boolT PRINTnoplanes; /* true 'Gn' if printing no planes */
- boolT PRINToptions1st; /* true 'FO' if printing options to stderr */
- boolT PRINTouter; /* true 'Go' if printing outer planes */
- boolT PRINTprecision; /* false 'Pp' if not reporting precision problems */
- qh_PRINT PRINTout[qh_PRINTEND]; /* list of output formats to print */
- boolT PRINTridges; /* true 'Gr' if print ridges */
- boolT PRINTspheres; /* true 'Gv' if print vertices as spheres */
- boolT PRINTstatistics; /* true 'Ts' if printing statistics to stderr */
- boolT PRINTsummary; /* true 's' if printing summary to stderr */
- boolT PRINTtransparent; /* true 'Gt' if print transparent outer ridges */
- boolT PROJECTdelaunay; /* true if DELAUNAY, no readpoints() and
- need projectinput() for Delaunay in qh_init_B */
- int PROJECTinput; /* number of projected dimensions 'bn:0Bn:0' */
- boolT QUICKhelp; /* true if quick help message for degen input */
- boolT RANDOMdist; /* true if randomly change distplane and setfacetplane */
- realT RANDOMfactor; /* maximum random perturbation */
- realT RANDOMa; /* qh_randomfactor is randr * RANDOMa + RANDOMb */
- realT RANDOMb;
- boolT RANDOMoutside; /* true if select a random outside point */
- int REPORTfreq; /* buildtracing reports every n facets */
- int REPORTfreq2; /* tracemerging reports every REPORTfreq/2 facets */
- int RERUN; /* 'TRn' rerun qhull n times (qh.build_cnt) */
- int ROTATErandom; /* 'QRn' seed, 0 time, >= rotate input */
- boolT SCALEinput; /* true 'Qbk' if scaling input */
- boolT SCALElast; /* true 'Qbb' if scale last coord to max prev coord */
- boolT SETroundoff; /* true 'E' if qh DISTround is predefined */
- boolT SKIPcheckmax; /* true 'Q5' if skip qh_check_maxout */
- boolT SKIPconvex; /* true 'Q6' if skip convexity testing during pre-merge */
- boolT SPLITthresholds; /* true if upper_/lower_threshold defines a region
- used only for printing (!for qh ONLYgood) */
- int STOPcone; /* 'TCn' 1+n for stopping after cone for point n */
- /* also used by qh_build_withresart for err exit*/
- int STOPpoint; /* 'TVn' 'TV-n' 1+n for stopping after/before(-)
- adding point n */
- int TESTpoints; /* 'QTn' num of test points after qh.num_points. Test points always coplanar. */
- boolT TESTvneighbors; /* true 'Qv' if test vertex neighbors at end */
- int TRACElevel; /* 'Tn' conditional IStracing level */
- int TRACElastrun; /* qh.TRACElevel applies to last qh.RERUN */
- int TRACEpoint; /* 'TPn' start tracing when point n is a vertex */
- realT TRACEdist; /* 'TWn' start tracing when merge distance too big */
- int TRACEmerge; /* 'TMn' start tracing before this merge */
- boolT TRIangulate; /* true 'Qt' if triangulate non-simplicial facets */
- boolT TRInormals; /* true 'Q11' if triangulate duplicates normals (sets Qt) */
- boolT UPPERdelaunay; /* true 'Qu' if computing furthest-site Delaunay */
- boolT USEstdout; /* true 'Tz' if using stdout instead of stderr */
- boolT VERIFYoutput; /* true 'Tv' if verify output at end of qhull */
- boolT VIRTUALmemory; /* true 'Q7' if depth-first processing in buildhull */
- boolT VORONOI; /* true 'v' if computing Voronoi diagram */
-
- /*--------input constants ---------*/
- realT AREAfactor; /* 1/(hull_dim-1)! for converting det's to area */
- boolT DOcheckmax; /* true if calling qh_check_maxout (qh_initqhull_globals) */
- char *feasible_string; /* feasible point 'Hn,n,n' for halfspace intersection */
- coordT *feasible_point; /* as coordinates, both malloc'd */
- boolT GETarea; /* true 'Fa', 'FA', 'FS', 'PAn', 'PFn' if compute facet area/Voronoi volume in io.c */
- boolT KEEPnearinside; /* true if near-inside points in coplanarset */
- int hull_dim; /* dimension of hull, set by initbuffers */
- int input_dim; /* dimension of input, set by initbuffers */
- int num_points; /* number of input points */
- pointT *first_point; /* array of input points, see POINTSmalloc */
- boolT POINTSmalloc; /* true if qh first_point/num_points allocated */
- pointT *input_points; /* copy of original qh.first_point for input points for qh_joggleinput */
- boolT input_malloc; /* true if qh input_points malloc'd */
- char qhull_command[256];/* command line that invoked this program */
- int qhull_commandsiz2; /* size of qhull_command at qh_clear_outputflags */
- char rbox_command[256]; /* command line that produced the input points */
- char qhull_options[512];/* descriptive list of options */
- int qhull_optionlen; /* length of last line */
- int qhull_optionsiz; /* size of qhull_options at qh_build_withrestart */
- int qhull_optionsiz2; /* size of qhull_options at qh_clear_outputflags */
- int run_id; /* non-zero, random identifier for this instance of qhull */
- boolT VERTEXneighbors; /* true if maintaining vertex neighbors */
- boolT ZEROcentrum; /* true if 'C-0' or 'C-0 Qx'. sets ZEROall_ok */
- realT *upper_threshold; /* don't print if facet->normal[k]>=upper_threshold[k]
- must set either GOODthreshold or SPLITthreshold
- if Delaunay, default is 0.0 for upper envelope */
- realT *lower_threshold; /* don't print if facet->normal[k] <=lower_threshold[k] */
- realT *upper_bound; /* scale point[k] to new upper bound */
- realT *lower_bound; /* scale point[k] to new lower bound
- project if both upper_ and lower_bound == 0 */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-prec">-</a>
-
- qh precision constants
- precision constants for Qhull
-
- notes:
- qh_detroundoff() computes the maximum roundoff error for distance
- and other computations. It also sets default values for the
- qh constants above.
-*/
- realT ANGLEround; /* max round off error for angles */
- realT centrum_radius; /* max centrum radius for convexity (roundoff added) */
- realT cos_max; /* max cosine for convexity (roundoff added) */
- realT DISTround; /* max round off error for distances, 'E' overrides */
- realT MAXabs_coord; /* max absolute coordinate */
- realT MAXlastcoord; /* max last coordinate for qh_scalelast */
- realT MAXsumcoord; /* max sum of coordinates */
- realT MAXwidth; /* max rectilinear width of point coordinates */
- realT MINdenom_1; /* min. abs. value for 1/x */
- realT MINdenom; /* use divzero if denominator < MINdenom */
- realT MINdenom_1_2; /* min. abs. val for 1/x that allows normalization */
- realT MINdenom_2; /* use divzero if denominator < MINdenom_2 */
- realT MINlastcoord; /* min. last coordinate for qh_scalelast */
- boolT NARROWhull; /* set in qh_initialhull if angle < qh_MAXnarrow */
- realT *NEARzero; /* hull_dim array for near zero in gausselim */
- realT NEARinside; /* keep points for qh_check_maxout if close to facet */
- realT ONEmerge; /* max distance for merging simplicial facets */
- realT outside_err; /* application's epsilon for coplanar points
- qh_check_bestdist() qh_check_points() reports error if point outside */
- realT WIDEfacet; /* size of wide facet for skipping ridge in
- area computation and locking centrum */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-codetern">-</a>
-
- qh internal constants
- internal constants for Qhull
-*/
- char qhull[sizeof("qhull")]; /* "qhull" for checking ownership while debugging */
- jmp_buf errexit; /* exit label for qh_errexit, defined by setjmp() */
- char jmpXtra[40]; /* extra bytes in case jmp_buf is defined wrong by compiler */
- jmp_buf restartexit; /* restart label for qh_errexit, defined by setjmp() */
- char jmpXtra2[40]; /* extra bytes in case jmp_buf is defined wrong by compiler*/
- FILE *fin; /* pointer to input file, init by qh_meminit */
- FILE *fout; /* pointer to output file */
- FILE *ferr; /* pointer to error file */
- pointT *interior_point; /* center point of the initial simplex*/
- int normal_size; /* size in bytes for facet normals and point coords*/
- int center_size; /* size in bytes for Voronoi centers */
- int TEMPsize; /* size for small, temporary sets (in quick mem) */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-lists">-</a>
-
- qh facet and vertex lists
- defines lists of facets, new facets, visible facets, vertices, and
- new vertices. Includes counts, next ids, and trace ids.
- see:
- qh_resetlists()
-*/
- facetT *facet_list; /* first facet */
- facetT *facet_tail; /* end of facet_list (dummy facet) */
- facetT *facet_next; /* next facet for buildhull()
- previous facets do not have outside sets
- NARROWhull: previous facets may have coplanar outside sets for qh_outcoplanar */
- facetT *newfacet_list; /* list of new facets to end of facet_list */
- facetT *visible_list; /* list of visible facets preceeding newfacet_list,
- facet->visible set */
- int num_visible; /* current number of visible facets */
- unsigned tracefacet_id; /* set at init, then can print whenever */
- facetT *tracefacet; /* set in newfacet/mergefacet, undone in delfacet*/
- unsigned tracevertex_id; /* set at buildtracing, can print whenever */
- vertexT *tracevertex; /* set in newvertex, undone in delvertex*/
- vertexT *vertex_list; /* list of all vertices, to vertex_tail */
- vertexT *vertex_tail; /* end of vertex_list (dummy vertex) */
- vertexT *newvertex_list; /* list of vertices in newfacet_list, to vertex_tail
- all vertices have 'newlist' set */
- int num_facets; /* number of facets in facet_list
- includes visble faces (num_visible) */
- int num_vertices; /* number of vertices in facet_list */
- int num_outside; /* number of points in outsidesets (for tracing and RANDOMoutside)
- includes coplanar outsideset points for NARROWhull/qh_outcoplanar() */
- int num_good; /* number of good facets (after findgood_all) */
- unsigned facet_id; /* ID of next, new facet from newfacet() */
- unsigned ridge_id:24; /* ID of next, new ridge from newridge() */
- unsigned vertex_id:24; /* ID of next, new vertex from newvertex() */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-var">-</a>
-
- qh global variables
- defines minimum and maximum distances, next visit ids, several flags,
- and other global variables.
- initialize in qh_initbuild or qh_maxmin if used in qh_buildhull
-*/
- unsigned long hulltime; /* ignore time to set up input and randomize */
- /* use unsigned to avoid wrap-around errors */
- boolT ALLOWrestart; /* true if qh_precision can use qh.restartexit */
- int build_cnt; /* number of calls to qh_initbuild */
- qh_CENTER CENTERtype; /* current type of facet->center, qh_CENTER */
- int furthest_id; /* pointid of furthest point, for tracing */
- facetT *GOODclosest; /* closest facet to GOODthreshold in qh_findgood */
- boolT hasAreaVolume; /* true if totarea, totvol was defined by qh_getarea */
- boolT hasTriangulation; /* true if triangulation created by qh_triangulate */
- realT JOGGLEmax; /* set 'QJn' if randomly joggle input */
- boolT maxoutdone; /* set qh_check_maxout(), cleared by qh_addpoint() */
- realT max_outside; /* maximum distance from a point to a facet,
- before roundoff, not simplicial vertices
- actual outer plane is +DISTround and
- computed outer plane is +2*DISTround */
- realT max_vertex; /* maximum distance (>0) from vertex to a facet,
- before roundoff, due to a merge */
- realT min_vertex; /* minimum distance (<0) from vertex to a facet,
- before roundoff, due to a merge
- if qh.JOGGLEmax, qh_makenewplanes sets it
- recomputed if qh.DOcheckmax, default -qh.DISTround */
- boolT NEWfacets; /* true while visible facets invalid due to new or merge
- from makecone/attachnewfacets to deletevisible */
- boolT findbestnew; /* true if partitioning calls qh_findbestnew */
- boolT findbest_notsharp; /* true if new facets are at least 90 degrees */
- boolT NOerrexit; /* true if qh.errexit is not available */
- realT PRINTcradius; /* radius for printing centrums */
- realT PRINTradius; /* radius for printing vertex spheres and points */
- boolT POSTmerging; /* true when post merging */
- int printoutvar; /* temporary variable for qh_printbegin, etc. */
- int printoutnum; /* number of facets printed */
- boolT QHULLfinished; /* True after qhull() is finished */
- realT totarea; /* 'FA': total facet area computed by qh_getarea, hasAreaVolume */
- realT totvol; /* 'FA': total volume computed by qh_getarea, hasAreaVolume */
- unsigned int visit_id; /* unique ID for searching neighborhoods, */
- unsigned int vertex_visit:31; /* unique ID for searching vertices, reset with qh_buildtracing */
- boolT ZEROall_ok; /* True if qh_checkzero always succeeds */
- boolT WAScoplanar; /* True if qh_partitioncoplanar (qh_check_maxout) */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-set">-</a>
-
- qh global sets
- defines sets for merging, initial simplex, hashing, extra input points,
- and deleted vertices
-*/
- setT *facet_mergeset; /* temporary set of merges to be done */
- setT *degen_mergeset; /* temporary set of degenerate and redundant merges */
- setT *hash_table; /* hash table for matching ridges in qh_matchfacets
- size is setsize() */
- setT *other_points; /* additional points */
- setT *del_vertices; /* vertices to partition and delete with visible
- facets. Have deleted set for checkfacet */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-buf">-</a>
-
- qh global buffers
- defines buffers for maxtrix operations, input, and error messages
-*/
- coordT *gm_matrix; /* (dim+1)Xdim matrix for geom.c */
- coordT **gm_row; /* array of gm_matrix rows */
- char* line; /* malloc'd input line of maxline+1 chars */
- int maxline;
- coordT *half_space; /* malloc'd input array for halfspace (qh normal_size+coordT) */
- coordT *temp_malloc; /* malloc'd input array for points */
-
-/*-<a href="qh-globa.htm#TOC"
- >--------------------------------</a><a name="qh-static">-</a>
-
- qh static variables
- defines static variables for individual functions
-
- notes:
- do not use 'static' within a function. Multiple instances of qhull
- may exist.
-
- do not assume zero initialization, 'QPn' may cause a restart
-*/
- boolT ERREXITcalled; /* true during qh_errexit (prevents duplicate calls */
- boolT firstcentrum; /* for qh_printcentrum */
- boolT old_randomdist; /* save RANDOMdist flag during io, tracing, or statistics */
- setT *coplanarfacetset; /* set of coplanar facets for searching qh_findbesthorizon() */
- realT last_low; /* qh_scalelast parameters for qh_setdelaunay */
- realT last_high;
- realT last_newhigh;
- unsigned lastreport; /* for qh_buildtracing */
- int mergereport; /* for qh_tracemerging */
- qhstatT *old_qhstat; /* for saving qh_qhstat in save_qhull() and UsingLibQhull. Free with qh_free() */
- setT *old_tempstack; /* for saving qhmem.tempstack in save_qhull */
- int ridgeoutnum; /* number of ridges for 4OFF output (qh_printbegin,etc) */
-};
-
-/*=========== -macros- =========================*/
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="otherfacet_">-</a>
-
- otherfacet_(ridge, facet)
- return neighboring facet for a ridge in facet
-*/
-#define otherfacet_(ridge, facet) \
- (((ridge)->top == (facet)) ? (ridge)->bottom : (ridge)->top)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="getid_">-</a>
-
- getid_(p)
- return int ID for facet, ridge, or vertex
- return -1 if NULL
-*/
-#define getid_(p) ((p) ? (int)((p)->id) : -1)
-
-/*============== FORALL macros ===================*/
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLfacets">-</a>
-
- FORALLfacets { ... }
- assign 'facet' to each facet in qh.facet_list
-
- notes:
- uses 'facetT *facet;'
- assumes last facet is a sentinel
-
- see:
- FORALLfacet_( facetlist )
-*/
-#define FORALLfacets for (facet=qh facet_list;facet && facet->next;facet=facet->next)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLpoints">-</a>
-
- FORALLpoints { ... }
- assign 'point' to each point in qh.first_point, qh.num_points
-
- declare:
- coordT *point, *pointtemp;
-*/
-#define FORALLpoints FORALLpoint_(qh first_point, qh num_points)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLpoint_">-</a>
-
- FORALLpoint_( points, num) { ... }
- assign 'point' to each point in points array of num points
-
- declare:
- coordT *point, *pointtemp;
-*/
-#define FORALLpoint_(points, num) for (point= (points), \
- pointtemp= (points)+qh hull_dim*(num); point < pointtemp; point += qh hull_dim)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLvertices">-</a>
-
- FORALLvertices { ... }
- assign 'vertex' to each vertex in qh.vertex_list
-
- declare:
- vertexT *vertex;
-
- notes:
- assumes qh.vertex_list terminated with a sentinel
-*/
-#define FORALLvertices for (vertex=qh vertex_list;vertex && vertex->next;vertex= vertex->next)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHfacet_">-</a>
-
- FOREACHfacet_( facets ) { ... }
- assign 'facet' to each facet in facets
-
- declare:
- facetT *facet, **facetp;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHfacet_(facets) FOREACHsetelement_(facetT, facets, facet)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHneighbor_">-</a>
-
- FOREACHneighbor_( facet ) { ... }
- assign 'neighbor' to each neighbor in facet->neighbors
-
- FOREACHneighbor_( vertex ) { ... }
- assign 'neighbor' to each neighbor in vertex->neighbors
-
- declare:
- facetT *neighbor, **neighborp;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHneighbor_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighbor)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHpoint_">-</a>
-
- FOREACHpoint_( points ) { ... }
- assign 'point' to each point in points set
-
- declare:
- pointT *point, **pointp;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHpoint_(points) FOREACHsetelement_(pointT, points, point)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHridge_">-</a>
-
- FOREACHridge_( ridges ) { ... }
- assign 'ridge' to each ridge in ridges set
-
- declare:
- ridgeT *ridge, **ridgep;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHridge_(ridges) FOREACHsetelement_(ridgeT, ridges, ridge)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHvertex_">-</a>
-
- FOREACHvertex_( vertices ) { ... }
- assign 'vertex' to each vertex in vertices set
-
- declare:
- vertexT *vertex, **vertexp;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHvertex_(vertices) FOREACHsetelement_(vertexT, vertices,vertex)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHfacet_i_">-</a>
-
- FOREACHfacet_i_( facets ) { ... }
- assign 'facet' and 'facet_i' for each facet in facets set
-
- declare:
- facetT *facet;
- int facet_n, facet_i;
-
- see:
- <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
-*/
-#define FOREACHfacet_i_(facets) FOREACHsetelement_i_(facetT, facets, facet)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHneighbor_i_">-</a>
-
- FOREACHneighbor_i_( facet ) { ... }
- assign 'neighbor' and 'neighbor_i' for each neighbor in facet->neighbors
-
- FOREACHneighbor_i_( vertex ) { ... }
- assign 'neighbor' and 'neighbor_i' for each neighbor in vertex->neighbors
-
- declare:
- facetT *neighbor;
- int neighbor_n, neighbor_i;
-
- see:
- <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
-*/
-#define FOREACHneighbor_i_(facet) FOREACHsetelement_i_(facetT, facet->neighbors, neighbor)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHpoint_i_">-</a>
-
- FOREACHpoint_i_( points ) { ... }
- assign 'point' and 'point_i' for each point in points set
-
- declare:
- pointT *point;
- int point_n, point_i;
-
- see:
- <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
-*/
-#define FOREACHpoint_i_(points) FOREACHsetelement_i_(pointT, points, point)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHridge_i_">-</a>
-
- FOREACHridge_i_( ridges ) { ... }
- assign 'ridge' and 'ridge_i' for each ridge in ridges set
-
- declare:
- ridgeT *ridge;
- int ridge_n, ridge_i;
-
- see:
- <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
-*/
-#define FOREACHridge_i_(ridges) FOREACHsetelement_i_(ridgeT, ridges, ridge)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHvertex_i_">-</a>
-
- FOREACHvertex_i_( vertices ) { ... }
- assign 'vertex' and 'vertex_i' for each vertex in vertices set
-
- declare:
- vertexT *vertex;
- int vertex_n, vertex_i;
-
- see:
- <a href="qset.h#FOREACHsetelement_i_">FOREACHsetelement_i_</a>
-*/
-#define FOREACHvertex_i_(vertices) FOREACHsetelement_i_(vertexT, vertices,vertex)
-
-/********* -libqhull.c prototypes (duplicated from qhull_a.h) **********************/
-
-void qh_qhull(void);
-boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
-void qh_printsummary(FILE *fp);
-
-/********* -user.c prototypes (alphabetical) **********************/
-
-void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge);
-void qh_errprint(const char* string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex);
-int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
- char *qhull_cmd, FILE *outfile, FILE *errfile);
-void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall);
-void qh_printhelp_degenerate(FILE *fp);
-void qh_printhelp_narrowhull(FILE *fp, realT minangle);
-void qh_printhelp_singular(FILE *fp);
-void qh_user_memsizes(void);
-
-/********* -usermem.c prototypes (alphabetical) **********************/
-void qh_exit(int exitcode);
-void qh_free(void *mem);
-void *qh_malloc(size_t size);
-
-/********* -userprintf.c and userprintf_rbox.c prototypes **********************/
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
-
-/***** -geom.c/geom2.c/random.c prototypes (duplicated from geom.h, random.h) ****************/
-
-facetT *qh_findbest(pointT *point, facetT *startfacet,
- boolT bestoutside, boolT newfacets, boolT noupper,
- realT *dist, boolT *isoutside, int *numpart);
-facetT *qh_findbestnew(pointT *point, facetT *startfacet,
- realT *dist, boolT bestoutside, boolT *isoutside, int *numpart);
-boolT qh_gram_schmidt(int dim, realT **rows);
-void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane);
-void qh_printsummary(FILE *fp);
-void qh_projectinput(void);
-void qh_randommatrix(realT *buffer, int dim, realT **row);
-void qh_rotateinput(realT **rows);
-void qh_scaleinput(void);
-void qh_setdelaunay(int dim, int count, pointT *points);
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible);
-
-/***** -global.c prototypes (alphabetical) ***********************/
-
-unsigned long qh_clock(void);
-void qh_checkflags(char *command, char *hiddenflags);
-void qh_clear_outputflags(void);
-void qh_freebuffers(void);
-void qh_freeqhull(boolT allmem);
-void qh_freeqhull2(boolT allmem);
-void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]);
-void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc);
-void qh_init_qhull_command(int argc, char *argv[]);
-void qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-void qh_initflags(char *command);
-void qh_initqhull_buffers(void);
-void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc);
-void qh_initqhull_mem(void);
-void qh_initqhull_outputflags(void);
-void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile);
-void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile);
-void qh_initthresholds(char *command);
-void qh_option(const char *option, int *i, realT *r);
-#if qh_QHpointer
-void qh_restore_qhull(qhT **oldqh);
-qhT *qh_save_qhull(void);
-#endif
-
-/***** -io.c prototypes (duplicated from io.h) ***********************/
-
-void dfacet( unsigned id);
-void dvertex( unsigned id);
-void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall);
-void qh_produce_output(void);
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc);
-
-
-/********* -mem.c prototypes (duplicated from mem.h) **********************/
-
-void qh_meminit(FILE *ferr);
-void qh_memfreeshort(int *curlong, int *totlong);
-
-/********* -poly.c/poly2.c prototypes (duplicated from poly.h) **********************/
-
-void qh_check_output(void);
-void qh_check_points(void);
-setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets);
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
- realT *bestdist, boolT *isoutside);
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
-pointT *qh_point(int id);
-setT *qh_pointfacet(void /*qh.facet_list*/);
-int qh_pointid(pointT *point);
-setT *qh_pointvertex(void /*qh.facet_list*/);
-void qh_setvoronoi_all(void);
-void qh_triangulate(void /*qh facet_list*/);
-
-/********* -rboxpoints.c prototypes **********************/
-int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command);
-void qh_errexit_rbox(int exitcode);
-
-/********* -stat.c prototypes (duplicated from stat.h) **********************/
-
-void qh_collectstatistics(void);
-void qh_printallstatistics(FILE *fp, const char *string);
-
-#endif /* qhDEFlibqhull */
diff --git a/PyMca/Object3D/Object3DQhull/src/mem.c b/PyMca/Object3D/Object3DQhull/src/mem.c
deleted file mode 100644
index 2b865ae..0000000
--- a/PyMca/Object3D/Object3DQhull/src/mem.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/*<html><pre> -<a href="qh-mem.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- mem.c
- memory management routines for qhull
-
- This is a standalone program.
-
- To initialize memory:
-
- qh_meminit(stderr);
- qh_meminitbuffers(qh IStracing, qh_MEMalign, 7, qh_MEMbufsize,qh_MEMinitbuf);
- qh_memsize((int)sizeof(facetT));
- qh_memsize((int)sizeof(facetT));
- ...
- qh_memsetup();
-
- To free up all memory buffers:
- qh_memfreeshort(&curlong, &totlong);
-
- if qh_NOmem,
- malloc/free is used instead of mem.c
-
- notes:
- uses Quickfit algorithm (freelists for commonly allocated sizes)
- assumes small sizes for freelists (it discards the tail of memory buffers)
-
- see:
- qh-mem.htm and mem.h
- global.c (qh_initbuffers) for an example of using mem.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/mem.c#4 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "mem.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef qhDEFlibqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-#ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4127) /* conditional expression is constant */
-#pragma warning( disable : 4706) /* assignment within conditional function */
-#endif
-void qh_errexit(int exitcode, facetT *, ridgeT *);
-void qh_exit(int exitcode);
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-void qh_free(void *mem);
-void *qh_malloc(size_t size);
-#endif
-
-/*============ -global data structure ==============
- see mem.h for definition
-*/
-
-qhmemT qhmem= {0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0}; /* remove "= {0}" if this causes a compiler error */
-
-#ifndef qh_NOmem
-
-/*============= internal functions ==============*/
-
-static int qh_intcompare(const void *i, const void *j);
-
-/*========== functions in alphabetical order ======== */
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="intcompare">-</a>
-
- qh_intcompare( i, j )
- used by qsort and bsearch to compare two integers
-*/
-static int qh_intcompare(const void *i, const void *j) {
- return(*((const int *)i) - *((const int *)j));
-} /* intcompare */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="memalloc">-</a>
-
- qh_memalloc( insize )
- returns object of insize bytes
- qhmem is the global memory structure
-
- returns:
- pointer to allocated memory
- errors if insufficient memory
-
- notes:
- use explicit type conversion to avoid type warnings on some compilers
- actual object may be larger than insize
- use qh_memalloc_() for inline code for quick allocations
- logs allocations if 'T5'
-
- design:
- if size < qhmem.LASTsize
- if qhmem.freelists[size] non-empty
- return first object on freelist
- else
- round up request to size of qhmem.freelists[size]
- allocate new allocation buffer if necessary
- allocate object from allocation buffer
- else
- allocate object with qh_malloc() in user.c
-*/
-void *qh_memalloc(int insize) {
- void **freelistp, *newbuffer;
- int idx, size, n;
- int outsize, bufsize;
- void *object;
-
- if (insize<0) {
- qh_fprintf(qhmem.ferr, 6235, "qhull error (qh_memalloc): negative request size (%d). Did int overflow due to high-D?\n", insize); /* WARN64 */
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- if (insize>=0 && insize <= qhmem.LASTsize) {
- idx= qhmem.indextable[insize];
- outsize= qhmem.sizetable[idx];
- qhmem.totshort += outsize;
- freelistp= qhmem.freelists+idx;
- if ((object= *freelistp)) {
- qhmem.cntquick++;
- qhmem.totfree -= outsize;
- *freelistp= *((void **)*freelistp); /* replace freelist with next object */
-#ifdef qh_TRACEshort
- n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8141, "qh_mem %p n %8d alloc quick: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
- return(object);
- }else {
- qhmem.cntshort++;
- if (outsize > qhmem .freesize) {
- qhmem .totdropped += qhmem .freesize;
- if (!qhmem.curbuffer)
- bufsize= qhmem.BUFinit;
- else
- bufsize= qhmem.BUFsize;
- if (!(newbuffer= qh_malloc((size_t)bufsize))) {
- qh_fprintf(qhmem.ferr, 6080, "qhull error (qh_memalloc): insufficient memory to allocate short memory buffer (%d bytes)\n", bufsize);
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- *((void **)newbuffer)= qhmem.curbuffer; /* prepend newbuffer to curbuffer
- list */
- qhmem.curbuffer= newbuffer;
- size= (sizeof(void **) + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
- qhmem.freemem= (void *)((char *)newbuffer+size);
- qhmem.freesize= bufsize - size;
- qhmem.totbuffer += bufsize - size; /* easier to check */
- /* Periodically test totbuffer. It matches at beginning and exit of every call */
- n = qhmem.totshort + qhmem.totfree + qhmem.totdropped + qhmem.freesize - outsize;
- if (qhmem.totbuffer != n) {
- qh_fprintf(qhmem.ferr, 6212, "qh_memalloc internal error: short totbuffer %d != totshort+totfree... %d\n", qhmem.totbuffer, n);
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- }
- object= qhmem.freemem;
- qhmem.freemem= (void *)((char *)qhmem.freemem + outsize);
- qhmem.freesize -= outsize;
- qhmem.totunused += outsize - insize;
-#ifdef qh_TRACEshort
- n= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8140, "qh_mem %p n %8d alloc short: %d bytes (tot %d cnt %d)\n", object, n, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
- return object;
- }
- }else { /* long allocation */
- if (!qhmem.indextable) {
- qh_fprintf(qhmem.ferr, 6081, "qhull internal error (qh_memalloc): qhmem has not been initialized.\n");
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- outsize= insize;
- qhmem .cntlong++;
- qhmem .totlong += outsize;
- if (qhmem.maxlong < qhmem.totlong)
- qhmem.maxlong= qhmem.totlong;
- if (!(object= qh_malloc((size_t)outsize))) {
- qh_fprintf(qhmem.ferr, 6082, "qhull error (qh_memalloc): insufficient memory to allocate %d bytes\n", outsize);
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8057, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, outsize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
- }
- return(object);
-} /* memalloc */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="memfree">-</a>
-
- qh_memfree( object, insize )
- free up an object of size bytes
- size is insize from qh_memalloc
-
- notes:
- object may be NULL
- type checking warns if using (void **)object
- use qh_memfree_() for quick free's of small objects
-
- design:
- if size <= qhmem.LASTsize
- append object to corresponding freelist
- else
- call qh_free(object)
-*/
-void qh_memfree(void *object, int insize) {
- void **freelistp;
- int idx, outsize;
-
- if (!object)
- return;
- if (insize <= qhmem.LASTsize) {
- qhmem .freeshort++;
- idx= qhmem.indextable[insize];
- outsize= qhmem.sizetable[idx];
- qhmem .totfree += outsize;
- qhmem .totshort -= outsize;
- freelistp= qhmem.freelists + idx;
- *((void **)object)= *freelistp;
- *freelistp= object;
-#ifdef qh_TRACEshort
- idx= qhmem.cntshort+qhmem.cntquick+qhmem.freeshort;
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8142, "qh_mem %p n %8d free short: %d bytes (tot %d cnt %d)\n", object, idx, outsize, qhmem.totshort, qhmem.cntshort+qhmem.cntquick-qhmem.freeshort);
-#endif
- }else {
- qhmem .freelong++;
- qhmem .totlong -= insize;
- qh_free(object);
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8058, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
- }
-} /* memfree */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="memfreeshort">-</a>
-
- qh_memfreeshort( curlong, totlong )
- frees up all short and qhmem memory allocations
-
- returns:
- number and size of current long allocations
-
- see:
- qh_freeqhull(allMem)
- qh_memtotal(curlong, totlong, curshort, totshort, maxlong, totbuffer);
-*/
-void qh_memfreeshort(int *curlong, int *totlong) {
- void *buffer, *nextbuffer;
- FILE *ferr;
-
- *curlong= qhmem .cntlong - qhmem .freelong;
- *totlong= qhmem .totlong;
- for (buffer= qhmem.curbuffer; buffer; buffer= nextbuffer) {
- nextbuffer= *((void **) buffer);
- qh_free(buffer);
- }
- qhmem.curbuffer= NULL;
- if (qhmem .LASTsize) {
- qh_free(qhmem .indextable);
- qh_free(qhmem .freelists);
- qh_free(qhmem .sizetable);
- }
- ferr= qhmem.ferr;
- memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
- qhmem.ferr= ferr;
-} /* memfreeshort */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="meminit">-</a>
-
- qh_meminit( ferr )
- initialize qhmem and test sizeof( void*)
-*/
-void qh_meminit(FILE *ferr) {
-
- memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
- qhmem.ferr= ferr;
- if (sizeof(void*) < sizeof(int)) {
- qh_fprintf(ferr, 6083, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d. qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
- qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
- }
- if (sizeof(void*) > sizeof(ptr_intT)) {
- qh_fprintf(ferr, 6084, "qhull internal error (qh_meminit): sizeof(void*) %d > sizeof(ptr_intT) %d. Change ptr_intT in mem.h to 'long long'\n", (int)sizeof(void*), (int)sizeof(ptr_intT));
- qh_exit(qhmem_ERRqhull); /* can not use qh_errexit() */
- }
-} /* meminit */
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="meminitbuffers">-</a>
-
- qh_meminitbuffers( tracelevel, alignment, numsizes, bufsize, bufinit )
- initialize qhmem
- if tracelevel >= 5, trace memory allocations
- alignment= desired address alignment for memory allocations
- numsizes= number of freelists
- bufsize= size of additional memory buffers for short allocations
- bufinit= size of initial memory buffer for short allocations
-*/
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
- qhmem.IStracing= tracelevel;
- qhmem.NUMsizes= numsizes;
- qhmem.BUFsize= bufsize;
- qhmem.BUFinit= bufinit;
- qhmem.ALIGNmask= alignment-1;
- if (qhmem.ALIGNmask & ~qhmem.ALIGNmask) {
- qh_fprintf(qhmem.ferr, 6085, "qhull internal error (qh_meminit): memory alignment %d is not a power of 2\n", alignment);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- qhmem.sizetable= (int *) calloc((size_t)numsizes, sizeof(int));
- qhmem.freelists= (void **) calloc((size_t)numsizes, sizeof(void *));
- if (!qhmem.sizetable || !qhmem.freelists) {
- qh_fprintf(qhmem.ferr, 6086, "qhull error (qh_meminit): insufficient memory\n");
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- if (qhmem.IStracing >= 1)
- qh_fprintf(qhmem.ferr, 8059, "qh_meminitbuffers: memory initialized with alignment %d\n", alignment);
-} /* meminitbuffers */
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="memsetup">-</a>
-
- qh_memsetup()
- set up memory after running memsize()
-*/
-void qh_memsetup(void) {
- int k,i;
-
- qsort(qhmem.sizetable, (size_t)qhmem.TABLEsize, sizeof(int), qh_intcompare);
- qhmem.LASTsize= qhmem.sizetable[qhmem.TABLEsize-1];
- if (qhmem .LASTsize >= qhmem .BUFsize || qhmem.LASTsize >= qhmem .BUFinit) {
- qh_fprintf(qhmem.ferr, 6087, "qhull error (qh_memsetup): largest mem size %d is >= buffer size %d or initial buffer size %d\n",
- qhmem .LASTsize, qhmem .BUFsize, qhmem .BUFinit);
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- if (!(qhmem.indextable= (int *)qh_malloc((qhmem.LASTsize+1) * sizeof(int)))) {
- qh_fprintf(qhmem.ferr, 6088, "qhull error (qh_memsetup): insufficient memory\n");
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- for (k=qhmem.LASTsize+1; k--; )
- qhmem.indextable[k]= k;
- i= 0;
- for (k=0; k <= qhmem.LASTsize; k++) {
- if (qhmem.indextable[k] <= qhmem.sizetable[i])
- qhmem.indextable[k]= i;
- else
- qhmem.indextable[k]= ++i;
- }
-} /* memsetup */
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="memsize">-</a>
-
- qh_memsize( size )
- define a free list for this size
-*/
-void qh_memsize(int size) {
- int k;
-
- if (qhmem .LASTsize) {
- qh_fprintf(qhmem.ferr, 6089, "qhull error (qh_memsize): called after qhmem_setup\n");
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- size= (size + qhmem.ALIGNmask) & ~qhmem.ALIGNmask;
- for (k=qhmem.TABLEsize; k--; ) {
- if (qhmem.sizetable[k] == size)
- return;
- }
- if (qhmem.TABLEsize < qhmem.NUMsizes)
- qhmem.sizetable[qhmem.TABLEsize++]= size;
- else
- qh_fprintf(qhmem.ferr, 7060, "qhull warning (memsize): free list table has room for only %d sizes\n", qhmem.NUMsizes);
-} /* memsize */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="memstatistics">-</a>
-
- qh_memstatistics( fp )
- print out memory statistics
-
- Verifies that qhmem.totfree == sum of freelists
-*/
-void qh_memstatistics(FILE *fp) {
- int i, count, totfree= 0;
- void *object;
-
- for (i=0; i < qhmem.TABLEsize; i++) {
- count=0;
- for (object= qhmem .freelists[i]; object; object= *((void **)object))
- count++;
- totfree += qhmem.sizetable[i] * count;
- }
- if (totfree != qhmem .totfree) {
- qh_fprintf(qhmem.ferr, 6211, "qh_memstatistics internal error: totfree %d not equal to freelist total %d\n", qhmem.totfree, totfree);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- qh_fprintf(fp, 9278, "\nmemory statistics:\n\
-%7d quick allocations\n\
-%7d short allocations\n\
-%7d long allocations\n\
-%7d short frees\n\
-%7d long frees\n\
-%7d bytes of short memory in use\n\
-%7d bytes of short memory in freelists\n\
-%7d bytes of dropped short memory\n\
-%7d bytes of unused short memory (estimated)\n\
-%7d bytes of long memory allocated (max, except for input)\n\
-%7d bytes of long memory in use (in %d pieces)\n\
-%7d bytes of short memory buffers (minus links)\n\
-%7d bytes per short memory buffer (initially %d bytes)\n",
- qhmem .cntquick, qhmem .cntshort, qhmem .cntlong,
- qhmem .freeshort, qhmem .freelong,
- qhmem .totshort, qhmem .totfree,
- qhmem .totdropped + qhmem .freesize, qhmem .totunused,
- qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong,
- qhmem .totbuffer, qhmem .BUFsize, qhmem .BUFinit);
- if (qhmem.cntlarger) {
- qh_fprintf(fp, 9279, "%7d calls to qh_setlarger\n%7.2g average copy size\n",
- qhmem.cntlarger, ((float)qhmem.totlarger)/(float)qhmem.cntlarger);
- qh_fprintf(fp, 9280, " freelists(bytes->count):");
- }
- for (i=0; i < qhmem.TABLEsize; i++) {
- count=0;
- for (object= qhmem .freelists[i]; object; object= *((void **)object))
- count++;
- qh_fprintf(fp, 9281, " %d->%d", qhmem.sizetable[i], count);
- }
- qh_fprintf(fp, 9282, "\n\n");
-} /* memstatistics */
-
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="NOmem">-</a>
-
- qh_NOmem
- turn off quick-fit memory allocation
-
- notes:
- uses qh_malloc() and qh_free() instead
-*/
-#else /* qh_NOmem */
-
-void *qh_memalloc(int insize) {
- void *object;
-
- if (!(object= qh_malloc((size_t)insize))) {
- qh_fprintf(qhmem.ferr, 6090, "qhull error (qh_memalloc): insufficient memory\n");
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- qhmem .cntlong++;
- qhmem .totlong += insize;
- if (qhmem.maxlong < qhmem.totlong)
- qhmem.maxlong= qhmem.totlong;
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8060, "qh_mem %p n %8d alloc long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
- return object;
-}
-
-void qh_memfree(void *object, int insize) {
-
- if (!object)
- return;
- qh_free(object);
- qhmem .freelong++;
- qhmem .totlong -= insize;
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8061, "qh_mem %p n %8d free long: %d bytes (tot %d cnt %d)\n", object, qhmem.cntlong+qhmem.freelong, insize, qhmem.totlong, qhmem.cntlong-qhmem.freelong);
-}
-
-void qh_memfreeshort(int *curlong, int *totlong) {
- *totlong= qhmem .totlong;
- *curlong= qhmem .cntlong - qhmem .freelong;
- memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
-}
-
-void qh_meminit(FILE *ferr) {
-
- memset((char *)&qhmem, 0, sizeof(qhmem)); /* every field is 0, FALSE, NULL */
- qhmem.ferr= ferr;
- if (sizeof(void*) < sizeof(int)) {
- qh_fprintf(ferr, 6091, "qhull internal error (qh_meminit): sizeof(void*) %d < sizeof(int) %d. qset.c will not work\n", (int)sizeof(void*), (int)sizeof(int));
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
-}
-
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes, int bufsize, int bufinit) {
-
- qhmem.IStracing= tracelevel;
-}
-
-void qh_memsetup(void) {
-
-}
-
-void qh_memsize(int size) {
-
-}
-
-void qh_memstatistics(FILE *fp) {
-
- qh_fprintf(fp, 9409, "\nmemory statistics:\n\
-%7d long allocations\n\
-%7d long frees\n\
-%7d bytes of long memory allocated (max, except for input)\n\
-%7d bytes of long memory in use (in %d pieces)\n",
- qhmem .cntlong,
- qhmem .freelong,
- qhmem .maxlong, qhmem .totlong, qhmem .cntlong - qhmem .freelong);
-}
-
-#endif /* qh_NOmem */
-
-/*-<a href="qh-mem.htm#TOC"
->-------------------------------</a><a name="memtotlong">-</a>
-
- qh_memtotal( totlong, curlong, totshort, curshort, maxlong, totbuffer )
- Return the total, allocated long and short memory
-
- returns:
- Returns the total current bytes of long and short allocations
- Returns the current count of long and short allocations
- Returns the maximum long memory and total short buffer (minus one link per buffer)
- Does not error (UsingLibQhull.cpp)
-*/
-void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer) {
- *totlong= qhmem .totlong;
- *curlong= qhmem .cntlong - qhmem .freelong;
- *totshort= qhmem .totshort;
- *curshort= qhmem .cntshort + qhmem .cntquick - qhmem .freeshort;
- *maxlong= qhmem .maxlong;
- *totbuffer= qhmem .totbuffer;
-} /* memtotlong */
-
diff --git a/PyMca/Object3D/Object3DQhull/src/mem.h b/PyMca/Object3D/Object3DQhull/src/mem.h
deleted file mode 100644
index ad89de8..0000000
--- a/PyMca/Object3D/Object3DQhull/src/mem.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/*<html><pre> -<a href="qh-mem.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- mem.h
- prototypes for memory management functions
-
- see qh-mem.htm, mem.c and qset.h
-
- for error handling, writes message and calls
- qh_errexit(qhmem_ERRmem, NULL, NULL) if insufficient memory
- and
- qh_errexit(qhmem_ERRqhull, NULL, NULL) otherwise
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/mem.h#4 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFmem
-#define qhDEFmem 1
-
-#include <stdio.h>
-
-/*-<a href="qh-mem.htm#TOC"
- >-------------------------------</a><a name="NOmem">-</a>
-
- qh_NOmem
- turn off quick-fit memory allocation
-
- notes:
- mem.c implements Quickfit memory allocation for about 20% time
- savings. If it fails on your machine, try to locate the
- problem, and send the answer to qhull@qhull.org. If this can
- not be done, define qh_NOmem to use malloc/free instead.
-
- #define qh_NOmem
-*/
-
-/*-<a href="qh-mem.htm#TOC"
->-------------------------------</a><a name="TRACEshort">-</a>
-
-qh_TRACEshort
-Trace short and quick memory allocations at T5
-
-*/
-#define qh_TRACEshort
-
-/*-------------------------------------------
- to avoid bus errors, memory allocation must consider alignment requirements.
- malloc() automatically takes care of alignment. Since mem.c manages
- its own memory, we need to explicitly specify alignment in
- qh_meminitbuffers().
-
- A safe choice is sizeof(double). sizeof(float) may be used if doubles
- do not occur in data structures and pointers are the same size. Be careful
- of machines (e.g., DEC Alpha) with large pointers. If gcc is available,
- use __alignof__(double) or fmax_(__alignof__(float), __alignof__(void *)).
-
- see <a href="user.h#MEMalign">qh_MEMalign</a> in user.h for qhull's alignment
-*/
-
-#define qhmem_ERRmem 4 /* matches qh_ERRmem in libqhull.h */
-#define qhmem_ERRqhull 5 /* matches qh_ERRqhull in libqhull.h */
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="ptr_intT">-</a>
-
- ptr_intT
- for casting a void * to an integer-type that holds a pointer
- Used for integer expressions (e.g., computing qh_gethash() in poly.c)
-
- notes:
- WARN64 -- these notes indicate 64-bit issues
- On 64-bit machines, a pointer may be larger than an 'int'.
- qh_meminit()/mem.c checks that 'ptr_intT' holds a 'void*'
- ptr_intT is typically a signed value, but not necessarily so
- size_t is typically unsigned, but should match the parameter type
- Qhull uses int instead of size_t except for system calls such as malloc, qsort, qh_malloc, etc.
- This matches Qt convention and is easier to work with.
-*/
-#if _MSC_VER && defined(_WIN64)
-typedef long long ptr_intT;
-#else
-typedef long ptr_intT;
-#endif
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="qhmemT">-</a>
-
- qhmemT
- global memory structure for mem.c
-
- notes:
- users should ignore qhmem except for writing extensions
- qhmem is allocated in mem.c
-
- qhmem could be swapable like qh and qhstat, but then
- multiple qh's and qhmem's would need to keep in synch.
- A swapable qhmem would also waste memory buffers. As long
- as memory operations are atomic, there is no problem with
- multiple qh structures being active at the same time.
- If you need separate address spaces, you can swap the
- contents of qhmem.
-*/
-typedef struct qhmemT qhmemT;
-extern qhmemT qhmem;
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT; /* defined in qset.h */
-#endif
-
-/* Update qhmem in mem.c if add or remove fields */
-struct qhmemT { /* global memory management variables */
- int BUFsize; /* size of memory allocation buffer */
- int BUFinit; /* initial size of memory allocation buffer */
- int TABLEsize; /* actual number of sizes in free list table */
- int NUMsizes; /* maximum number of sizes in free list table */
- int LASTsize; /* last size in free list table */
- int ALIGNmask; /* worst-case alignment, must be 2^n-1 */
- void **freelists; /* free list table, linked by offset 0 */
- int *sizetable; /* size of each freelist */
- int *indextable; /* size->index table */
- void *curbuffer; /* current buffer, linked by offset 0 */
- void *freemem; /* free memory in curbuffer */
- int freesize; /* size of freemem in bytes */
- setT *tempstack; /* stack of temporary memory, managed by users */
- FILE *ferr; /* file for reporting errors, only user is qh_fprintf() */
- int IStracing; /* =5 if tracing memory allocations */
- int cntquick; /* count of quick allocations */
- /* Note: removing statistics doesn't effect speed */
- int cntshort; /* count of short allocations */
- int cntlong; /* count of long allocations */
- int freeshort; /* count of short memfrees */
- int freelong; /* count of long memfrees */
- int totbuffer; /* total short memory buffers minus buffer links */
- int totdropped; /* total dropped memory at end of short memory buffers (e.g., freesize) */
- int totfree; /* total size of free, short memory on freelists */
- int totlong; /* total size of long memory in use */
- int maxlong; /* maximum totlong */
- int totshort; /* total size of short memory in use */
- int totunused; /* total unused short memory (estimated, short size - request size of first allocations) */
- int cntlarger; /* count of setlarger's */
- int totlarger; /* total copied by setlarger */
-};
-
-
-/*==================== -macros ====================*/
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="memalloc_">-</a>
-
- qh_memalloc_(insize, object, type)
- returns object of size bytes
- assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-
-#if defined qh_NOmem
-#define qh_memalloc_(insize, freelistp, object, type) {\
- object= (type*)qh_memalloc(insize); }
-#elif defined qh_TRACEshort
-#define qh_memalloc_(insize, freelistp, object, type) {\
- freelistp= NULL; /* Avoid warnings */ \
- object= (type*)qh_memalloc(insize); }
-#else /* !qh_NOmem */
-
-#define qh_memalloc_(insize, freelistp, object, type) {\
- freelistp= qhmem.freelists + qhmem.indextable[insize];\
- if ((object= (type*)*freelistp)) {\
- qhmem.totshort += qhmem.sizetable[qhmem.indextable[insize]]; \
- qhmem.totfree -= qhmem.sizetable[qhmem.indextable[insize]]; \
- qhmem.cntquick++; \
- *freelistp= *((void **)*freelistp);\
- }else object= (type*)qh_memalloc(insize);}
-#endif
-
-/*-<a href="qh-mem.htm#TOC"
- >--------------------------------</a><a name="memfree_">-</a>
-
- qh_memfree_(object, insize)
- free up an object
-
- notes:
- object may be NULL
- assumes size<=qhmem.LASTsize and void **freelistp is a temp
-*/
-#if defined qh_NOmem
-#define qh_memfree_(object, insize, freelistp) {\
- qh_memfree(object, insize); }
-#elif defined qh_TRACEshort
-#define qh_memfree_(object, insize, freelistp) {\
- freelistp= NULL; /* Avoid warnings */ \
- qh_memfree(object, insize); }
-#else /* !qh_NOmem */
-
-#define qh_memfree_(object, insize, freelistp) {\
- if (object) { \
- qhmem .freeshort++;\
- freelistp= qhmem.freelists + qhmem.indextable[insize];\
- qhmem.totshort -= qhmem.sizetable[qhmem.indextable[insize]]; \
- qhmem.totfree += qhmem.sizetable[qhmem.indextable[insize]]; \
- *((void **)object)= *freelistp;\
- *freelistp= object;}}
-#endif
-
-/*=============== prototypes in alphabetical order ============*/
-
-void *qh_memalloc(int insize);
-void qh_memfree(void *object, int insize);
-void qh_memfreeshort(int *curlong, int *totlong);
-void qh_meminit(FILE *ferr);
-void qh_meminitbuffers(int tracelevel, int alignment, int numsizes,
- int bufsize, int bufinit);
-void qh_memsetup(void);
-void qh_memsize(int size);
-void qh_memstatistics(FILE *fp);
-void qh_memtotal(int *totlong, int *curlong, int *totshort, int *curshort, int *maxlong, int *totbuffer);
-
-#endif /* qhDEFmem */
diff --git a/PyMca/Object3D/Object3DQhull/src/merge.c b/PyMca/Object3D/Object3DQhull/src/merge.c
deleted file mode 100644
index 70c7f57..0000000
--- a/PyMca/Object3D/Object3DQhull/src/merge.c
+++ /dev/null
@@ -1,3623 +0,0 @@
-/*<html><pre> -<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="TOP">-</a>
-
- merge.c
- merges non-convex facets
-
- see qh-merge.htm and merge.h
-
- other modules call qh_premerge() and qh_postmerge()
-
- the user may call qh_postmerge() to perform additional merges.
-
- To remove deleted facets and vertices (qhull() in libqhull.c):
- qh_partitionvisible(!qh_ALL, &numoutside); // visible_list, newfacet_list
- qh_deletevisible(); // qh.visible_list
- qh_resetlists(False, qh_RESETvisible); // qh.visible_list newvertex_list newfacet_list
-
- assumes qh.CENTERtype= centrum
-
- merges occur in qh_mergefacet and in qh_mergecycle
- vertex->neighbors not set until the first merge occurs
-
- Copyright (c) 1993-2012 C.B. Barber.
- $Id: //main/2011/qhull/src/libqhull/merge.c#4 $$Change: 1490 $
- $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-#ifndef qh_NOmerge
-
-/*===== functions(alphabetical after premerge and postmerge) ======*/
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="premerge">-</a>
-
- qh_premerge( apex, maxcentrum )
- pre-merge nonconvex facets in qh.newfacet_list for apex
- maxcentrum defines coplanar and concave (qh_test_appendmerge)
-
- returns:
- deleted facets added to qh.visible_list with facet->visible set
-
- notes:
- uses globals, qh.MERGEexact, qh.PREmerge
-
- design:
- mark duplicate ridges in qh.newfacet_list
- merge facet cycles in qh.newfacet_list
- merge duplicate ridges and concave facets in qh.newfacet_list
- check merged facet cycles for degenerate and redundant facets
- merge degenerate and redundant facets
- collect coplanar and concave facets
- merge concave, coplanar, degenerate, and redundant facets
-*/
-void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
- boolT othermerge= False;
- facetT *newfacet;
-
- if (qh ZEROcentrum && qh_checkzero(!qh_ALL))
- return;
- trace2((qh ferr, 2008, "qh_premerge: premerge centrum %2.2g angle %2.2g for apex v%d facetlist f%d\n",
- maxcentrum, maxangle, apex->id, getid_(qh newfacet_list)));
- if (qh IStracing >= 4 && qh num_facets < 50)
- qh_printlists();
- qh centrum_radius= maxcentrum;
- qh cos_max= maxangle;
- qh degen_mergeset= qh_settemp(qh TEMPsize);
- qh facet_mergeset= qh_settemp(qh TEMPsize);
- if (qh hull_dim >=3) {
- qh_mark_dupridges(qh newfacet_list); /* facet_mergeset */
- qh_mergecycle_all(qh newfacet_list, &othermerge);
- qh_forcedmerges(&othermerge /* qh facet_mergeset */);
- FORALLnew_facets { /* test samecycle merges */
- if (!newfacet->simplicial && !newfacet->mergeridge)
- qh_degen_redundant_neighbors(newfacet, NULL);
- }
- if (qh_merge_degenredundant())
- othermerge= True;
- }else /* qh hull_dim == 2 */
- qh_mergecycle_all(qh newfacet_list, &othermerge);
- qh_flippedmerges(qh newfacet_list, &othermerge);
- if (!qh MERGEexact || zzval_(Ztotmerge)) {
- zinc_(Zpremergetot);
- qh POSTmerging= False;
- qh_getmergeset_initial(qh newfacet_list);
- qh_all_merges(othermerge, False);
- }
- qh_settempfree(&qh facet_mergeset);
- qh_settempfree(&qh degen_mergeset);
-} /* premerge */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="postmerge">-</a>
-
- qh_postmerge( reason, maxcentrum, maxangle, vneighbors )
- post-merge nonconvex facets as defined by maxcentrum and maxangle
- 'reason' is for reporting progress
- if vneighbors,
- calls qh_test_vneighbors at end of qh_all_merge
- if firstmerge,
- calls qh_reducevertices before qh_getmergeset
-
- returns:
- if first call (qh.visible_list != qh.facet_list),
- builds qh.facet_newlist, qh.newvertex_list
- deleted facets added to qh.visible_list with facet->visible
- qh.visible_list == qh.facet_list
-
- notes:
-
-
- design:
- if first call
- set qh.visible_list and qh.newfacet_list to qh.facet_list
- add all facets to qh.newfacet_list
- mark non-simplicial facets, facet->newmerge
- set qh.newvertext_list to qh.vertex_list
- add all vertices to qh.newvertex_list
- if a pre-merge occured
- set vertex->delridge {will retest the ridge}
- if qh.MERGEexact
- call qh_reducevertices()
- if no pre-merging
- merge flipped facets
- determine non-convex facets
- merge all non-convex facets
-*/
-void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
- boolT vneighbors) {
- facetT *newfacet;
- boolT othermerges= False;
- vertexT *vertex;
-
- if (qh REPORTfreq || qh IStracing) {
- qh_buildtracing(NULL, NULL);
- qh_printsummary(qh ferr);
- if (qh PRINTstatistics)
- qh_printallstatistics(qh ferr, "reason");
- qh_fprintf(qh ferr, 8062, "\n%s with 'C%.2g' and 'A%.2g'\n",
- reason, maxcentrum, maxangle);
- }
- trace2((qh ferr, 2009, "qh_postmerge: postmerge. test vneighbors? %d\n",
- vneighbors));
- qh centrum_radius= maxcentrum;
- qh cos_max= maxangle;
- qh POSTmerging= True;
- qh degen_mergeset= qh_settemp(qh TEMPsize);
- qh facet_mergeset= qh_settemp(qh TEMPsize);
- if (qh visible_list != qh facet_list) { /* first call */
- qh NEWfacets= True;
- qh visible_list= qh newfacet_list= qh facet_list;
- FORALLnew_facets {
- newfacet->newfacet= True;
- if (!newfacet->simplicial)
- newfacet->newmerge= True;
- zinc_(Zpostfacets);
- }
- qh newvertex_list= qh vertex_list;
- FORALLvertices
- vertex->newlist= True;
- if (qh VERTEXneighbors) { /* a merge has occurred */
- FORALLvertices
- vertex->delridge= True; /* test for redundant, needed? */
- if (qh MERGEexact) {
- if (qh hull_dim <= qh_DIMreduceBuild)
- qh_reducevertices(); /* was skipped during pre-merging */
- }
- }
- if (!qh PREmerge && !qh MERGEexact)
- qh_flippedmerges(qh newfacet_list, &othermerges);
- }
- qh_getmergeset_initial(qh newfacet_list);
- qh_all_merges(False, vneighbors);
- qh_settempfree(&qh facet_mergeset);
- qh_settempfree(&qh degen_mergeset);
-} /* post_merge */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="all_merges">-</a>
-
- qh_all_merges( othermerge, vneighbors )
- merge all non-convex facets
-
- set othermerge if already merged facets (for qh_reducevertices)
- if vneighbors
- tests vertex neighbors for convexity at end
- qh.facet_mergeset lists the non-convex ridges in qh_newfacet_list
- qh.degen_mergeset is defined
- if qh.MERGEexact && !qh.POSTmerging,
- does not merge coplanar facets
-
- returns:
- deleted facets added to qh.visible_list with facet->visible
- deleted vertices added qh.delvertex_list with vertex->delvertex
-
- notes:
- unless !qh.MERGEindependent,
- merges facets in independent sets
- uses qh.newfacet_list as argument since merges call qh_removefacet()
-
- design:
- while merges occur
- for each merge in qh.facet_mergeset
- unless one of the facets was already merged in this pass
- merge the facets
- test merged facets for additional merges
- add merges to qh.facet_mergeset
- if vertices record neighboring facets
- rename redundant vertices
- update qh.facet_mergeset
- if vneighbors ??
- tests vertex neighbors for convexity at end
-*/
-void qh_all_merges(boolT othermerge, boolT vneighbors) {
- facetT *facet1, *facet2;
- mergeT *merge;
- boolT wasmerge= True, isreduce;
- void **freelistp; /* used !qh_NOmem */
- vertexT *vertex;
- mergeType mergetype;
- int numcoplanar=0, numconcave=0, numdegenredun= 0, numnewmerges= 0;
-
- trace2((qh ferr, 2010, "qh_all_merges: starting to merge facets beginning from f%d\n",
- getid_(qh newfacet_list)));
- while (True) {
- wasmerge= False;
- while (qh_setsize(qh facet_mergeset)) {
- while ((merge= (mergeT*)qh_setdellast(qh facet_mergeset))) {
- facet1= merge->facet1;
- facet2= merge->facet2;
- mergetype= merge->type;
- qh_memfree_(merge, (int)sizeof(mergeT), freelistp);
- if (facet1->visible || facet2->visible) /*deleted facet*/
- continue;
- if ((facet1->newfacet && !facet1->tested)
- || (facet2->newfacet && !facet2->tested)) {
- if (qh MERGEindependent && mergetype <= MRGanglecoplanar)
- continue; /* perform independent sets of merges */
- }
- qh_merge_nonconvex(facet1, facet2, mergetype);
- numdegenredun += qh_merge_degenredundant();
- numnewmerges++;
- wasmerge= True;
- if (mergetype == MRGconcave)
- numconcave++;
- else /* MRGcoplanar or MRGanglecoplanar */
- numcoplanar++;
- } /* while setdellast */
- if (qh POSTmerging && qh hull_dim <= qh_DIMreduceBuild
- && numnewmerges > qh_MAXnewmerges) {
- numnewmerges= 0;
- qh_reducevertices(); /* otherwise large post merges too slow */
- }
- qh_getmergeset(qh newfacet_list); /* facet_mergeset */
- } /* while mergeset */
- if (qh VERTEXneighbors) {
- isreduce= False;
- if (qh hull_dim >=4 && qh POSTmerging) {
- FORALLvertices
- vertex->delridge= True;
- isreduce= True;
- }
- if ((wasmerge || othermerge) && (!qh MERGEexact || qh POSTmerging)
- && qh hull_dim <= qh_DIMreduceBuild) {
- othermerge= False;
- isreduce= True;
- }
- if (isreduce) {
- if (qh_reducevertices()) {
- qh_getmergeset(qh newfacet_list); /* facet_mergeset */
- continue;
- }
- }
- }
- if (vneighbors && qh_test_vneighbors(/* qh newfacet_list */))
- continue;
- break;
- } /* while (True) */
- if (qh CHECKfrequently && !qh MERGEexact) {
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- qh_checkconvex(qh newfacet_list, qh_ALGORITHMfault);
- /* qh_checkconnect(); [this is slow and it changes the facet order] */
- qh RANDOMdist= qh old_randomdist;
- }
- trace1((qh ferr, 1009, "qh_all_merges: merged %d coplanar facets %d concave facets and %d degen or redundant facets.\n",
- numcoplanar, numconcave, numdegenredun));
- if (qh IStracing >= 4 && qh num_facets < 50)
- qh_printlists();
-} /* all_merges */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="appendmergeset">-</a>
-
- qh_appendmergeset( facet, neighbor, mergetype, angle )
- appends an entry to qh.facet_mergeset or qh.degen_mergeset
-
- angle ignored if NULL or !qh.ANGLEmerge
-
- returns:
- merge appended to facet_mergeset or degen_mergeset
- sets ->degenerate or ->redundant if degen_mergeset
-
- see:
- qh_test_appendmerge()
-
- design:
- allocate merge entry
- if regular merge
- append to qh.facet_mergeset
- else if degenerate merge and qh.facet_mergeset is all degenerate
- append to qh.degen_mergeset
- else if degenerate merge
- prepend to qh.degen_mergeset
- else if redundant merge
- append to qh.degen_mergeset
-*/
-void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle) {
- mergeT *merge, *lastmerge;
- void **freelistp; /* used !qh_NOmem */
-
- if (facet->redundant)
- return;
- if (facet->degenerate && mergetype == MRGdegen)
- return;
- qh_memalloc_((int)sizeof(mergeT), freelistp, merge, mergeT);
- merge->facet1= facet;
- merge->facet2= neighbor;
- merge->type= mergetype;
- if (angle && qh ANGLEmerge)
- merge->angle= *angle;
- if (mergetype < MRGdegen)
- qh_setappend(&(qh facet_mergeset), merge);
- else if (mergetype == MRGdegen) {
- facet->degenerate= True;
- if (!(lastmerge= (mergeT*)qh_setlast(qh degen_mergeset))
- || lastmerge->type == MRGdegen)
- qh_setappend(&(qh degen_mergeset), merge);
- else
- qh_setaddnth(&(qh degen_mergeset), 0, merge);
- }else if (mergetype == MRGredundant) {
- facet->redundant= True;
- qh_setappend(&(qh degen_mergeset), merge);
- }else /* mergetype == MRGmirror */ {
- if (facet->redundant || neighbor->redundant) {
- qh_fprintf(qh ferr, 6092, "qhull error (qh_appendmergeset): facet f%d or f%d is already a mirrored facet\n",
- facet->id, neighbor->id);
- qh_errexit2 (qh_ERRqhull, facet, neighbor);
- }
- if (!qh_setequal(facet->vertices, neighbor->vertices)) {
- qh_fprintf(qh ferr, 6093, "qhull error (qh_appendmergeset): mirrored facets f%d and f%d do not have the same vertices\n",
- facet->id, neighbor->id);
- qh_errexit2 (qh_ERRqhull, facet, neighbor);
- }
- facet->redundant= True;
- neighbor->redundant= True;
- qh_setappend(&(qh degen_mergeset), merge);
- }
-} /* appendmergeset */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="basevertices">-</a>
-
- qh_basevertices( samecycle )
- return temporary set of base vertices for samecycle
- samecycle is first facet in the cycle
- assumes apex is SETfirst_( samecycle->vertices )
-
- returns:
- vertices(settemp)
- all ->seen are cleared
-
- notes:
- uses qh_vertex_visit;
-
- design:
- for each facet in samecycle
- for each unseen vertex in facet->vertices
- append to result
-*/
-setT *qh_basevertices(facetT *samecycle) {
- facetT *same;
- vertexT *apex, *vertex, **vertexp;
- setT *vertices= qh_settemp(qh TEMPsize);
-
- apex= SETfirstt_(samecycle->vertices, vertexT);
- apex->visitid= ++qh vertex_visit;
- FORALLsame_cycle_(samecycle) {
- if (same->mergeridge)
- continue;
- FOREACHvertex_(same->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- qh_setappend(&vertices, vertex);
- vertex->visitid= qh vertex_visit;
- vertex->seen= False;
- }
- }
- }
- trace4((qh ferr, 4019, "qh_basevertices: found %d vertices\n",
- qh_setsize(vertices)));
- return vertices;
-} /* basevertices */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="checkconnect">-</a>
-
- qh_checkconnect()
- check that new facets are connected
- new facets are on qh.newfacet_list
-
- notes:
- this is slow and it changes the order of the facets
- uses qh.visit_id
-
- design:
- move first new facet to end of qh.facet_list
- for all newly appended facets
- append unvisited neighbors to end of qh.facet_list
- for all new facets
- report error if unvisited
-*/
-void qh_checkconnect(void /* qh newfacet_list */) {
- facetT *facet, *newfacet, *errfacet= NULL, *neighbor, **neighborp;
-
- facet= qh newfacet_list;
- qh_removefacet(facet);
- qh_appendfacet(facet);
- facet->visitid= ++qh visit_id;
- FORALLfacet_(facet) {
- FOREACHneighbor_(facet) {
- if (neighbor->visitid != qh visit_id) {
- qh_removefacet(neighbor);
- qh_appendfacet(neighbor);
- neighbor->visitid= qh visit_id;
- }
- }
- }
- FORALLnew_facets {
- if (newfacet->visitid == qh visit_id)
- break;
- qh_fprintf(qh ferr, 6094, "qhull error: f%d is not attached to the new facets\n",
- newfacet->id);
- errfacet= newfacet;
- }
- if (errfacet)
- qh_errexit(qh_ERRqhull, errfacet, NULL);
-} /* checkconnect */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="checkzero">-</a>
-
- qh_checkzero( testall )
- check that facets are clearly convex for qh.DISTround with qh.MERGEexact
-
- if testall,
- test all facets for qh.MERGEexact post-merging
- else
- test qh.newfacet_list
-
- if qh.MERGEexact,
- allows coplanar ridges
- skips convexity test while qh.ZEROall_ok
-
- returns:
- True if all facets !flipped, !dupridge, normal
- if all horizon facets are simplicial
- if all vertices are clearly below neighbor
- if all opposite vertices of horizon are below
- clears qh.ZEROall_ok if any problems or coplanar facets
-
- notes:
- uses qh.vertex_visit
- horizon facets may define multiple new facets
-
- design:
- for all facets in qh.newfacet_list or qh.facet_list
- check for flagged faults (flipped, etc.)
- for all facets in qh.newfacet_list or qh.facet_list
- for each neighbor of facet
- skip horizon facets for qh.newfacet_list
- test the opposite vertex
- if qh.newfacet_list
- test the other vertices in the facet's horizon facet
-*/
-boolT qh_checkzero(boolT testall) {
- facetT *facet, *neighbor, **neighborp;
- facetT *horizon, *facetlist;
- int neighbor_i;
- vertexT *vertex, **vertexp;
- realT dist;
-
- if (testall)
- facetlist= qh facet_list;
- else {
- facetlist= qh newfacet_list;
- FORALLfacet_(facetlist) {
- horizon= SETfirstt_(facet->neighbors, facetT);
- if (!horizon->simplicial)
- goto LABELproblem;
- if (facet->flipped || facet->dupridge || !facet->normal)
- goto LABELproblem;
- }
- if (qh MERGEexact && qh ZEROall_ok) {
- trace2((qh ferr, 2011, "qh_checkzero: skip convexity check until first pre-merge\n"));
- return True;
- }
- }
- FORALLfacet_(facetlist) {
- qh vertex_visit++;
- neighbor_i= 0;
- horizon= NULL;
- FOREACHneighbor_(facet) {
- if (!neighbor_i && !testall) {
- horizon= neighbor;
- neighbor_i++;
- continue; /* horizon facet tested in qh_findhorizon */
- }
- vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
- vertex->visitid= qh vertex_visit;
- zzinc_(Zdistzero);
- qh_distplane(vertex->point, neighbor, &dist);
- if (dist >= -qh DISTround) {
- qh ZEROall_ok= False;
- if (!qh MERGEexact || testall || dist > qh DISTround)
- goto LABELnonconvex;
- }
- }
- if (!testall) {
- FOREACHvertex_(horizon->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- zzinc_(Zdistzero);
- qh_distplane(vertex->point, facet, &dist);
- if (dist >= -qh DISTround) {
- qh ZEROall_ok= False;
- if (!qh MERGEexact || dist > qh DISTround)
- goto LABELnonconvex;
- }
- break;
- }
- }
- }
- }
- trace2((qh ferr, 2012, "qh_checkzero: testall %d, facets are %s\n", testall,
- (qh MERGEexact && !testall) ?
- "not concave, flipped, or duplicate ridged" : "clearly convex"));
- return True;
-
- LABELproblem:
- qh ZEROall_ok= False;
- trace2((qh ferr, 2013, "qh_checkzero: facet f%d needs pre-merging\n",
- facet->id));
- return False;
-
- LABELnonconvex:
- trace2((qh ferr, 2014, "qh_checkzero: facet f%d and f%d are not clearly convex. v%d dist %.2g\n",
- facet->id, neighbor->id, vertex->id, dist));
- return False;
-} /* checkzero */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="compareangle">-</a>
-
- qh_compareangle( angle1, angle2 )
- used by qsort() to order merges by angle
-*/
-int qh_compareangle(const void *p1, const void *p2) {
- const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
-
- return((a->angle > b->angle) ? 1 : -1);
-} /* compareangle */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="comparemerge">-</a>
-
- qh_comparemerge( merge1, merge2 )
- used by qsort() to order merges
-*/
-int qh_comparemerge(const void *p1, const void *p2) {
- const mergeT *a= *((mergeT *const*)p1), *b= *((mergeT *const*)p2);
-
- return(a->type - b->type);
-} /* comparemerge */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="comparevisit">-</a>
-
- qh_comparevisit( vertex1, vertex2 )
- used by qsort() to order vertices by their visitid
-*/
-int qh_comparevisit(const void *p1, const void *p2) {
- const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
-
- return(a->visitid - b->visitid);
-} /* comparevisit */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="copynonconvex">-</a>
-
- qh_copynonconvex( atridge )
- set non-convex flag on other ridges (if any) between same neighbors
-
- notes:
- may be faster if use smaller ridge set
-
- design:
- for each ridge of atridge's top facet
- if ridge shares the same neighbor
- set nonconvex flag
-*/
-void qh_copynonconvex(ridgeT *atridge) {
- facetT *facet, *otherfacet;
- ridgeT *ridge, **ridgep;
-
- facet= atridge->top;
- otherfacet= atridge->bottom;
- FOREACHridge_(facet->ridges) {
- if (otherfacet == otherfacet_(ridge, facet) && ridge != atridge) {
- ridge->nonconvex= True;
- trace4((qh ferr, 4020, "qh_copynonconvex: moved nonconvex flag from r%d to r%d\n",
- atridge->id, ridge->id));
- break;
- }
- }
-} /* copynonconvex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="degen_redundant_facet">-</a>
-
- qh_degen_redundant_facet( facet )
- check facet for degen. or redundancy
-
- notes:
- bumps vertex_visit
- called if a facet was redundant but no longer is (qh_merge_degenredundant)
- qh_appendmergeset() only appends first reference to facet (i.e., redundant)
-
- see:
- qh_degen_redundant_neighbors()
-
- design:
- test for redundant neighbor
- test for degenerate facet
-*/
-void qh_degen_redundant_facet(facetT *facet) {
- vertexT *vertex, **vertexp;
- facetT *neighbor, **neighborp;
-
- trace4((qh ferr, 4021, "qh_degen_redundant_facet: test facet f%d for degen/redundant\n",
- facet->id));
- FOREACHneighbor_(facet) {
- qh vertex_visit++;
- FOREACHvertex_(neighbor->vertices)
- vertex->visitid= qh vertex_visit;
- FOREACHvertex_(facet->vertices) {
- if (vertex->visitid != qh vertex_visit)
- break;
- }
- if (!vertex) {
- qh_appendmergeset(facet, neighbor, MRGredundant, NULL);
- trace2((qh ferr, 2015, "qh_degen_redundant_facet: f%d is contained in f%d. merge\n", facet->id, neighbor->id));
- return;
- }
- }
- if (qh_setsize(facet->neighbors) < qh hull_dim) {
- qh_appendmergeset(facet, facet, MRGdegen, NULL);
- trace2((qh ferr, 2016, "qh_degen_redundant_neighbors: f%d is degenerate.\n", facet->id));
- }
-} /* degen_redundant_facet */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="degen_redundant_neighbors">-</a>
-
- qh_degen_redundant_neighbors( facet, delfacet, )
- append degenerate and redundant neighbors to facet_mergeset
- if delfacet,
- only checks neighbors of both delfacet and facet
- also checks current facet for degeneracy
-
- notes:
- bumps vertex_visit
- called for each qh_mergefacet() and qh_mergecycle()
- merge and statistics occur in merge_nonconvex
- qh_appendmergeset() only appends first reference to facet (i.e., redundant)
- it appends redundant facets after degenerate ones
-
- a degenerate facet has fewer than hull_dim neighbors
- a redundant facet's vertices is a subset of its neighbor's vertices
- tests for redundant merges first (appendmergeset is nop for others)
- in a merge, only needs to test neighbors of merged facet
-
- see:
- qh_merge_degenredundant() and qh_degen_redundant_facet()
-
- design:
- test for degenerate facet
- test for redundant neighbor
- test for degenerate neighbor
-*/
-void qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet) {
- vertexT *vertex, **vertexp;
- facetT *neighbor, **neighborp;
- int size;
-
- trace4((qh ferr, 4022, "qh_degen_redundant_neighbors: test neighbors of f%d with delfacet f%d\n",
- facet->id, getid_(delfacet)));
- if ((size= qh_setsize(facet->neighbors)) < qh hull_dim) {
- qh_appendmergeset(facet, facet, MRGdegen, NULL);
- trace2((qh ferr, 2017, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors.\n", facet->id, size));
- }
- if (!delfacet)
- delfacet= facet;
- qh vertex_visit++;
- FOREACHvertex_(facet->vertices)
- vertex->visitid= qh vertex_visit;
- FOREACHneighbor_(delfacet) {
- /* uses early out instead of checking vertex count */
- if (neighbor == facet)
- continue;
- FOREACHvertex_(neighbor->vertices) {
- if (vertex->visitid != qh vertex_visit)
- break;
- }
- if (!vertex) {
- qh_appendmergeset(neighbor, facet, MRGredundant, NULL);
- trace2((qh ferr, 2018, "qh_degen_redundant_neighbors: f%d is contained in f%d. merge\n", neighbor->id, facet->id));
- }
- }
- FOREACHneighbor_(delfacet) { /* redundant merges occur first */
- if (neighbor == facet)
- continue;
- if ((size= qh_setsize(neighbor->neighbors)) < qh hull_dim) {
- qh_appendmergeset(neighbor, neighbor, MRGdegen, NULL);
- trace2((qh ferr, 2019, "qh_degen_redundant_neighbors: f%d is degenerate with %d neighbors. Neighbor of f%d.\n", neighbor->id, size, facet->id));
- }
- }
-} /* degen_redundant_neighbors */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="find_newvertex">-</a>
-
- qh_find_newvertex( oldvertex, vertices, ridges )
- locate new vertex for renaming old vertex
- vertices is a set of possible new vertices
- vertices sorted by number of deleted ridges
-
- returns:
- newvertex or NULL
- each ridge includes both vertex and oldvertex
- vertices sorted by number of deleted ridges
-
- notes:
- modifies vertex->visitid
- new vertex is in one of the ridges
- renaming will not cause a duplicate ridge
- renaming will minimize the number of deleted ridges
- newvertex may not be adjacent in the dual (though unlikely)
-
- design:
- for each vertex in vertices
- set vertex->visitid to number of references in ridges
- remove unvisited vertices
- set qh.vertex_visit above all possible values
- sort vertices by number of references in ridges
- add each ridge to qh.hash_table
- for each vertex in vertices
- look for a vertex that would not cause a duplicate ridge after a rename
-*/
-vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges) {
- vertexT *vertex, **vertexp;
- setT *newridges;
- ridgeT *ridge, **ridgep;
- int size, hashsize;
- int hash;
-
-#ifndef qh_NOtrace
- if (qh IStracing >= 4) {
- qh_fprintf(qh ferr, 8063, "qh_find_newvertex: find new vertex for v%d from ",
- oldvertex->id);
- FOREACHvertex_(vertices)
- qh_fprintf(qh ferr, 8064, "v%d ", vertex->id);
- FOREACHridge_(ridges)
- qh_fprintf(qh ferr, 8065, "r%d ", ridge->id);
- qh_fprintf(qh ferr, 8066, "\n");
- }
-#endif
- FOREACHvertex_(vertices)
- vertex->visitid= 0;
- FOREACHridge_(ridges) {
- FOREACHvertex_(ridge->vertices)
- vertex->visitid++;
- }
- FOREACHvertex_(vertices) {
- if (!vertex->visitid) {
- qh_setdelnth(vertices, SETindex_(vertices,vertex));
- vertexp--; /* repeat since deleted this vertex */
- }
- }
- qh vertex_visit += (unsigned int)qh_setsize(ridges);
- if (!qh_setsize(vertices)) {
- trace4((qh ferr, 4023, "qh_find_newvertex: vertices not in ridges for v%d\n",
- oldvertex->id));
- return NULL;
- }
- qsort(SETaddr_(vertices, vertexT), (size_t)qh_setsize(vertices),
- sizeof(vertexT *), qh_comparevisit);
- /* can now use qh vertex_visit */
- if (qh PRINTstatistics) {
- size= qh_setsize(vertices);
- zinc_(Zintersect);
- zadd_(Zintersecttot, size);
- zmax_(Zintersectmax, size);
- }
- hashsize= qh_newhashtable(qh_setsize(ridges));
- FOREACHridge_(ridges)
- qh_hashridge(qh hash_table, hashsize, ridge, oldvertex);
- FOREACHvertex_(vertices) {
- newridges= qh_vertexridges(vertex);
- FOREACHridge_(newridges) {
- if (qh_hashridge_find(qh hash_table, hashsize, ridge, vertex, oldvertex, &hash)) {
- zinc_(Zdupridge);
- break;
- }
- }
- qh_settempfree(&newridges);
- if (!ridge)
- break; /* found a rename */
- }
- if (vertex) {
- /* counted in qh_renamevertex */
- trace2((qh ferr, 2020, "qh_find_newvertex: found v%d for old v%d from %d vertices and %d ridges.\n",
- vertex->id, oldvertex->id, qh_setsize(vertices), qh_setsize(ridges)));
- }else {
- zinc_(Zfindfail);
- trace0((qh ferr, 14, "qh_find_newvertex: no vertex for renaming v%d(all duplicated ridges) during p%d\n",
- oldvertex->id, qh furthest_id));
- }
- qh_setfree(&qh hash_table);
- return vertex;
-} /* find_newvertex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="findbest_test">-</a>
-
- qh_findbest_test( testcentrum, facet, neighbor, bestfacet, dist, mindist, maxdist )
- test neighbor of facet for qh_findbestneighbor()
- if testcentrum,
- tests centrum (assumes it is defined)
- else
- tests vertices
-
- returns:
- if a better facet (i.e., vertices/centrum of facet closer to neighbor)
- updates bestfacet, dist, mindist, and maxdist
-*/
-void qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
- facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp) {
- realT dist, mindist, maxdist;
-
- if (testcentrum) {
- zzinc_(Zbestdist);
- qh_distplane(facet->center, neighbor, &dist);
- dist *= qh hull_dim; /* estimate furthest vertex */
- if (dist < 0) {
- maxdist= 0;
- mindist= dist;
- dist= -dist;
- }else {
- mindist= 0;
- maxdist= dist;
- }
- }else
- dist= qh_getdistance(facet, neighbor, &mindist, &maxdist);
- if (dist < *distp) {
- *bestfacet= neighbor;
- *mindistp= mindist;
- *maxdistp= maxdist;
- *distp= dist;
- }
-} /* findbest_test */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="findbestneighbor">-</a>
-
- qh_findbestneighbor( facet, dist, mindist, maxdist )
- finds best neighbor (least dist) of a facet for merging
-
- returns:
- returns min and max distances and their max absolute value
-
- notes:
- avoids merging old into new
- assumes ridge->nonconvex only set on one ridge between a pair of facets
- could use an early out predicate but not worth it
-
- design:
- if a large facet
- will test centrum
- else
- will test vertices
- if a large facet
- test nonconvex neighbors for best merge
- else
- test all neighbors for the best merge
- if testing centrum
- get distance information
-*/
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp) {
- facetT *neighbor, **neighborp, *bestfacet= NULL;
- ridgeT *ridge, **ridgep;
- boolT nonconvex= True, testcentrum= False;
- int size= qh_setsize(facet->vertices);
-
- *distp= REALmax;
- if (size > qh_BESTcentrum2 * qh hull_dim + qh_BESTcentrum) {
- testcentrum= True;
- zinc_(Zbestcentrum);
- if (!facet->center)
- facet->center= qh_getcentrum(facet);
- }
- if (size > qh hull_dim + qh_BESTnonconvex) {
- FOREACHridge_(facet->ridges) {
- if (ridge->nonconvex) {
- neighbor= otherfacet_(ridge, facet);
- qh_findbest_test(testcentrum, facet, neighbor,
- &bestfacet, distp, mindistp, maxdistp);
- }
- }
- }
- if (!bestfacet) {
- nonconvex= False;
- FOREACHneighbor_(facet)
- qh_findbest_test(testcentrum, facet, neighbor,
- &bestfacet, distp, mindistp, maxdistp);
- }
- if (!bestfacet) {
- qh_fprintf(qh ferr, 6095, "qhull internal error (qh_findbestneighbor): no neighbors for f%d\n", facet->id);
-
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- if (testcentrum)
- qh_getdistance(facet, bestfacet, mindistp, maxdistp);
- trace3((qh ferr, 3002, "qh_findbestneighbor: f%d is best neighbor for f%d testcentrum? %d nonconvex? %d dist %2.2g min %2.2g max %2.2g\n",
- bestfacet->id, facet->id, testcentrum, nonconvex, *distp, *mindistp, *maxdistp));
- return(bestfacet);
-} /* findbestneighbor */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="flippedmerges">-</a>
-
- qh_flippedmerges( facetlist, wasmerge )
- merge flipped facets into best neighbor
- assumes qh.facet_mergeset at top of temporary stack
-
- returns:
- no flipped facets on facetlist
- sets wasmerge if merge occurred
- degen/redundant merges passed through
-
- notes:
- othermerges not needed since qh.facet_mergeset is empty before & after
- keep it in case of change
-
- design:
- append flipped facets to qh.facetmergeset
- for each flipped merge
- find best neighbor
- merge facet into neighbor
- merge degenerate and redundant facets
- remove flipped merges from qh.facet_mergeset
-*/
-void qh_flippedmerges(facetT *facetlist, boolT *wasmerge) {
- facetT *facet, *neighbor, *facet1;
- realT dist, mindist, maxdist;
- mergeT *merge, **mergep;
- setT *othermerges;
- int nummerge=0;
-
- trace4((qh ferr, 4024, "qh_flippedmerges: begin\n"));
- FORALLfacet_(facetlist) {
- if (facet->flipped && !facet->visible)
- qh_appendmergeset(facet, facet, MRGflip, NULL);
- }
- othermerges= qh_settemppop(); /* was facet_mergeset */
- qh facet_mergeset= qh_settemp(qh TEMPsize);
- qh_settemppush(othermerges);
- FOREACHmerge_(othermerges) {
- facet1= merge->facet1;
- if (merge->type != MRGflip || facet1->visible)
- continue;
- if (qh TRACEmerge-1 == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- neighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
- trace0((qh ferr, 15, "qh_flippedmerges: merge flipped f%d into f%d dist %2.2g during p%d\n",
- facet1->id, neighbor->id, dist, qh furthest_id));
- qh_mergefacet(facet1, neighbor, &mindist, &maxdist, !qh_MERGEapex);
- nummerge++;
- if (qh PRINTstatistics) {
- zinc_(Zflipped);
- wadd_(Wflippedtot, dist);
- wmax_(Wflippedmax, dist);
- }
- qh_merge_degenredundant();
- }
- FOREACHmerge_(othermerges) {
- if (merge->facet1->visible || merge->facet2->visible)
- qh_memfree(merge, (int)sizeof(mergeT));
- else
- qh_setappend(&qh facet_mergeset, merge);
- }
- qh_settempfree(&othermerges);
- if (nummerge)
- *wasmerge= True;
- trace1((qh ferr, 1010, "qh_flippedmerges: merged %d flipped facets into a good neighbor\n", nummerge));
-} /* flippedmerges */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="forcedmerges">-</a>
-
- qh_forcedmerges( wasmerge )
- merge duplicated ridges
-
- returns:
- removes all duplicate ridges on facet_mergeset
- wasmerge set if merge
- qh.facet_mergeset may include non-forced merges(none for now)
- qh.degen_mergeset includes degen/redun merges
-
- notes:
- duplicate ridges occur when the horizon is pinched,
- i.e. a subridge occurs in more than two horizon ridges.
- could rename vertices that pinch the horizon
- assumes qh_merge_degenredundant() has not be called
- othermerges isn't needed since facet_mergeset is empty afterwards
- keep it in case of change
-
- design:
- for each duplicate ridge
- find current facets by chasing f.replace links
- determine best direction for facet
- merge one facet into the other
- remove duplicate ridges from qh.facet_mergeset
-*/
-void qh_forcedmerges(boolT *wasmerge) {
- facetT *facet1, *facet2;
- mergeT *merge, **mergep;
- realT dist1, dist2, mindist1, mindist2, maxdist1, maxdist2;
- setT *othermerges;
- int nummerge=0, numflip=0;
-
- if (qh TRACEmerge-1 == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- trace4((qh ferr, 4025, "qh_forcedmerges: begin\n"));
- othermerges= qh_settemppop(); /* was facet_mergeset */
- qh facet_mergeset= qh_settemp(qh TEMPsize);
- qh_settemppush(othermerges);
- FOREACHmerge_(othermerges) {
- if (merge->type != MRGridge)
- continue;
- facet1= merge->facet1;
- facet2= merge->facet2;
- while (facet1->visible) /* must exist, no qh_merge_degenredunant */
- facet1= facet1->f.replace; /* previously merged facet */
- while (facet2->visible)
- facet2= facet2->f.replace; /* previously merged facet */
- if (facet1 == facet2)
- continue;
- if (!qh_setin(facet2->neighbors, facet1)) {
- qh_fprintf(qh ferr, 6096, "qhull internal error (qh_forcedmerges): f%d and f%d had a duplicate ridge but as f%d and f%d they are no longer neighbors\n",
- merge->facet1->id, merge->facet2->id, facet1->id, facet2->id);
- qh_errexit2 (qh_ERRqhull, facet1, facet2);
- }
- if (qh TRACEmerge-1 == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- dist1= qh_getdistance(facet1, facet2, &mindist1, &maxdist1);
- dist2= qh_getdistance(facet2, facet1, &mindist2, &maxdist2);
- trace0((qh ferr, 16, "qh_forcedmerges: duplicate ridge between f%d and f%d, dist %2.2g and reverse dist %2.2g during p%d\n",
- facet1->id, facet2->id, dist1, dist2, qh furthest_id));
- if (dist1 < dist2)
- qh_mergefacet(facet1, facet2, &mindist1, &maxdist1, !qh_MERGEapex);
- else {
- qh_mergefacet(facet2, facet1, &mindist2, &maxdist2, !qh_MERGEapex);
- dist1= dist2;
- facet1= facet2;
- }
- if (facet1->flipped) {
- zinc_(Zmergeflipdup);
- numflip++;
- }else
- nummerge++;
- if (qh PRINTstatistics) {
- zinc_(Zduplicate);
- wadd_(Wduplicatetot, dist1);
- wmax_(Wduplicatemax, dist1);
- }
- }
- FOREACHmerge_(othermerges) {
- if (merge->type == MRGridge)
- qh_memfree(merge, (int)sizeof(mergeT));
- else
- qh_setappend(&qh facet_mergeset, merge);
- }
- qh_settempfree(&othermerges);
- if (nummerge)
- *wasmerge= True;
- trace1((qh ferr, 1011, "qh_forcedmerges: merged %d facets and %d flipped facets across duplicated ridges\n",
- nummerge, numflip));
-} /* forcedmerges */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="getmergeset">-</a>
-
- qh_getmergeset( facetlist )
- determines nonconvex facets on facetlist
- tests !tested ridges and nonconvex ridges of !tested facets
-
- returns:
- returns sorted qh.facet_mergeset of facet-neighbor pairs to be merged
- all ridges tested
-
- notes:
- assumes no nonconvex ridges with both facets tested
- uses facet->tested/ridge->tested to prevent duplicate tests
- can not limit tests to modified ridges since the centrum changed
- uses qh.visit_id
-
- see:
- qh_getmergeset_initial()
-
- design:
- for each facet on facetlist
- for each ridge of facet
- if untested ridge
- test ridge for convexity
- if non-convex
- append ridge to qh.facet_mergeset
- sort qh.facet_mergeset by angle
-*/
-void qh_getmergeset(facetT *facetlist) {
- facetT *facet, *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
- int nummerges;
-
- nummerges= qh_setsize(qh facet_mergeset);
- trace4((qh ferr, 4026, "qh_getmergeset: started.\n"));
- qh visit_id++;
- FORALLfacet_(facetlist) {
- if (facet->tested)
- continue;
- facet->visitid= qh visit_id;
- facet->tested= True; /* must be non-simplicial due to merge */
- FOREACHneighbor_(facet)
- neighbor->seen= False;
- FOREACHridge_(facet->ridges) {
- if (ridge->tested && !ridge->nonconvex)
- continue;
- /* if tested & nonconvex, need to append merge */
- neighbor= otherfacet_(ridge, facet);
- if (neighbor->seen) {
- ridge->tested= True;
- ridge->nonconvex= False;
- }else if (neighbor->visitid != qh visit_id) {
- ridge->tested= True;
- ridge->nonconvex= False;
- neighbor->seen= True; /* only one ridge is marked nonconvex */
- if (qh_test_appendmerge(facet, neighbor))
- ridge->nonconvex= True;
- }
- }
- }
- nummerges= qh_setsize(qh facet_mergeset);
- if (qh ANGLEmerge)
- qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
- else
- qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
- if (qh POSTmerging) {
- zadd_(Zmergesettot2, nummerges);
- }else {
- zadd_(Zmergesettot, nummerges);
- zmax_(Zmergesetmax, nummerges);
- }
- trace2((qh ferr, 2021, "qh_getmergeset: %d merges found\n", nummerges));
-} /* getmergeset */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="getmergeset_initial">-</a>
-
- qh_getmergeset_initial( facetlist )
- determine initial qh.facet_mergeset for facets
- tests all facet/neighbor pairs on facetlist
-
- returns:
- sorted qh.facet_mergeset with nonconvex ridges
- sets facet->tested, ridge->tested, and ridge->nonconvex
-
- notes:
- uses visit_id, assumes ridge->nonconvex is False
-
- see:
- qh_getmergeset()
-
- design:
- for each facet on facetlist
- for each untested neighbor of facet
- test facet and neighbor for convexity
- if non-convex
- append merge to qh.facet_mergeset
- mark one of the ridges as nonconvex
- sort qh.facet_mergeset by angle
-*/
-void qh_getmergeset_initial(facetT *facetlist) {
- facetT *facet, *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
- int nummerges;
-
- qh visit_id++;
- FORALLfacet_(facetlist) {
- facet->visitid= qh visit_id;
- facet->tested= True;
- FOREACHneighbor_(facet) {
- if (neighbor->visitid != qh visit_id) {
- if (qh_test_appendmerge(facet, neighbor)) {
- FOREACHridge_(neighbor->ridges) {
- if (facet == otherfacet_(ridge, neighbor)) {
- ridge->nonconvex= True;
- break; /* only one ridge is marked nonconvex */
- }
- }
- }
- }
- }
- FOREACHridge_(facet->ridges)
- ridge->tested= True;
- }
- nummerges= qh_setsize(qh facet_mergeset);
- if (qh ANGLEmerge)
- qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_compareangle);
- else
- qsort(SETaddr_(qh facet_mergeset, mergeT), (size_t)nummerges, sizeof(mergeT *), qh_comparemerge);
- if (qh POSTmerging) {
- zadd_(Zmergeinittot2, nummerges);
- }else {
- zadd_(Zmergeinittot, nummerges);
- zmax_(Zmergeinitmax, nummerges);
- }
- trace2((qh ferr, 2022, "qh_getmergeset_initial: %d merges found\n", nummerges));
-} /* getmergeset_initial */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="hashridge">-</a>
-
- qh_hashridge( hashtable, hashsize, ridge, oldvertex )
- add ridge to hashtable without oldvertex
-
- notes:
- assumes hashtable is large enough
-
- design:
- determine hash value for ridge without oldvertex
- find next empty slot for ridge
-*/
-void qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex) {
- int hash;
- ridgeT *ridgeA;
-
- hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, oldvertex);
- while (True) {
- if (!(ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
- SETelem_(hashtable, hash)= ridge;
- break;
- }else if (ridgeA == ridge)
- break;
- if (++hash == hashsize)
- hash= 0;
- }
-} /* hashridge */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="hashridge_find">-</a>
-
- qh_hashridge_find( hashtable, hashsize, ridge, vertex, oldvertex, hashslot )
- returns matching ridge without oldvertex in hashtable
- for ridge without vertex
- if oldvertex is NULL
- matches with any one skip
-
- returns:
- matching ridge or NULL
- if no match,
- if ridge already in table
- hashslot= -1
- else
- hashslot= next NULL index
-
- notes:
- assumes hashtable is large enough
- can't match ridge to itself
-
- design:
- get hash value for ridge without vertex
- for each hashslot
- return match if ridge matches ridgeA without oldvertex
-*/
-ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
- vertexT *vertex, vertexT *oldvertex, int *hashslot) {
- int hash;
- ridgeT *ridgeA;
-
- *hashslot= 0;
- zinc_(Zhashridge);
- hash= qh_gethash(hashsize, ridge->vertices, qh hull_dim-1, 0, vertex);
- while ((ridgeA= SETelemt_(hashtable, hash, ridgeT))) {
- if (ridgeA == ridge)
- *hashslot= -1;
- else {
- zinc_(Zhashridgetest);
- if (qh_setequal_except(ridge->vertices, vertex, ridgeA->vertices, oldvertex))
- return ridgeA;
- }
- if (++hash == hashsize)
- hash= 0;
- }
- if (!*hashslot)
- *hashslot= hash;
- return NULL;
-} /* hashridge_find */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="makeridges">-</a>
-
- qh_makeridges( facet )
- creates explicit ridges between simplicial facets
-
- returns:
- facet with ridges and without qh_MERGEridge
- ->simplicial is False
-
- notes:
- allows qh_MERGEridge flag
- uses existing ridges
- duplicate neighbors ok if ridges already exist (qh_mergecycle_ridges)
-
- see:
- qh_mergecycle_ridges()
-
- design:
- look for qh_MERGEridge neighbors
- mark neighbors that already have ridges
- for each unprocessed neighbor of facet
- create a ridge for neighbor and facet
- if any qh_MERGEridge neighbors
- delete qh_MERGEridge flags (already handled by qh_mark_dupridges)
-*/
-void qh_makeridges(facetT *facet) {
- facetT *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
- int neighbor_i, neighbor_n;
- boolT toporient, mergeridge= False;
-
- if (!facet->simplicial)
- return;
- trace4((qh ferr, 4027, "qh_makeridges: make ridges for f%d\n", facet->id));
- facet->simplicial= False;
- FOREACHneighbor_(facet) {
- if (neighbor == qh_MERGEridge)
- mergeridge= True;
- else
- neighbor->seen= False;
- }
- FOREACHridge_(facet->ridges)
- otherfacet_(ridge, facet)->seen= True;
- FOREACHneighbor_i_(facet) {
- if (neighbor == qh_MERGEridge)
- continue; /* fixed by qh_mark_dupridges */
- else if (!neighbor->seen) { /* no current ridges */
- ridge= qh_newridge();
- ridge->vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
- neighbor_i, 0);
- toporient= facet->toporient ^ (neighbor_i & 0x1);
- if (toporient) {
- ridge->top= facet;
- ridge->bottom= neighbor;
- }else {
- ridge->top= neighbor;
- ridge->bottom= facet;
- }
-#if 0 /* this also works */
- flip= (facet->toporient ^ neighbor->toporient)^(skip1 & 0x1) ^ (skip2 & 0x1);
- if (facet->toporient ^ (skip1 & 0x1) ^ flip) {
- ridge->top= neighbor;
- ridge->bottom= facet;
- }else {
- ridge->top= facet;
- ridge->bottom= neighbor;
- }
-#endif
- qh_setappend(&(facet->ridges), ridge);
- qh_setappend(&(neighbor->ridges), ridge);
- }
- }
- if (mergeridge) {
- while (qh_setdel(facet->neighbors, qh_MERGEridge))
- ; /* delete each one */
- }
-} /* makeridges */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mark_dupridges">-</a>
-
- qh_mark_dupridges( facetlist )
- add duplicated ridges to qh.facet_mergeset
- facet->dupridge is true
-
- returns:
- duplicate ridges on qh.facet_mergeset
- ->mergeridge/->mergeridge2 set
- duplicate ridges marked by qh_MERGEridge and both sides facet->dupridge
- no MERGEridges in neighbor sets
-
- notes:
- duplicate ridges occur when the horizon is pinched,
- i.e. a subridge occurs in more than two horizon ridges.
- could rename vertices that pinch the horizon
- uses qh.visit_id
-
- design:
- for all facets on facetlist
- if facet contains a duplicate ridge
- for each neighbor of facet
- if neighbor marked qh_MERGEridge (one side of the merge)
- set facet->mergeridge
- else
- if neighbor contains a duplicate ridge
- and the back link is qh_MERGEridge
- append duplicate ridge to qh.facet_mergeset
- for each duplicate ridge
- make ridge sets in preparation for merging
- remove qh_MERGEridge from neighbor set
- for each duplicate ridge
- restore the missing neighbor from the neighbor set that was qh_MERGEridge
- add the missing ridge for this neighbor
-*/
-void qh_mark_dupridges(facetT *facetlist) {
- facetT *facet, *neighbor, **neighborp;
- int nummerge=0;
- mergeT *merge, **mergep;
-
-
- trace4((qh ferr, 4028, "qh_mark_dupridges: identify duplicate ridges\n"));
- FORALLfacet_(facetlist) {
- if (facet->dupridge) {
- FOREACHneighbor_(facet) {
- if (neighbor == qh_MERGEridge) {
- facet->mergeridge= True;
- continue;
- }
- if (neighbor->dupridge
- && !qh_setin(neighbor->neighbors, facet)) { /* qh_MERGEridge */
- qh_appendmergeset(facet, neighbor, MRGridge, NULL);
- facet->mergeridge2= True;
- facet->mergeridge= True;
- nummerge++;
- }
- }
- }
- }
- if (!nummerge)
- return;
- FORALLfacet_(facetlist) { /* gets rid of qh_MERGEridge */
- if (facet->mergeridge && !facet->mergeridge2)
- qh_makeridges(facet);
- }
- FOREACHmerge_(qh facet_mergeset) { /* restore the missing neighbors */
- if (merge->type == MRGridge) {
- qh_setappend(&merge->facet2->neighbors, merge->facet1);
- qh_makeridges(merge->facet1); /* and the missing ridges */
- }
- }
- trace1((qh ferr, 1012, "qh_mark_dupridges: found %d duplicated ridges\n",
- nummerge));
-} /* mark_dupridges */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="maydropneighbor">-</a>
-
- qh_maydropneighbor( facet )
- drop neighbor relationship if no ridge between facet and neighbor
-
- returns:
- neighbor sets updated
- appends degenerate facets to qh.facet_mergeset
-
- notes:
- won't cause redundant facets since vertex inclusion is the same
- may drop vertex and neighbor if no ridge
- uses qh.visit_id
-
- design:
- visit all neighbors with ridges
- for each unvisited neighbor of facet
- delete neighbor and facet from the neighbor sets
- if neighbor becomes degenerate
- append neighbor to qh.degen_mergeset
- if facet is degenerate
- append facet to qh.degen_mergeset
-*/
-void qh_maydropneighbor(facetT *facet) {
- ridgeT *ridge, **ridgep;
- realT angledegen= qh_ANGLEdegen;
- facetT *neighbor, **neighborp;
-
- qh visit_id++;
- trace4((qh ferr, 4029, "qh_maydropneighbor: test f%d for no ridges to a neighbor\n",
- facet->id));
- FOREACHridge_(facet->ridges) {
- ridge->top->visitid= qh visit_id;
- ridge->bottom->visitid= qh visit_id;
- }
- FOREACHneighbor_(facet) {
- if (neighbor->visitid != qh visit_id) {
- trace0((qh ferr, 17, "qh_maydropneighbor: facets f%d and f%d are no longer neighbors during p%d\n",
- facet->id, neighbor->id, qh furthest_id));
- zinc_(Zdropneighbor);
- qh_setdel(facet->neighbors, neighbor);
- neighborp--; /* repeat, deleted a neighbor */
- qh_setdel(neighbor->neighbors, facet);
- if (qh_setsize(neighbor->neighbors) < qh hull_dim) {
- zinc_(Zdropdegen);
- qh_appendmergeset(neighbor, neighbor, MRGdegen, &angledegen);
- trace2((qh ferr, 2023, "qh_maydropneighbors: f%d is degenerate.\n", neighbor->id));
- }
- }
- }
- if (qh_setsize(facet->neighbors) < qh hull_dim) {
- zinc_(Zdropdegen);
- qh_appendmergeset(facet, facet, MRGdegen, &angledegen);
- trace2((qh ferr, 2024, "qh_maydropneighbors: f%d is degenerate.\n", facet->id));
- }
-} /* maydropneighbor */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="merge_degenredundant">-</a>
-
- qh_merge_degenredundant()
- merge all degenerate and redundant facets
- qh.degen_mergeset contains merges from qh_degen_redundant_neighbors()
-
- returns:
- number of merges performed
- resets facet->degenerate/redundant
- if deleted (visible) facet has no neighbors
- sets ->f.replace to NULL
-
- notes:
- redundant merges happen before degenerate ones
- merging and renaming vertices can result in degen/redundant facets
-
- design:
- for each merge on qh.degen_mergeset
- if redundant merge
- if non-redundant facet merged into redundant facet
- recheck facet for redundancy
- else
- merge redundant facet into other facet
-*/
-int qh_merge_degenredundant(void) {
- int size;
- mergeT *merge;
- facetT *bestneighbor, *facet1, *facet2;
- realT dist, mindist, maxdist;
- vertexT *vertex, **vertexp;
- int nummerges= 0;
- mergeType mergetype;
-
- while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
- facet1= merge->facet1;
- facet2= merge->facet2;
- mergetype= merge->type;
- qh_memfree(merge, (int)sizeof(mergeT));
- if (facet1->visible)
- continue;
- facet1->degenerate= False;
- facet1->redundant= False;
- if (qh TRACEmerge-1 == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- if (mergetype == MRGredundant) {
- zinc_(Zneighbor);
- while (facet2->visible) {
- if (!facet2->f.replace) {
- qh_fprintf(qh ferr, 6097, "qhull internal error (qh_merge_degenredunant): f%d redundant but f%d has no replacement\n",
- facet1->id, facet2->id);
- qh_errexit2 (qh_ERRqhull, facet1, facet2);
- }
- facet2= facet2->f.replace;
- }
- if (facet1 == facet2) {
- qh_degen_redundant_facet(facet1); /* in case of others */
- continue;
- }
- trace2((qh ferr, 2025, "qh_merge_degenredundant: facet f%d is contained in f%d, will merge\n",
- facet1->id, facet2->id));
- qh_mergefacet(facet1, facet2, NULL, NULL, !qh_MERGEapex);
- /* merge distance is already accounted for */
- nummerges++;
- }else { /* mergetype == MRGdegen, other merges may have fixed */
- if (!(size= qh_setsize(facet1->neighbors))) {
- zinc_(Zdelfacetdup);
- trace2((qh ferr, 2026, "qh_merge_degenredundant: facet f%d has no neighbors. Deleted\n", facet1->id));
- qh_willdelete(facet1, NULL);
- FOREACHvertex_(facet1->vertices) {
- qh_setdel(vertex->neighbors, facet1);
- if (!SETfirst_(vertex->neighbors)) {
- zinc_(Zdegenvertex);
- trace2((qh ferr, 2027, "qh_merge_degenredundant: deleted v%d because f%d has no neighbors\n",
- vertex->id, facet1->id));
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
- }
- }
- nummerges++;
- }else if (size < qh hull_dim) {
- bestneighbor= qh_findbestneighbor(facet1, &dist, &mindist, &maxdist);
- trace2((qh ferr, 2028, "qh_merge_degenredundant: facet f%d has %d neighbors, merge into f%d dist %2.2g\n",
- facet1->id, size, bestneighbor->id, dist));
- qh_mergefacet(facet1, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
- nummerges++;
- if (qh PRINTstatistics) {
- zinc_(Zdegen);
- wadd_(Wdegentot, dist);
- wmax_(Wdegenmax, dist);
- }
- } /* else, another merge fixed the degeneracy and redundancy tested */
- }
- }
- return nummerges;
-} /* merge_degenredundant */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="merge_nonconvex">-</a>
-
- qh_merge_nonconvex( facet1, facet2, mergetype )
- remove non-convex ridge between facet1 into facet2
- mergetype gives why the facet's are non-convex
-
- returns:
- merges one of the facets into the best neighbor
-
- design:
- if one of the facets is a new facet
- prefer merging new facet into old facet
- find best neighbors for both facets
- merge the nearest facet into its best neighbor
- update the statistics
-*/
-void qh_merge_nonconvex(facetT *facet1, facetT *facet2, mergeType mergetype) {
- facetT *bestfacet, *bestneighbor, *neighbor;
- realT dist, dist2, mindist, mindist2, maxdist, maxdist2;
-
- if (qh TRACEmerge-1 == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- trace3((qh ferr, 3003, "qh_merge_nonconvex: merge #%d for f%d and f%d type %d\n",
- zzval_(Ztotmerge) + 1, facet1->id, facet2->id, mergetype));
- /* concave or coplanar */
- if (!facet1->newfacet) {
- bestfacet= facet2; /* avoid merging old facet if new is ok */
- facet2= facet1;
- facet1= bestfacet;
- }else
- bestfacet= facet1;
- bestneighbor= qh_findbestneighbor(bestfacet, &dist, &mindist, &maxdist);
- neighbor= qh_findbestneighbor(facet2, &dist2, &mindist2, &maxdist2);
- if (dist < dist2) {
- qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
- }else if (qh AVOIDold && !facet2->newfacet
- && ((mindist >= -qh MAXcoplanar && maxdist <= qh max_outside)
- || dist * 1.5 < dist2)) {
- zinc_(Zavoidold);
- wadd_(Wavoidoldtot, dist);
- wmax_(Wavoidoldmax, dist);
- trace2((qh ferr, 2029, "qh_merge_nonconvex: avoid merging old facet f%d dist %2.2g. Use f%d dist %2.2g instead\n",
- facet2->id, dist2, facet1->id, dist2));
- qh_mergefacet(bestfacet, bestneighbor, &mindist, &maxdist, !qh_MERGEapex);
- }else {
- qh_mergefacet(facet2, neighbor, &mindist2, &maxdist2, !qh_MERGEapex);
- dist= dist2;
- }
- if (qh PRINTstatistics) {
- if (mergetype == MRGanglecoplanar) {
- zinc_(Zacoplanar);
- wadd_(Wacoplanartot, dist);
- wmax_(Wacoplanarmax, dist);
- }else if (mergetype == MRGconcave) {
- zinc_(Zconcave);
- wadd_(Wconcavetot, dist);
- wmax_(Wconcavemax, dist);
- }else { /* MRGcoplanar */
- zinc_(Zcoplanar);
- wadd_(Wcoplanartot, dist);
- wmax_(Wcoplanarmax, dist);
- }
- }
-} /* merge_nonconvex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle">-</a>
-
- qh_mergecycle( samecycle, newfacet )
- merge a cycle of facets starting at samecycle into a newfacet
- newfacet is a horizon facet with ->normal
- samecycle facets are simplicial from an apex
-
- returns:
- initializes vertex neighbors on first merge
- samecycle deleted (placed on qh.visible_list)
- newfacet at end of qh.facet_list
- deleted vertices on qh.del_vertices
-
- see:
- qh_mergefacet()
- called by qh_mergecycle_all() for multiple, same cycle facets
-
- design:
- make vertex neighbors if necessary
- make ridges for newfacet
- merge neighbor sets of samecycle into newfacet
- merge ridges of samecycle into newfacet
- merge vertex neighbors of samecycle into newfacet
- make apex of samecycle the apex of newfacet
- if newfacet wasn't a new facet
- add its vertices to qh.newvertex_list
- delete samecycle facets a make newfacet a newfacet
-*/
-void qh_mergecycle(facetT *samecycle, facetT *newfacet) {
- int traceonce= False, tracerestore= 0;
- vertexT *apex;
-#ifndef qh_NOtrace
- facetT *same;
-#endif
-
- if (newfacet->tricoplanar) {
- if (!qh TRInormals) {
- qh_fprintf(qh ferr, 6224, "Qhull internal error (qh_mergecycle): does not work for tricoplanar facets. Use option 'Q11'\n");
- qh_errexit(qh_ERRqhull, newfacet, NULL);
- }
- newfacet->tricoplanar= False;
- newfacet->keepcentrum= False;
- }
- if (!qh VERTEXneighbors)
- qh_vertexneighbors();
- zzinc_(Ztotmerge);
- if (qh REPORTfreq2 && qh POSTmerging) {
- if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
- qh_tracemerging();
- }
-#ifndef qh_NOtrace
- if (qh TRACEmerge == zzval_(Ztotmerge))
- qhmem.IStracing= qh IStracing= qh TRACElevel;
- trace2((qh ferr, 2030, "qh_mergecycle: merge #%d for facets from cycle f%d into coplanar horizon f%d\n",
- zzval_(Ztotmerge), samecycle->id, newfacet->id));
- if (newfacet == qh tracefacet) {
- tracerestore= qh IStracing;
- qh IStracing= 4;
- qh_fprintf(qh ferr, 8068, "qh_mergecycle: ========= trace merge %d of samecycle %d into trace f%d, furthest is p%d\n",
- zzval_(Ztotmerge), samecycle->id, newfacet->id, qh furthest_id);
- traceonce= True;
- }
- if (qh IStracing >=4) {
- qh_fprintf(qh ferr, 8069, " same cycle:");
- FORALLsame_cycle_(samecycle)
- qh_fprintf(qh ferr, 8070, " f%d", same->id);
- qh_fprintf(qh ferr, 8071, "\n");
- }
- if (qh IStracing >=4)
- qh_errprint("MERGING CYCLE", samecycle, newfacet, NULL, NULL);
-#endif /* !qh_NOtrace */
- apex= SETfirstt_(samecycle->vertices, vertexT);
- qh_makeridges(newfacet);
- qh_mergecycle_neighbors(samecycle, newfacet);
- qh_mergecycle_ridges(samecycle, newfacet);
- qh_mergecycle_vneighbors(samecycle, newfacet);
- if (SETfirstt_(newfacet->vertices, vertexT) != apex)
- qh_setaddnth(&newfacet->vertices, 0, apex); /* apex has last id */
- if (!newfacet->newfacet)
- qh_newvertices(newfacet->vertices);
- qh_mergecycle_facets(samecycle, newfacet);
- qh_tracemerge(samecycle, newfacet);
- /* check for degen_redundant_neighbors after qh_forcedmerges() */
- if (traceonce) {
- qh_fprintf(qh ferr, 8072, "qh_mergecycle: end of trace facet\n");
- qh IStracing= tracerestore;
- }
-} /* mergecycle */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle_all">-</a>
-
- qh_mergecycle_all( facetlist, wasmerge )
- merge all samecycles of coplanar facets into horizon
- don't merge facets with ->mergeridge (these already have ->normal)
- all facets are simplicial from apex
- all facet->cycledone == False
-
- returns:
- all newfacets merged into coplanar horizon facets
- deleted vertices on qh.del_vertices
- sets wasmerge if any merge
-
- see:
- calls qh_mergecycle for multiple, same cycle facets
-
- design:
- for each facet on facetlist
- skip facets with duplicate ridges and normals
- check that facet is in a samecycle (->mergehorizon)
- if facet only member of samecycle
- sets vertex->delridge for all vertices except apex
- merge facet into horizon
- else
- mark all facets in samecycle
- remove facets with duplicate ridges from samecycle
- merge samecycle into horizon (deletes facets from facetlist)
-*/
-void qh_mergecycle_all(facetT *facetlist, boolT *wasmerge) {
- facetT *facet, *same, *prev, *horizon;
- facetT *samecycle= NULL, *nextfacet, *nextsame;
- vertexT *apex, *vertex, **vertexp;
- int cycles=0, total=0, facets, nummerge;
-
- trace2((qh ferr, 2031, "qh_mergecycle_all: begin\n"));
- for (facet= facetlist; facet && (nextfacet= facet->next); facet= nextfacet) {
- if (facet->normal)
- continue;
- if (!facet->mergehorizon) {
- qh_fprintf(qh ferr, 6225, "Qhull internal error (qh_mergecycle_all): f%d without normal\n", facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- horizon= SETfirstt_(facet->neighbors, facetT);
- if (facet->f.samecycle == facet) {
- zinc_(Zonehorizon);
- /* merge distance done in qh_findhorizon */
- apex= SETfirstt_(facet->vertices, vertexT);
- FOREACHvertex_(facet->vertices) {
- if (vertex != apex)
- vertex->delridge= True;
- }
- horizon->f.newcycle= NULL;
- qh_mergefacet(facet, horizon, NULL, NULL, qh_MERGEapex);
- }else {
- samecycle= facet;
- facets= 0;
- prev= facet;
- for (same= facet->f.samecycle; same; /* FORALLsame_cycle_(facet) */
- same= (same == facet ? NULL :nextsame)) { /* ends at facet */
- nextsame= same->f.samecycle;
- if (same->cycledone || same->visible)
- qh_infiniteloop(same);
- same->cycledone= True;
- if (same->normal) {
- prev->f.samecycle= same->f.samecycle; /* unlink ->mergeridge */
- same->f.samecycle= NULL;
- }else {
- prev= same;
- facets++;
- }
- }
- while (nextfacet && nextfacet->cycledone) /* will delete samecycle */
- nextfacet= nextfacet->next;
- horizon->f.newcycle= NULL;
- qh_mergecycle(samecycle, horizon);
- nummerge= horizon->nummerge + facets;
- if (nummerge > qh_MAXnummerge)
- horizon->nummerge= qh_MAXnummerge;
- else
- horizon->nummerge= (short unsigned int)nummerge;
- zzinc_(Zcyclehorizon);
- total += facets;
- zzadd_(Zcyclefacettot, facets);
- zmax_(Zcyclefacetmax, facets);
- }
- cycles++;
- }
- if (cycles)
- *wasmerge= True;
- trace1((qh ferr, 1013, "qh_mergecycle_all: merged %d same cycles or facets into coplanar horizons\n", cycles));
-} /* mergecycle_all */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle_facets">-</a>
-
- qh_mergecycle_facets( samecycle, newfacet )
- finish merge of samecycle into newfacet
-
- returns:
- samecycle prepended to visible_list for later deletion and partitioning
- each facet->f.replace == newfacet
-
- newfacet moved to end of qh.facet_list
- makes newfacet a newfacet (get's facet1->id if it was old)
- sets newfacet->newmerge
- clears newfacet->center (unless merging into a large facet)
- clears newfacet->tested and ridge->tested for facet1
-
- adds neighboring facets to facet_mergeset if redundant or degenerate
-
- design:
- make newfacet a new facet and set its flags
- move samecycle facets to qh.visible_list for later deletion
- unless newfacet is large
- remove its centrum
-*/
-void qh_mergecycle_facets(facetT *samecycle, facetT *newfacet) {
- facetT *same, *next;
-
- trace4((qh ferr, 4030, "qh_mergecycle_facets: make newfacet new and samecycle deleted\n"));
- qh_removefacet(newfacet); /* append as a newfacet to end of qh facet_list */
- qh_appendfacet(newfacet);
- newfacet->newfacet= True;
- newfacet->simplicial= False;
- newfacet->newmerge= True;
-
- for (same= samecycle->f.samecycle; same; same= (same == samecycle ? NULL : next)) {
- next= same->f.samecycle; /* reused by willdelete */
- qh_willdelete(same, newfacet);
- }
- if (newfacet->center
- && qh_setsize(newfacet->vertices) <= qh hull_dim + qh_MAXnewcentrum) {
- qh_memfree(newfacet->center, qh normal_size);
- newfacet->center= NULL;
- }
- trace3((qh ferr, 3004, "qh_mergecycle_facets: merged facets from cycle f%d into f%d\n",
- samecycle->id, newfacet->id));
-} /* mergecycle_facets */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle_neighbors">-</a>
-
- qh_mergecycle_neighbors( samecycle, newfacet )
- add neighbors for samecycle facets to newfacet
-
- returns:
- newfacet with updated neighbors and vice-versa
- newfacet has ridges
- all neighbors of newfacet marked with qh.visit_id
- samecycle facets marked with qh.visit_id-1
- ridges updated for simplicial neighbors of samecycle with a ridge
-
- notes:
- assumes newfacet not in samecycle
- usually, samecycle facets are new, simplicial facets without internal ridges
- not so if horizon facet is coplanar to two different samecycles
-
- see:
- qh_mergeneighbors()
-
- design:
- check samecycle
- delete neighbors from newfacet that are also in samecycle
- for each neighbor of a facet in samecycle
- if neighbor is simplicial
- if first visit
- move the neighbor relation to newfacet
- update facet links for its ridges
- else
- make ridges for neighbor
- remove samecycle reference
- else
- update neighbor sets
-*/
-void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet) {
- facetT *same, *neighbor, **neighborp;
- int delneighbors= 0, newneighbors= 0;
- unsigned int samevisitid;
- ridgeT *ridge, **ridgep;
-
- samevisitid= ++qh visit_id;
- FORALLsame_cycle_(samecycle) {
- if (same->visitid == samevisitid || same->visible)
- qh_infiniteloop(samecycle);
- same->visitid= samevisitid;
- }
- newfacet->visitid= ++qh visit_id;
- trace4((qh ferr, 4031, "qh_mergecycle_neighbors: delete shared neighbors from newfacet\n"));
- FOREACHneighbor_(newfacet) {
- if (neighbor->visitid == samevisitid) {
- SETref_(neighbor)= NULL; /* samecycle neighbors deleted */
- delneighbors++;
- }else
- neighbor->visitid= qh visit_id;
- }
- qh_setcompact(newfacet->neighbors);
-
- trace4((qh ferr, 4032, "qh_mergecycle_neighbors: update neighbors\n"));
- FORALLsame_cycle_(samecycle) {
- FOREACHneighbor_(same) {
- if (neighbor->visitid == samevisitid)
- continue;
- if (neighbor->simplicial) {
- if (neighbor->visitid != qh visit_id) {
- qh_setappend(&newfacet->neighbors, neighbor);
- qh_setreplace(neighbor->neighbors, same, newfacet);
- newneighbors++;
- neighbor->visitid= qh visit_id;
- FOREACHridge_(neighbor->ridges) { /* update ridge in case of qh_makeridges */
- if (ridge->top == same) {
- ridge->top= newfacet;
- break;
- }else if (ridge->bottom == same) {
- ridge->bottom= newfacet;
- break;
- }
- }
- }else {
- qh_makeridges(neighbor);
- qh_setdel(neighbor->neighbors, same);
- /* same can't be horizon facet for neighbor */
- }
- }else { /* non-simplicial neighbor */
- qh_setdel(neighbor->neighbors, same);
- if (neighbor->visitid != qh visit_id) {
- qh_setappend(&neighbor->neighbors, newfacet);
- qh_setappend(&newfacet->neighbors, neighbor);
- neighbor->visitid= qh visit_id;
- newneighbors++;
- }
- }
- }
- }
- trace2((qh ferr, 2032, "qh_mergecycle_neighbors: deleted %d neighbors and added %d\n",
- delneighbors, newneighbors));
-} /* mergecycle_neighbors */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle_ridges">-</a>
-
- qh_mergecycle_ridges( samecycle, newfacet )
- add ridges/neighbors for facets in samecycle to newfacet
- all new/old neighbors of newfacet marked with qh.visit_id
- facets in samecycle marked with qh.visit_id-1
- newfacet marked with qh.visit_id
-
- returns:
- newfacet has merged ridges
-
- notes:
- ridge already updated for simplicial neighbors of samecycle with a ridge
-
- see:
- qh_mergeridges()
- qh_makeridges()
-
- design:
- remove ridges between newfacet and samecycle
- for each facet in samecycle
- for each ridge in facet
- update facet pointers in ridge
- skip ridges processed in qh_mergecycle_neighors
- free ridges between newfacet and samecycle
- free ridges between facets of samecycle (on 2nd visit)
- append remaining ridges to newfacet
- if simpilicial facet
- for each neighbor of facet
- if simplicial facet
- and not samecycle facet or newfacet
- make ridge between neighbor and newfacet
-*/
-void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet) {
- facetT *same, *neighbor= NULL;
- int numold=0, numnew=0;
- int neighbor_i, neighbor_n;
- unsigned int samevisitid;
- ridgeT *ridge, **ridgep;
- boolT toporient;
- void **freelistp; /* used !qh_NOmem */
-
- trace4((qh ferr, 4033, "qh_mergecycle_ridges: delete shared ridges from newfacet\n"));
- samevisitid= qh visit_id -1;
- FOREACHridge_(newfacet->ridges) {
- neighbor= otherfacet_(ridge, newfacet);
- if (neighbor->visitid == samevisitid)
- SETref_(ridge)= NULL; /* ridge free'd below */
- }
- qh_setcompact(newfacet->ridges);
-
- trace4((qh ferr, 4034, "qh_mergecycle_ridges: add ridges to newfacet\n"));
- FORALLsame_cycle_(samecycle) {
- FOREACHridge_(same->ridges) {
- if (ridge->top == same) {
- ridge->top= newfacet;
- neighbor= ridge->bottom;
- }else if (ridge->bottom == same) {
- ridge->bottom= newfacet;
- neighbor= ridge->top;
- }else if (ridge->top == newfacet || ridge->bottom == newfacet) {
- qh_setappend(&newfacet->ridges, ridge);
- numold++; /* already set by qh_mergecycle_neighbors */
- continue;
- }else {
- qh_fprintf(qh ferr, 6098, "qhull internal error (qh_mergecycle_ridges): bad ridge r%d\n", ridge->id);
- qh_errexit(qh_ERRqhull, NULL, ridge);
- }
- if (neighbor == newfacet) {
- qh_setfree(&(ridge->vertices));
- qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
- numold++;
- }else if (neighbor->visitid == samevisitid) {
- qh_setdel(neighbor->ridges, ridge);
- qh_setfree(&(ridge->vertices));
- qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
- numold++;
- }else {
- qh_setappend(&newfacet->ridges, ridge);
- numold++;
- }
- }
- if (same->ridges)
- qh_settruncate(same->ridges, 0);
- if (!same->simplicial)
- continue;
- FOREACHneighbor_i_(same) { /* note: !newfact->simplicial */
- if (neighbor->visitid != samevisitid && neighbor->simplicial) {
- ridge= qh_newridge();
- ridge->vertices= qh_setnew_delnthsorted(same->vertices, qh hull_dim,
- neighbor_i, 0);
- toporient= same->toporient ^ (neighbor_i & 0x1);
- if (toporient) {
- ridge->top= newfacet;
- ridge->bottom= neighbor;
- }else {
- ridge->top= neighbor;
- ridge->bottom= newfacet;
- }
- qh_setappend(&(newfacet->ridges), ridge);
- qh_setappend(&(neighbor->ridges), ridge);
- numnew++;
- }
- }
- }
-
- trace2((qh ferr, 2033, "qh_mergecycle_ridges: found %d old ridges and %d new ones\n",
- numold, numnew));
-} /* mergecycle_ridges */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergecycle_vneighbors">-</a>
-
- qh_mergecycle_vneighbors( samecycle, newfacet )
- create vertex neighbors for newfacet from vertices of facets in samecycle
- samecycle marked with visitid == qh.visit_id - 1
-
- returns:
- newfacet vertices with updated neighbors
- marks newfacet with qh.visit_id-1
- deletes vertices that are merged away
- sets delridge on all vertices (faster here than in mergecycle_ridges)
-
- see:
- qh_mergevertex_neighbors()
-
- design:
- for each vertex of samecycle facet
- set vertex->delridge
- delete samecycle facets from vertex neighbors
- append newfacet to vertex neighbors
- if vertex only in newfacet
- delete it from newfacet
- add it to qh.del_vertices for later deletion
-*/
-void qh_mergecycle_vneighbors(facetT *samecycle, facetT *newfacet) {
- facetT *neighbor, **neighborp;
- unsigned int mergeid;
- vertexT *vertex, **vertexp, *apex;
- setT *vertices;
-
- trace4((qh ferr, 4035, "qh_mergecycle_vneighbors: update vertex neighbors for newfacet\n"));
- mergeid= qh visit_id - 1;
- newfacet->visitid= mergeid;
- vertices= qh_basevertices(samecycle); /* temp */
- apex= SETfirstt_(samecycle->vertices, vertexT);
- qh_setappend(&vertices, apex);
- FOREACHvertex_(vertices) {
- vertex->delridge= True;
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid == mergeid)
- SETref_(neighbor)= NULL;
- }
- qh_setcompact(vertex->neighbors);
- qh_setappend(&vertex->neighbors, newfacet);
- if (!SETsecond_(vertex->neighbors)) {
- zinc_(Zcyclevertex);
- trace2((qh ferr, 2034, "qh_mergecycle_vneighbors: deleted v%d when merging cycle f%d into f%d\n",
- vertex->id, samecycle->id, newfacet->id));
- qh_setdelsorted(newfacet->vertices, vertex);
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
- }
- }
- qh_settempfree(&vertices);
- trace3((qh ferr, 3005, "qh_mergecycle_vneighbors: merged vertices from cycle f%d into f%d\n",
- samecycle->id, newfacet->id));
-} /* mergecycle_vneighbors */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergefacet">-</a>
-
- qh_mergefacet( facet1, facet2, mindist, maxdist, mergeapex )
- merges facet1 into facet2
- mergeapex==qh_MERGEapex if merging new facet into coplanar horizon
-
- returns:
- qh.max_outside and qh.min_vertex updated
- initializes vertex neighbors on first merge
-
- returns:
- facet2 contains facet1's vertices, neighbors, and ridges
- facet2 moved to end of qh.facet_list
- makes facet2 a newfacet
- sets facet2->newmerge set
- clears facet2->center (unless merging into a large facet)
- clears facet2->tested and ridge->tested for facet1
-
- facet1 prepended to visible_list for later deletion and partitioning
- facet1->f.replace == facet2
-
- adds neighboring facets to facet_mergeset if redundant or degenerate
-
- notes:
- mindist/maxdist may be NULL (only if both NULL)
- traces merge if fmax_(maxdist,-mindist) > TRACEdist
-
- see:
- qh_mergecycle()
-
- design:
- trace merge and check for degenerate simplex
- make ridges for both facets
- update qh.max_outside, qh.max_vertex, qh.min_vertex
- update facet2->maxoutside and keepcentrum
- update facet2->nummerge
- update tested flags for facet2
- if facet1 is simplicial
- merge facet1 into facet2
- else
- merge facet1's neighbors into facet2
- merge facet1's ridges into facet2
- merge facet1's vertices into facet2
- merge facet1's vertex neighbors into facet2
- add facet2's vertices to qh.new_vertexlist
- unless qh_MERGEapex
- test facet2 for degenerate or redundant neighbors
- move facet1 to qh.visible_list for later deletion
- move facet2 to end of qh.newfacet_list
-*/
-void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex) {
- boolT traceonce= False;
- vertexT *vertex, **vertexp;
- int tracerestore=0, nummerge;
-
- if (facet1->tricoplanar || facet2->tricoplanar) {
- if (!qh TRInormals) {
- qh_fprintf(qh ferr, 6226, "Qhull internal error (qh_mergefacet): does not work for tricoplanar facets. Use option 'Q11'\n");
- qh_errexit2 (qh_ERRqhull, facet1, facet2);
- }
- if (facet2->tricoplanar) {
- facet2->tricoplanar= False;
- facet2->keepcentrum= False;
- }
- }
- zzinc_(Ztotmerge);
- if (qh REPORTfreq2 && qh POSTmerging) {
- if (zzval_(Ztotmerge) > qh mergereport + qh REPORTfreq2)
- qh_tracemerging();
- }
-#ifndef qh_NOtrace
- if (qh build_cnt >= qh RERUN) {
- if (mindist && (-*mindist > qh TRACEdist || *maxdist > qh TRACEdist)) {
- tracerestore= 0;
- qh IStracing= qh TRACElevel;
- traceonce= True;
- qh_fprintf(qh ferr, 8075, "qh_mergefacet: ========= trace wide merge #%d(%2.2g) for f%d into f%d, last point was p%d\n", zzval_(Ztotmerge),
- fmax_(-*mindist, *maxdist), facet1->id, facet2->id, qh furthest_id);
- }else if (facet1 == qh tracefacet || facet2 == qh tracefacet) {
- tracerestore= qh IStracing;
- qh IStracing= 4;
- traceonce= True;
- qh_fprintf(qh ferr, 8076, "qh_mergefacet: ========= trace merge #%d involving f%d, furthest is p%d\n",
- zzval_(Ztotmerge), qh tracefacet_id, qh furthest_id);
- }
- }
- if (qh IStracing >= 2) {
- realT mergemin= -2;
- realT mergemax= -2;
-
- if (mindist) {
- mergemin= *mindist;
- mergemax= *maxdist;
- }
- qh_fprintf(qh ferr, 8077, "qh_mergefacet: #%d merge f%d into f%d, mindist= %2.2g, maxdist= %2.2g\n",
- zzval_(Ztotmerge), facet1->id, facet2->id, mergemin, mergemax);
- }
-#endif /* !qh_NOtrace */
- if (facet1 == facet2 || facet1->visible || facet2->visible) {
- qh_fprintf(qh ferr, 6099, "qhull internal error (qh_mergefacet): either f%d and f%d are the same or one is a visible facet\n",
- facet1->id, facet2->id);
- qh_errexit2 (qh_ERRqhull, facet1, facet2);
- }
- if (qh num_facets - qh num_visible <= qh hull_dim + 1) {
- qh_fprintf(qh ferr, 6227, "\n\
-qhull precision error: Only %d facets remain. Can not merge another\n\
-pair. The input is too degenerate or the convexity constraints are\n\
-too strong.\n", qh hull_dim+1);
- if (qh hull_dim >= 5 && !qh MERGEexact)
- qh_fprintf(qh ferr, 8079, "Option 'Qx' may avoid this problem.\n");
- qh_errexit(qh_ERRprec, NULL, NULL);
- }
- if (!qh VERTEXneighbors)
- qh_vertexneighbors();
- qh_makeridges(facet1);
- qh_makeridges(facet2);
- if (qh IStracing >=4)
- qh_errprint("MERGING", facet1, facet2, NULL, NULL);
- if (mindist) {
- maximize_(qh max_outside, *maxdist);
- maximize_(qh max_vertex, *maxdist);
-#if qh_MAXoutside
- maximize_(facet2->maxoutside, *maxdist);
-#endif
- minimize_(qh min_vertex, *mindist);
- if (!facet2->keepcentrum
- && (*maxdist > qh WIDEfacet || *mindist < -qh WIDEfacet)) {
- facet2->keepcentrum= True;
- zinc_(Zwidefacet);
- }
- }
- nummerge= facet1->nummerge + facet2->nummerge + 1;
- if (nummerge >= qh_MAXnummerge)
- facet2->nummerge= qh_MAXnummerge;
- else
- facet2->nummerge= (short unsigned int)nummerge;
- facet2->newmerge= True;
- facet2->dupridge= False;
- qh_updatetested (facet1, facet2);
- if (qh hull_dim > 2 && qh_setsize(facet1->vertices) == qh hull_dim)
- qh_mergesimplex(facet1, facet2, mergeapex);
- else {
- qh vertex_visit++;
- FOREACHvertex_(facet2->vertices)
- vertex->visitid= qh vertex_visit;
- if (qh hull_dim == 2)
- qh_mergefacet2d(facet1, facet2);
- else {
- qh_mergeneighbors(facet1, facet2);
- qh_mergevertices(facet1->vertices, &facet2->vertices);
- }
- qh_mergeridges(facet1, facet2);
- qh_mergevertex_neighbors(facet1, facet2);
- if (!facet2->newfacet)
- qh_newvertices(facet2->vertices);
- }
- if (!mergeapex)
- qh_degen_redundant_neighbors(facet2, facet1);
- if (facet2->coplanar || !facet2->newfacet) {
- zinc_(Zmergeintohorizon);
- }else if (!facet1->newfacet && facet2->newfacet) {
- zinc_(Zmergehorizon);
- }else {
- zinc_(Zmergenew);
- }
- qh_willdelete(facet1, facet2);
- qh_removefacet(facet2); /* append as a newfacet to end of qh facet_list */
- qh_appendfacet(facet2);
- facet2->newfacet= True;
- facet2->tested= False;
- qh_tracemerge(facet1, facet2);
- if (traceonce) {
- qh_fprintf(qh ferr, 8080, "qh_mergefacet: end of wide tracing\n");
- qh IStracing= tracerestore;
- }
-} /* mergefacet */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergefacet2d">-</a>
-
- qh_mergefacet2d( facet1, facet2 )
- in 2d, merges neighbors and vertices of facet1 into facet2
-
- returns:
- build ridges for neighbors if necessary
- facet2 looks like a simplicial facet except for centrum, ridges
- neighbors are opposite the corresponding vertex
- maintains orientation of facet2
-
- notes:
- qh_mergefacet() retains non-simplicial structures
- they are not needed in 2d, but later routines may use them
- preserves qh.vertex_visit for qh_mergevertex_neighbors()
-
- design:
- get vertices and neighbors
- determine new vertices and neighbors
- set new vertices and neighbors and adjust orientation
- make ridges for new neighbor if needed
-*/
-void qh_mergefacet2d(facetT *facet1, facetT *facet2) {
- vertexT *vertex1A, *vertex1B, *vertex2A, *vertex2B, *vertexA, *vertexB;
- facetT *neighbor1A, *neighbor1B, *neighbor2A, *neighbor2B, *neighborA, *neighborB;
-
- vertex1A= SETfirstt_(facet1->vertices, vertexT);
- vertex1B= SETsecondt_(facet1->vertices, vertexT);
- vertex2A= SETfirstt_(facet2->vertices, vertexT);
- vertex2B= SETsecondt_(facet2->vertices, vertexT);
- neighbor1A= SETfirstt_(facet1->neighbors, facetT);
- neighbor1B= SETsecondt_(facet1->neighbors, facetT);
- neighbor2A= SETfirstt_(facet2->neighbors, facetT);
- neighbor2B= SETsecondt_(facet2->neighbors, facetT);
- if (vertex1A == vertex2A) {
- vertexA= vertex1B;
- vertexB= vertex2B;
- neighborA= neighbor2A;
- neighborB= neighbor1A;
- }else if (vertex1A == vertex2B) {
- vertexA= vertex1B;
- vertexB= vertex2A;
- neighborA= neighbor2B;
- neighborB= neighbor1A;
- }else if (vertex1B == vertex2A) {
- vertexA= vertex1A;
- vertexB= vertex2B;
- neighborA= neighbor2A;
- neighborB= neighbor1B;
- }else { /* 1B == 2B */
- vertexA= vertex1A;
- vertexB= vertex2A;
- neighborA= neighbor2B;
- neighborB= neighbor1B;
- }
- /* vertexB always from facet2, neighborB always from facet1 */
- if (vertexA->id > vertexB->id) {
- SETfirst_(facet2->vertices)= vertexA;
- SETsecond_(facet2->vertices)= vertexB;
- if (vertexB == vertex2A)
- facet2->toporient= !facet2->toporient;
- SETfirst_(facet2->neighbors)= neighborA;
- SETsecond_(facet2->neighbors)= neighborB;
- }else {
- SETfirst_(facet2->vertices)= vertexB;
- SETsecond_(facet2->vertices)= vertexA;
- if (vertexB == vertex2B)
- facet2->toporient= !facet2->toporient;
- SETfirst_(facet2->neighbors)= neighborB;
- SETsecond_(facet2->neighbors)= neighborA;
- }
- qh_makeridges(neighborB);
- qh_setreplace(neighborB->neighbors, facet1, facet2);
- trace4((qh ferr, 4036, "qh_mergefacet2d: merged v%d and neighbor f%d of f%d into f%d\n",
- vertexA->id, neighborB->id, facet1->id, facet2->id));
-} /* mergefacet2d */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergeneighbors">-</a>
-
- qh_mergeneighbors( facet1, facet2 )
- merges the neighbors of facet1 into facet2
-
- see:
- qh_mergecycle_neighbors()
-
- design:
- for each neighbor of facet1
- if neighbor is also a neighbor of facet2
- if neighbor is simpilicial
- make ridges for later deletion as a degenerate facet
- update its neighbor set
- else
- move the neighbor relation to facet2
- remove the neighbor relation for facet1 and facet2
-*/
-void qh_mergeneighbors(facetT *facet1, facetT *facet2) {
- facetT *neighbor, **neighborp;
-
- trace4((qh ferr, 4037, "qh_mergeneighbors: merge neighbors of f%d and f%d\n",
- facet1->id, facet2->id));
- qh visit_id++;
- FOREACHneighbor_(facet2) {
- neighbor->visitid= qh visit_id;
- }
- FOREACHneighbor_(facet1) {
- if (neighbor->visitid == qh visit_id) {
- if (neighbor->simplicial) /* is degen, needs ridges */
- qh_makeridges(neighbor);
- if (SETfirstt_(neighbor->neighbors, facetT) != facet1) /*keep newfacet->horizon*/
- qh_setdel(neighbor->neighbors, facet1);
- else {
- qh_setdel(neighbor->neighbors, facet2);
- qh_setreplace(neighbor->neighbors, facet1, facet2);
- }
- }else if (neighbor != facet2) {
- qh_setappend(&(facet2->neighbors), neighbor);
- qh_setreplace(neighbor->neighbors, facet1, facet2);
- }
- }
- qh_setdel(facet1->neighbors, facet2); /* here for makeridges */
- qh_setdel(facet2->neighbors, facet1);
-} /* mergeneighbors */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergeridges">-</a>
-
- qh_mergeridges( facet1, facet2 )
- merges the ridge set of facet1 into facet2
-
- returns:
- may delete all ridges for a vertex
- sets vertex->delridge on deleted ridges
-
- see:
- qh_mergecycle_ridges()
-
- design:
- delete ridges between facet1 and facet2
- mark (delridge) vertices on these ridges for later testing
- for each remaining ridge
- rename facet1 to facet2
-*/
-void qh_mergeridges(facetT *facet1, facetT *facet2) {
- ridgeT *ridge, **ridgep;
- vertexT *vertex, **vertexp;
-
- trace4((qh ferr, 4038, "qh_mergeridges: merge ridges of f%d and f%d\n",
- facet1->id, facet2->id));
- FOREACHridge_(facet2->ridges) {
- if ((ridge->top == facet1) || (ridge->bottom == facet1)) {
- FOREACHvertex_(ridge->vertices)
- vertex->delridge= True;
- qh_delridge(ridge); /* expensive in high-d, could rebuild */
- ridgep--; /*repeat*/
- }
- }
- FOREACHridge_(facet1->ridges) {
- if (ridge->top == facet1)
- ridge->top= facet2;
- else
- ridge->bottom= facet2;
- qh_setappend(&(facet2->ridges), ridge);
- }
-} /* mergeridges */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergesimplex">-</a>
-
- qh_mergesimplex( facet1, facet2, mergeapex )
- merge simplicial facet1 into facet2
- mergeapex==qh_MERGEapex if merging samecycle into horizon facet
- vertex id is latest (most recently created)
- facet1 may be contained in facet2
- ridges exist for both facets
-
- returns:
- facet2 with updated vertices, ridges, neighbors
- updated neighbors for facet1's vertices
- facet1 not deleted
- sets vertex->delridge on deleted ridges
-
- notes:
- special case code since this is the most common merge
- called from qh_mergefacet()
-
- design:
- if qh_MERGEapex
- add vertices of facet2 to qh.new_vertexlist if necessary
- add apex to facet2
- else
- for each ridge between facet1 and facet2
- set vertex->delridge
- determine the apex for facet1 (i.e., vertex to be merged)
- unless apex already in facet2
- insert apex into vertices for facet2
- add vertices of facet2 to qh.new_vertexlist if necessary
- add apex to qh.new_vertexlist if necessary
- for each vertex of facet1
- if apex
- rename facet1 to facet2 in its vertex neighbors
- else
- delete facet1 from vertex neighors
- if only in facet2
- add vertex to qh.del_vertices for later deletion
- for each ridge of facet1
- delete ridges between facet1 and facet2
- append other ridges to facet2 after renaming facet to facet2
-*/
-void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex) {
- vertexT *vertex, **vertexp, *apex;
- ridgeT *ridge, **ridgep;
- boolT issubset= False;
- int vertex_i= -1, vertex_n;
- facetT *neighbor, **neighborp, *otherfacet;
-
- if (mergeapex) {
- if (!facet2->newfacet)
- qh_newvertices(facet2->vertices); /* apex is new */
- apex= SETfirstt_(facet1->vertices, vertexT);
- if (SETfirstt_(facet2->vertices, vertexT) != apex)
- qh_setaddnth(&facet2->vertices, 0, apex); /* apex has last id */
- else
- issubset= True;
- }else {
- zinc_(Zmergesimplex);
- FOREACHvertex_(facet1->vertices)
- vertex->seen= False;
- FOREACHridge_(facet1->ridges) {
- if (otherfacet_(ridge, facet1) == facet2) {
- FOREACHvertex_(ridge->vertices) {
- vertex->seen= True;
- vertex->delridge= True;
- }
- break;
- }
- }
- FOREACHvertex_(facet1->vertices) {
- if (!vertex->seen)
- break; /* must occur */
- }
- apex= vertex;
- trace4((qh ferr, 4039, "qh_mergesimplex: merge apex v%d of f%d into facet f%d\n",
- apex->id, facet1->id, facet2->id));
- FOREACHvertex_i_(facet2->vertices) {
- if (vertex->id < apex->id) {
- break;
- }else if (vertex->id == apex->id) {
- issubset= True;
- break;
- }
- }
- if (!issubset)
- qh_setaddnth(&facet2->vertices, vertex_i, apex);
- if (!facet2->newfacet)
- qh_newvertices(facet2->vertices);
- else if (!apex->newlist) {
- qh_removevertex(apex);
- qh_appendvertex(apex);
- }
- }
- trace4((qh ferr, 4040, "qh_mergesimplex: update vertex neighbors of f%d\n",
- facet1->id));
- FOREACHvertex_(facet1->vertices) {
- if (vertex == apex && !issubset)
- qh_setreplace(vertex->neighbors, facet1, facet2);
- else {
- qh_setdel(vertex->neighbors, facet1);
- if (!SETsecond_(vertex->neighbors))
- qh_mergevertex_del(vertex, facet1, facet2);
- }
- }
- trace4((qh ferr, 4041, "qh_mergesimplex: merge ridges and neighbors of f%d into f%d\n",
- facet1->id, facet2->id));
- qh visit_id++;
- FOREACHneighbor_(facet2)
- neighbor->visitid= qh visit_id;
- FOREACHridge_(facet1->ridges) {
- otherfacet= otherfacet_(ridge, facet1);
- if (otherfacet == facet2) {
- qh_setdel(facet2->ridges, ridge);
- qh_setfree(&(ridge->vertices));
- qh_memfree(ridge, (int)sizeof(ridgeT));
- qh_setdel(facet2->neighbors, facet1);
- }else {
- qh_setappend(&facet2->ridges, ridge);
- if (otherfacet->visitid != qh visit_id) {
- qh_setappend(&facet2->neighbors, otherfacet);
- qh_setreplace(otherfacet->neighbors, facet1, facet2);
- otherfacet->visitid= qh visit_id;
- }else {
- if (otherfacet->simplicial) /* is degen, needs ridges */
- qh_makeridges(otherfacet);
- if (SETfirstt_(otherfacet->neighbors, facetT) != facet1)
- qh_setdel(otherfacet->neighbors, facet1);
- else { /*keep newfacet->neighbors->horizon*/
- qh_setdel(otherfacet->neighbors, facet2);
- qh_setreplace(otherfacet->neighbors, facet1, facet2);
- }
- }
- if (ridge->top == facet1) /* wait until after qh_makeridges */
- ridge->top= facet2;
- else
- ridge->bottom= facet2;
- }
- }
- SETfirst_(facet1->ridges)= NULL; /* it will be deleted */
- trace3((qh ferr, 3006, "qh_mergesimplex: merged simplex f%d apex v%d into facet f%d\n",
- facet1->id, getid_(apex), facet2->id));
-} /* mergesimplex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergevertex_del">-</a>
-
- qh_mergevertex_del( vertex, facet1, facet2 )
- delete a vertex because of merging facet1 into facet2
-
- returns:
- deletes vertex from facet2
- adds vertex to qh.del_vertices for later deletion
-*/
-void qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2) {
-
- zinc_(Zmergevertex);
- trace2((qh ferr, 2035, "qh_mergevertex_del: deleted v%d when merging f%d into f%d\n",
- vertex->id, facet1->id, facet2->id));
- qh_setdelsorted(facet2->vertices, vertex);
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
-} /* mergevertex_del */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergevertex_neighbors">-</a>
-
- qh_mergevertex_neighbors( facet1, facet2 )
- merge the vertex neighbors of facet1 to facet2
-
- returns:
- if vertex is current qh.vertex_visit
- deletes facet1 from vertex->neighbors
- else
- renames facet1 to facet2 in vertex->neighbors
- deletes vertices if only one neighbor
-
- notes:
- assumes vertex neighbor sets are good
-*/
-void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2) {
- vertexT *vertex, **vertexp;
-
- trace4((qh ferr, 4042, "qh_mergevertex_neighbors: merge vertex neighbors of f%d and f%d\n",
- facet1->id, facet2->id));
- if (qh tracevertex) {
- qh_fprintf(qh ferr, 8081, "qh_mergevertex_neighbors: of f%d and f%d at furthest p%d f0= %p\n",
- facet1->id, facet2->id, qh furthest_id, qh tracevertex->neighbors->e[0].p);
- qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
- }
- FOREACHvertex_(facet1->vertices) {
- if (vertex->visitid != qh vertex_visit)
- qh_setreplace(vertex->neighbors, facet1, facet2);
- else {
- qh_setdel(vertex->neighbors, facet1);
- if (!SETsecond_(vertex->neighbors))
- qh_mergevertex_del(vertex, facet1, facet2);
- }
- }
- if (qh tracevertex)
- qh_errprint("TRACE", NULL, NULL, NULL, qh tracevertex);
-} /* mergevertex_neighbors */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="mergevertices">-</a>
-
- qh_mergevertices( vertices1, vertices2 )
- merges the vertex set of facet1 into facet2
-
- returns:
- replaces vertices2 with merged set
- preserves vertex_visit for qh_mergevertex_neighbors
- updates qh.newvertex_list
-
- design:
- create a merged set of both vertices (in inverse id order)
-*/
-void qh_mergevertices(setT *vertices1, setT **vertices2) {
- int newsize= qh_setsize(vertices1)+qh_setsize(*vertices2) - qh hull_dim + 1;
- setT *mergedvertices;
- vertexT *vertex, **vertexp, **vertex2= SETaddr_(*vertices2, vertexT);
-
- mergedvertices= qh_settemp(newsize);
- FOREACHvertex_(vertices1) {
- if (!*vertex2 || vertex->id > (*vertex2)->id)
- qh_setappend(&mergedvertices, vertex);
- else {
- while (*vertex2 && (*vertex2)->id > vertex->id)
- qh_setappend(&mergedvertices, *vertex2++);
- if (!*vertex2 || (*vertex2)->id < vertex->id)
- qh_setappend(&mergedvertices, vertex);
- else
- qh_setappend(&mergedvertices, *vertex2++);
- }
- }
- while (*vertex2)
- qh_setappend(&mergedvertices, *vertex2++);
- if (newsize < qh_setsize(mergedvertices)) {
- qh_fprintf(qh ferr, 6100, "qhull internal error (qh_mergevertices): facets did not share a ridge\n");
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh_setfree(vertices2);
- *vertices2= mergedvertices;
- qh_settemppop();
-} /* mergevertices */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="neighbor_intersections">-</a>
-
- qh_neighbor_intersections( vertex )
- return intersection of all vertices in vertex->neighbors except for vertex
-
- returns:
- returns temporary set of vertices
- does not include vertex
- NULL if a neighbor is simplicial
- NULL if empty set
-
- notes:
- used for renaming vertices
-
- design:
- initialize the intersection set with vertices of the first two neighbors
- delete vertex from the intersection
- for each remaining neighbor
- intersect its vertex set with the intersection set
- return NULL if empty
- return the intersection set
-*/
-setT *qh_neighbor_intersections(vertexT *vertex) {
- facetT *neighbor, **neighborp, *neighborA, *neighborB;
- setT *intersect;
- int neighbor_i, neighbor_n;
-
- FOREACHneighbor_(vertex) {
- if (neighbor->simplicial)
- return NULL;
- }
- neighborA= SETfirstt_(vertex->neighbors, facetT);
- neighborB= SETsecondt_(vertex->neighbors, facetT);
- zinc_(Zintersectnum);
- if (!neighborA)
- return NULL;
- if (!neighborB)
- intersect= qh_setcopy(neighborA->vertices, 0);
- else
- intersect= qh_vertexintersect_new(neighborA->vertices, neighborB->vertices);
- qh_settemppush(intersect);
- qh_setdelsorted(intersect, vertex);
- FOREACHneighbor_i_(vertex) {
- if (neighbor_i >= 2) {
- zinc_(Zintersectnum);
- qh_vertexintersect(&intersect, neighbor->vertices);
- if (!SETfirst_(intersect)) {
- zinc_(Zintersectfail);
- qh_settempfree(&intersect);
- return NULL;
- }
- }
- }
- trace3((qh ferr, 3007, "qh_neighbor_intersections: %d vertices in neighbor intersection of v%d\n",
- qh_setsize(intersect), vertex->id));
- return intersect;
-} /* neighbor_intersections */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="newvertices">-</a>
-
- qh_newvertices( vertices )
- add vertices to end of qh.vertex_list (marks as new vertices)
-
- returns:
- vertices on qh.newvertex_list
- vertex->newlist set
-*/
-void qh_newvertices(setT *vertices) {
- vertexT *vertex, **vertexp;
-
- FOREACHvertex_(vertices) {
- if (!vertex->newlist) {
- qh_removevertex(vertex);
- qh_appendvertex(vertex);
- }
- }
-} /* newvertices */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="reducevertices">-</a>
-
- qh_reducevertices()
- reduce extra vertices, shared vertices, and redundant vertices
- facet->newmerge is set if merged since last call
- if !qh.MERGEvertices, only removes extra vertices
-
- returns:
- True if also merged degen_redundant facets
- vertices are renamed if possible
- clears facet->newmerge and vertex->delridge
-
- notes:
- ignored if 2-d
-
- design:
- merge any degenerate or redundant facets
- for each newly merged facet
- remove extra vertices
- if qh.MERGEvertices
- for each newly merged facet
- for each vertex
- if vertex was on a deleted ridge
- rename vertex if it is shared
- remove delridge flag from new vertices
-*/
-boolT qh_reducevertices(void) {
- int numshare=0, numrename= 0;
- boolT degenredun= False;
- facetT *newfacet;
- vertexT *vertex, **vertexp;
-
- if (qh hull_dim == 2)
- return False;
- if (qh_merge_degenredundant())
- degenredun= True;
- LABELrestart:
- FORALLnew_facets {
- if (newfacet->newmerge) {
- if (!qh MERGEvertices)
- newfacet->newmerge= False;
- qh_remove_extravertices(newfacet);
- }
- }
- if (!qh MERGEvertices)
- return False;
- FORALLnew_facets {
- if (newfacet->newmerge) {
- newfacet->newmerge= False;
- FOREACHvertex_(newfacet->vertices) {
- if (vertex->delridge) {
- if (qh_rename_sharedvertex(vertex, newfacet)) {
- numshare++;
- vertexp--; /* repeat since deleted vertex */
- }
- }
- }
- }
- }
- FORALLvertex_(qh newvertex_list) {
- if (vertex->delridge && !vertex->deleted) {
- vertex->delridge= False;
- if (qh hull_dim >= 4 && qh_redundant_vertex(vertex)) {
- numrename++;
- if (qh_merge_degenredundant()) {
- degenredun= True;
- goto LABELrestart;
- }
- }
- }
- }
- trace1((qh ferr, 1014, "qh_reducevertices: renamed %d shared vertices and %d redundant vertices. Degen? %d\n",
- numshare, numrename, degenredun));
- return degenredun;
-} /* reducevertices */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="redundant_vertex">-</a>
-
- qh_redundant_vertex( vertex )
- detect and rename a redundant vertex
- vertices have full vertex->neighbors
-
- returns:
- returns true if find a redundant vertex
- deletes vertex(vertex->deleted)
-
- notes:
- only needed if vertex->delridge and hull_dim >= 4
- may add degenerate facets to qh.facet_mergeset
- doesn't change vertex->neighbors or create redundant facets
-
- design:
- intersect vertices of all facet neighbors of vertex
- determine ridges for these vertices
- if find a new vertex for vertex amoung these ridges and vertices
- rename vertex to the new vertex
-*/
-vertexT *qh_redundant_vertex(vertexT *vertex) {
- vertexT *newvertex= NULL;
- setT *vertices, *ridges;
-
- trace3((qh ferr, 3008, "qh_redundant_vertex: check if v%d can be renamed\n", vertex->id));
- if ((vertices= qh_neighbor_intersections(vertex))) {
- ridges= qh_vertexridges(vertex);
- if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
- qh_renamevertex(vertex, newvertex, ridges, NULL, NULL);
- qh_settempfree(&ridges);
- qh_settempfree(&vertices);
- }
- return newvertex;
-} /* redundant_vertex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="remove_extravertices">-</a>
-
- qh_remove_extravertices( facet )
- remove extra vertices from non-simplicial facets
-
- returns:
- returns True if it finds them
-
- design:
- for each vertex in facet
- if vertex not in a ridge (i.e., no longer used)
- delete vertex from facet
- delete facet from vertice's neighbors
- unless vertex in another facet
- add vertex to qh.del_vertices for later deletion
-*/
-boolT qh_remove_extravertices(facetT *facet) {
- ridgeT *ridge, **ridgep;
- vertexT *vertex, **vertexp;
- boolT foundrem= False;
-
- trace4((qh ferr, 4043, "qh_remove_extravertices: test f%d for extra vertices\n",
- facet->id));
- FOREACHvertex_(facet->vertices)
- vertex->seen= False;
- FOREACHridge_(facet->ridges) {
- FOREACHvertex_(ridge->vertices)
- vertex->seen= True;
- }
- FOREACHvertex_(facet->vertices) {
- if (!vertex->seen) {
- foundrem= True;
- zinc_(Zremvertex);
- qh_setdelsorted(facet->vertices, vertex);
- qh_setdel(vertex->neighbors, facet);
- if (!qh_setsize(vertex->neighbors)) {
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
- zinc_(Zremvertexdel);
- trace2((qh ferr, 2036, "qh_remove_extravertices: v%d deleted because it's lost all ridges\n", vertex->id));
- }else
- trace3((qh ferr, 3009, "qh_remove_extravertices: v%d removed from f%d because it's lost all ridges\n", vertex->id, facet->id));
- vertexp--; /*repeat*/
- }
- }
- return foundrem;
-} /* remove_extravertices */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="rename_sharedvertex">-</a>
-
- qh_rename_sharedvertex( vertex, facet )
- detect and rename if shared vertex in facet
- vertices have full ->neighbors
-
- returns:
- newvertex or NULL
- the vertex may still exist in other facets (i.e., a neighbor was pinched)
- does not change facet->neighbors
- updates vertex->neighbors
-
- notes:
- a shared vertex for a facet is only in ridges to one neighbor
- this may undo a pinched facet
-
- it does not catch pinches involving multiple facets. These appear
- to be difficult to detect, since an exhaustive search is too expensive.
-
- design:
- if vertex only has two neighbors
- determine the ridges that contain the vertex
- determine the vertices shared by both neighbors
- if can find a new vertex in this set
- rename the vertex to the new vertex
-*/
-vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet) {
- facetT *neighbor, **neighborp, *neighborA= NULL;
- setT *vertices, *ridges;
- vertexT *newvertex;
-
- if (qh_setsize(vertex->neighbors) == 2) {
- neighborA= SETfirstt_(vertex->neighbors, facetT);
- if (neighborA == facet)
- neighborA= SETsecondt_(vertex->neighbors, facetT);
- }else if (qh hull_dim == 3)
- return NULL;
- else {
- qh visit_id++;
- FOREACHneighbor_(facet)
- neighbor->visitid= qh visit_id;
- FOREACHneighbor_(vertex) {
- if (neighbor->visitid == qh visit_id) {
- if (neighborA)
- return NULL;
- neighborA= neighbor;
- }
- }
- if (!neighborA) {
- qh_fprintf(qh ferr, 6101, "qhull internal error (qh_rename_sharedvertex): v%d's neighbors not in f%d\n",
- vertex->id, facet->id);
- qh_errprint("ERRONEOUS", facet, NULL, NULL, vertex);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- }
- /* the vertex is shared by facet and neighborA */
- ridges= qh_settemp(qh TEMPsize);
- neighborA->visitid= ++qh visit_id;
- qh_vertexridges_facet(vertex, facet, &ridges);
- trace2((qh ferr, 2037, "qh_rename_sharedvertex: p%d(v%d) is shared by f%d(%d ridges) and f%d\n",
- qh_pointid(vertex->point), vertex->id, facet->id, qh_setsize(ridges), neighborA->id));
- zinc_(Zintersectnum);
- vertices= qh_vertexintersect_new(facet->vertices, neighborA->vertices);
- qh_setdel(vertices, vertex);
- qh_settemppush(vertices);
- if ((newvertex= qh_find_newvertex(vertex, vertices, ridges)))
- qh_renamevertex(vertex, newvertex, ridges, facet, neighborA);
- qh_settempfree(&vertices);
- qh_settempfree(&ridges);
- return newvertex;
-} /* rename_sharedvertex */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="renameridgevertex">-</a>
-
- qh_renameridgevertex( ridge, oldvertex, newvertex )
- renames oldvertex as newvertex in ridge
-
- returns:
-
- design:
- delete oldvertex from ridge
- if newvertex already in ridge
- copy ridge->noconvex to another ridge if possible
- delete the ridge
- else
- insert newvertex into the ridge
- adjust the ridge's orientation
-*/
-void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex) {
- int nth= 0, oldnth;
- facetT *temp;
- vertexT *vertex, **vertexp;
-
- oldnth= qh_setindex(ridge->vertices, oldvertex);
- qh_setdelnthsorted(ridge->vertices, oldnth);
- FOREACHvertex_(ridge->vertices) {
- if (vertex == newvertex) {
- zinc_(Zdelridge);
- if (ridge->nonconvex) /* only one ridge has nonconvex set */
- qh_copynonconvex(ridge);
- qh_delridge(ridge);
- trace2((qh ferr, 2038, "qh_renameridgevertex: ridge r%d deleted. It contained both v%d and v%d\n",
- ridge->id, oldvertex->id, newvertex->id));
- return;
- }
- if (vertex->id < newvertex->id)
- break;
- nth++;
- }
- qh_setaddnth(&ridge->vertices, nth, newvertex);
- if (abs(oldnth - nth)%2) {
- trace3((qh ferr, 3010, "qh_renameridgevertex: swapped the top and bottom of ridge r%d\n",
- ridge->id));
- temp= ridge->top;
- ridge->top= ridge->bottom;
- ridge->bottom= temp;
- }
-} /* renameridgevertex */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="renamevertex">-</a>
-
- qh_renamevertex( oldvertex, newvertex, ridges, oldfacet, neighborA )
- renames oldvertex as newvertex in ridges
- gives oldfacet/neighborA if oldvertex is shared between two facets
-
- returns:
- oldvertex may still exist afterwards
-
-
- notes:
- can not change neighbors of newvertex (since it's a subset)
-
- design:
- for each ridge in ridges
- rename oldvertex to newvertex and delete degenerate ridges
- if oldfacet not defined
- for each neighbor of oldvertex
- delete oldvertex from neighbor's vertices
- remove extra vertices from neighbor
- add oldvertex to qh.del_vertices
- else if oldvertex only between oldfacet and neighborA
- delete oldvertex from oldfacet and neighborA
- add oldvertex to qh.del_vertices
- else oldvertex is in oldfacet and neighborA and other facets (i.e., pinched)
- delete oldvertex from oldfacet
- delete oldfacet from oldvertice's neighbors
- remove extra vertices (e.g., oldvertex) from neighborA
-*/
-void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges, facetT *oldfacet, facetT *neighborA) {
- facetT *neighbor, **neighborp;
- ridgeT *ridge, **ridgep;
- boolT istrace= False;
-
- if (qh IStracing >= 2 || oldvertex->id == qh tracevertex_id ||
- newvertex->id == qh tracevertex_id)
- istrace= True;
- FOREACHridge_(ridges)
- qh_renameridgevertex(ridge, oldvertex, newvertex);
- if (!oldfacet) {
- zinc_(Zrenameall);
- if (istrace)
- qh_fprintf(qh ferr, 8082, "qh_renamevertex: renamed v%d to v%d in several facets\n",
- oldvertex->id, newvertex->id);
- FOREACHneighbor_(oldvertex) {
- qh_maydropneighbor(neighbor);
- qh_setdelsorted(neighbor->vertices, oldvertex);
- if (qh_remove_extravertices(neighbor))
- neighborp--; /* neighbor may be deleted */
- }
- if (!oldvertex->deleted) {
- oldvertex->deleted= True;
- qh_setappend(&qh del_vertices, oldvertex);
- }
- }else if (qh_setsize(oldvertex->neighbors) == 2) {
- zinc_(Zrenameshare);
- if (istrace)
- qh_fprintf(qh ferr, 8083, "qh_renamevertex: renamed v%d to v%d in oldfacet f%d\n",
- oldvertex->id, newvertex->id, oldfacet->id);
- FOREACHneighbor_(oldvertex)
- qh_setdelsorted(neighbor->vertices, oldvertex);
- oldvertex->deleted= True;
- qh_setappend(&qh del_vertices, oldvertex);
- }else {
- zinc_(Zrenamepinch);
- if (istrace || qh IStracing)
- qh_fprintf(qh ferr, 8084, "qh_renamevertex: renamed pinched v%d to v%d between f%d and f%d\n",
- oldvertex->id, newvertex->id, oldfacet->id, neighborA->id);
- qh_setdelsorted(oldfacet->vertices, oldvertex);
- qh_setdel(oldvertex->neighbors, oldfacet);
- qh_remove_extravertices(neighborA);
- }
-} /* renamevertex */
-
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="test_appendmerge">-</a>
-
- qh_test_appendmerge( facet, neighbor )
- tests facet/neighbor for convexity
- appends to mergeset if non-convex
- if pre-merging,
- nop if qh.SKIPconvex, or qh.MERGEexact and coplanar
-
- returns:
- true if appends facet/neighbor to mergeset
- sets facet->center as needed
- does not change facet->seen
-
- design:
- if qh.cos_max is defined
- if the angle between facet normals is too shallow
- append an angle-coplanar merge to qh.mergeset
- return True
- make facet's centrum if needed
- if facet's centrum is above the neighbor
- set isconcave
- else
- if facet's centrum is not below the neighbor
- set iscoplanar
- make neighbor's centrum if needed
- if neighbor's centrum is above the facet
- set isconcave
- else if neighbor's centrum is not below the facet
- set iscoplanar
- if isconcave or iscoplanar
- get angle if needed
- append concave or coplanar merge to qh.mergeset
-*/
-boolT qh_test_appendmerge(facetT *facet, facetT *neighbor) {
- realT dist, dist2= -REALmax, angle= -REALmax;
- boolT isconcave= False, iscoplanar= False, okangle= False;
-
- if (qh SKIPconvex && !qh POSTmerging)
- return False;
- if ((!qh MERGEexact || qh POSTmerging) && qh cos_max < REALmax/2) {
- angle= qh_getangle(facet->normal, neighbor->normal);
- zinc_(Zangletests);
- if (angle > qh cos_max) {
- zinc_(Zcoplanarangle);
- qh_appendmergeset(facet, neighbor, MRGanglecoplanar, &angle);
- trace2((qh ferr, 2039, "qh_test_appendmerge: coplanar angle %4.4g between f%d and f%d\n",
- angle, facet->id, neighbor->id));
- return True;
- }else
- okangle= True;
- }
- if (!facet->center)
- facet->center= qh_getcentrum(facet);
- zzinc_(Zcentrumtests);
- qh_distplane(facet->center, neighbor, &dist);
- if (dist > qh centrum_radius)
- isconcave= True;
- else {
- if (dist > -qh centrum_radius)
- iscoplanar= True;
- if (!neighbor->center)
- neighbor->center= qh_getcentrum(neighbor);
- zzinc_(Zcentrumtests);
- qh_distplane(neighbor->center, facet, &dist2);
- if (dist2 > qh centrum_radius)
- isconcave= True;
- else if (!iscoplanar && dist2 > -qh centrum_radius)
- iscoplanar= True;
- }
- if (!isconcave && (!iscoplanar || (qh MERGEexact && !qh POSTmerging)))
- return False;
- if (!okangle && qh ANGLEmerge) {
- angle= qh_getangle(facet->normal, neighbor->normal);
- zinc_(Zangletests);
- }
- if (isconcave) {
- zinc_(Zconcaveridge);
- if (qh ANGLEmerge)
- angle += qh_ANGLEconcave + 0.5;
- qh_appendmergeset(facet, neighbor, MRGconcave, &angle);
- trace0((qh ferr, 18, "qh_test_appendmerge: concave f%d to f%d dist %4.4g and reverse dist %4.4g angle %4.4g during p%d\n",
- facet->id, neighbor->id, dist, dist2, angle, qh furthest_id));
- }else /* iscoplanar */ {
- zinc_(Zcoplanarcentrum);
- qh_appendmergeset(facet, neighbor, MRGcoplanar, &angle);
- trace2((qh ferr, 2040, "qh_test_appendmerge: coplanar f%d to f%d dist %4.4g, reverse dist %4.4g angle %4.4g\n",
- facet->id, neighbor->id, dist, dist2, angle));
- }
- return True;
-} /* test_appendmerge */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="test_vneighbors">-</a>
-
- qh_test_vneighbors()
- test vertex neighbors for convexity
- tests all facets on qh.newfacet_list
-
- returns:
- true if non-convex vneighbors appended to qh.facet_mergeset
- initializes vertex neighbors if needed
-
- notes:
- assumes all facet neighbors have been tested
- this can be expensive
- this does not guarantee that a centrum is below all facets
- but it is unlikely
- uses qh.visit_id
-
- design:
- build vertex neighbors if necessary
- for all new facets
- for all vertices
- for each unvisited facet neighbor of the vertex
- test new facet and neighbor for convexity
-*/
-boolT qh_test_vneighbors(void /* qh newfacet_list */) {
- facetT *newfacet, *neighbor, **neighborp;
- vertexT *vertex, **vertexp;
- int nummerges= 0;
-
- trace1((qh ferr, 1015, "qh_test_vneighbors: testing vertex neighbors for convexity\n"));
- if (!qh VERTEXneighbors)
- qh_vertexneighbors();
- FORALLnew_facets
- newfacet->seen= False;
- FORALLnew_facets {
- newfacet->seen= True;
- newfacet->visitid= qh visit_id++;
- FOREACHneighbor_(newfacet)
- newfacet->visitid= qh visit_id;
- FOREACHvertex_(newfacet->vertices) {
- FOREACHneighbor_(vertex) {
- if (neighbor->seen || neighbor->visitid == qh visit_id)
- continue;
- if (qh_test_appendmerge(newfacet, neighbor))
- nummerges++;
- }
- }
- }
- zadd_(Ztestvneighbor, nummerges);
- trace1((qh ferr, 1016, "qh_test_vneighbors: found %d non-convex, vertex neighbors\n",
- nummerges));
- return (nummerges > 0);
-} /* test_vneighbors */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="tracemerge">-</a>
-
- qh_tracemerge( facet1, facet2 )
- print trace message after merge
-*/
-void qh_tracemerge(facetT *facet1, facetT *facet2) {
- boolT waserror= False;
-
-#ifndef qh_NOtrace
- if (qh IStracing >= 4)
- qh_errprint("MERGED", facet2, NULL, NULL, NULL);
- if (facet2 == qh tracefacet || (qh tracevertex && qh tracevertex->newlist)) {
- qh_fprintf(qh ferr, 8085, "qh_tracemerge: trace facet and vertex after merge of f%d and f%d, furthest p%d\n", facet1->id, facet2->id, qh furthest_id);
- if (facet2 != qh tracefacet)
- qh_errprint("TRACE", qh tracefacet,
- (qh tracevertex && qh tracevertex->neighbors) ?
- SETfirstt_(qh tracevertex->neighbors, facetT) : NULL,
- NULL, qh tracevertex);
- }
- if (qh tracevertex) {
- if (qh tracevertex->deleted)
- qh_fprintf(qh ferr, 8086, "qh_tracemerge: trace vertex deleted at furthest p%d\n",
- qh furthest_id);
- else
- qh_checkvertex(qh tracevertex);
- }
- if (qh tracefacet) {
- qh_checkfacet(qh tracefacet, True, &waserror);
- if (waserror)
- qh_errexit(qh_ERRqhull, qh tracefacet, NULL);
- }
-#endif /* !qh_NOtrace */
- if (qh CHECKfrequently || qh IStracing >= 4) { /* can't check polygon here */
- qh_checkfacet(facet2, True, &waserror);
- if (waserror)
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-} /* tracemerge */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="tracemerging">-</a>
-
- qh_tracemerging()
- print trace message during POSTmerging
-
- returns:
- updates qh.mergereport
-
- notes:
- called from qh_mergecycle() and qh_mergefacet()
-
- see:
- qh_buildtracing()
-*/
-void qh_tracemerging(void) {
- realT cpu;
- int total;
- time_t timedata;
- struct tm *tp;
-
- qh mergereport= zzval_(Ztotmerge);
- time(&timedata);
- tp= localtime(&timedata);
- cpu= qh_CPUclock;
- cpu /= qh_SECticks;
- total= zzval_(Ztotmerge) - zzval_(Zcyclehorizon) + zzval_(Zcyclefacettot);
- qh_fprintf(qh ferr, 8087, "\n\
-At %d:%d:%d & %2.5g CPU secs, qhull has merged %d facets. The hull\n\
- contains %d facets and %d vertices.\n",
- tp->tm_hour, tp->tm_min, tp->tm_sec, cpu,
- total, qh num_facets - qh num_visible,
- qh num_vertices-qh_setsize(qh del_vertices));
-} /* tracemerging */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="updatetested">-</a>
-
- qh_updatetested( facet1, facet2 )
- clear facet2->tested and facet1->ridge->tested for merge
-
- returns:
- deletes facet2->center unless it's already large
- if so, clears facet2->ridge->tested
-
- design:
- clear facet2->tested
- clear ridge->tested for facet1's ridges
- if facet2 has a centrum
- if facet2 is large
- set facet2->keepcentrum
- else if facet2 has 3 vertices due to many merges, or not large and post merging
- clear facet2->keepcentrum
- unless facet2->keepcentrum
- clear facet2->center to recompute centrum later
- clear ridge->tested for facet2's ridges
-*/
-void qh_updatetested(facetT *facet1, facetT *facet2) {
- ridgeT *ridge, **ridgep;
- int size;
-
- facet2->tested= False;
- FOREACHridge_(facet1->ridges)
- ridge->tested= False;
- if (!facet2->center)
- return;
- size= qh_setsize(facet2->vertices);
- if (!facet2->keepcentrum) {
- if (size > qh hull_dim + qh_MAXnewcentrum) {
- facet2->keepcentrum= True;
- zinc_(Zwidevertices);
- }
- }else if (size <= qh hull_dim + qh_MAXnewcentrum) {
- /* center and keepcentrum was set */
- if (size == qh hull_dim || qh POSTmerging)
- facet2->keepcentrum= False; /* if many merges need to recompute centrum */
- }
- if (!facet2->keepcentrum) {
- qh_memfree(facet2->center, qh normal_size);
- facet2->center= NULL;
- FOREACHridge_(facet2->ridges)
- ridge->tested= False;
- }
-} /* updatetested */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="vertexridges">-</a>
-
- qh_vertexridges( vertex )
- return temporary set of ridges adjacent to a vertex
- vertex->neighbors defined
-
- ntoes:
- uses qh.visit_id
- does not include implicit ridges for simplicial facets
-
- design:
- for each neighbor of vertex
- add ridges that include the vertex to ridges
-*/
-setT *qh_vertexridges(vertexT *vertex) {
- facetT *neighbor, **neighborp;
- setT *ridges= qh_settemp(qh TEMPsize);
- int size;
-
- qh visit_id++;
- FOREACHneighbor_(vertex)
- neighbor->visitid= qh visit_id;
- FOREACHneighbor_(vertex) {
- if (*neighborp) /* no new ridges in last neighbor */
- qh_vertexridges_facet(vertex, neighbor, &ridges);
- }
- if (qh PRINTstatistics || qh IStracing) {
- size= qh_setsize(ridges);
- zinc_(Zvertexridge);
- zadd_(Zvertexridgetot, size);
- zmax_(Zvertexridgemax, size);
- trace3((qh ferr, 3011, "qh_vertexridges: found %d ridges for v%d\n",
- size, vertex->id));
- }
- return ridges;
-} /* vertexridges */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="vertexridges_facet">-</a>
-
- qh_vertexridges_facet( vertex, facet, ridges )
- add adjacent ridges for vertex in facet
- neighbor->visitid==qh.visit_id if it hasn't been visited
-
- returns:
- ridges updated
- sets facet->visitid to qh.visit_id-1
-
- design:
- for each ridge of facet
- if ridge of visited neighbor (i.e., unprocessed)
- if vertex in ridge
- append ridge to vertex
- mark facet processed
-*/
-void qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges) {
- ridgeT *ridge, **ridgep;
- facetT *neighbor;
-
- FOREACHridge_(facet->ridges) {
- neighbor= otherfacet_(ridge, facet);
- if (neighbor->visitid == qh visit_id
- && qh_setin(ridge->vertices, vertex))
- qh_setappend(ridges, ridge);
- }
- facet->visitid= qh visit_id-1;
-} /* vertexridges_facet */
-
-/*-<a href="qh-merge.htm#TOC"
- >-------------------------------</a><a name="willdelete">-</a>
-
- qh_willdelete( facet, replace )
- moves facet to visible list
- sets facet->f.replace to replace (may be NULL)
-
- returns:
- bumps qh.num_visible
-*/
-void qh_willdelete(facetT *facet, facetT *replace) {
-
- qh_removefacet(facet);
- qh_prependfacet(facet, &qh visible_list);
- qh num_visible++;
- facet->visible= True;
- facet->f.replace= replace;
-} /* willdelete */
-
-#else /* qh_NOmerge */
-void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle) {
-}
-void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
- boolT vneighbors) {
-}
-boolT qh_checkzero(boolT testall) {
- }
-#endif /* qh_NOmerge */
-
diff --git a/PyMca/Object3D/Object3DQhull/src/merge.h b/PyMca/Object3D/Object3DQhull/src/merge.h
deleted file mode 100644
index da0fb53..0000000
--- a/PyMca/Object3D/Object3DQhull/src/merge.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*<html><pre> -<a href="qh-merge.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- merge.h
- header file for merge.c
-
- see qh-merge.htm and merge.c
-
- Copyright (c) 1993-2012 C.B. Barber.
- $Id: //main/2011/qhull/src/libqhull/merge.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFmerge
-#define qhDEFmerge 1
-
-#include "libqhull.h"
-
-
-/*============ -constants- ==============*/
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="qh_ANGLEredundant">-</a>
-
- qh_ANGLEredundant
- indicates redundant merge in mergeT->angle
-*/
-#define qh_ANGLEredundant 6.0
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="qh_ANGLEdegen">-</a>
-
- qh_ANGLEdegen
- indicates degenerate facet in mergeT->angle
-*/
-#define qh_ANGLEdegen 5.0
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="qh_ANGLEconcave">-</a>
-
- qh_ANGLEconcave
- offset to indicate concave facets in mergeT->angle
-
- notes:
- concave facets are assigned the range of [2,4] in mergeT->angle
- roundoff error may make the angle less than 2
-*/
-#define qh_ANGLEconcave 1.5
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="MRG">-</a>
-
- MRG... (mergeType)
- indicates the type of a merge (mergeT->type)
-*/
-typedef enum { /* in sort order for facet_mergeset */
- MRGnone= 0,
- MRGcoplanar, /* centrum coplanar */
- MRGanglecoplanar, /* angle coplanar */
- /* could detect half concave ridges */
- MRGconcave, /* concave ridge */
- MRGflip, /* flipped facet. facet1 == facet2 */
- MRGridge, /* duplicate ridge (qh_MERGEridge) */
- /* degen and redundant go onto degen_mergeset */
- MRGdegen, /* degenerate facet (!enough neighbors) facet1 == facet2 */
- MRGredundant, /* redundant facet (vertex subset) */
- /* merge_degenredundant assumes degen < redundant */
- MRGmirror, /* mirror facet from qh_triangulate */
- ENDmrg
-} mergeType;
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="qh_MERGEapex">-</a>
-
- qh_MERGEapex
- flag for qh_mergefacet() to indicate an apex merge
-*/
-#define qh_MERGEapex True
-
-/*============ -structures- ====================*/
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="mergeT">-</a>
-
- mergeT
- structure used to merge facets
-*/
-
-typedef struct mergeT mergeT;
-struct mergeT { /* initialize in qh_appendmergeset */
- realT angle; /* angle between normals of facet1 and facet2 */
- facetT *facet1; /* will merge facet1 into facet2 */
- facetT *facet2;
- mergeType type;
-};
-
-
-/*=========== -macros- =========================*/
-
-/*-<a href="qh-merge.htm#TOC"
- >--------------------------------</a><a name="FOREACHmerge_">-</a>
-
- FOREACHmerge_( merges ) {...}
- assign 'merge' to each merge in merges
-
- notes:
- uses 'mergeT *merge, **mergep;'
- if qh_mergefacet(),
- restart since qh.facet_mergeset may change
- see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHmerge_( merges ) FOREACHsetelement_(mergeT, merges, merge)
-
-/*============ prototypes in alphabetical order after pre/postmerge =======*/
-
-void qh_premerge(vertexT *apex, realT maxcentrum, realT maxangle);
-void qh_postmerge(const char *reason, realT maxcentrum, realT maxangle,
- boolT vneighbors);
-void qh_all_merges(boolT othermerge, boolT vneighbors);
-void qh_appendmergeset(facetT *facet, facetT *neighbor, mergeType mergetype, realT *angle);
-setT *qh_basevertices( facetT *samecycle);
-void qh_checkconnect(void /* qh new_facets */);
-boolT qh_checkzero(boolT testall);
-int qh_compareangle(const void *p1, const void *p2);
-int qh_comparemerge(const void *p1, const void *p2);
-int qh_comparevisit(const void *p1, const void *p2);
-void qh_copynonconvex(ridgeT *atridge);
-void qh_degen_redundant_facet(facetT *facet);
-void qh_degen_redundant_neighbors(facetT *facet, facetT *delfacet);
-vertexT *qh_find_newvertex(vertexT *oldvertex, setT *vertices, setT *ridges);
-void qh_findbest_test(boolT testcentrum, facetT *facet, facetT *neighbor,
- facetT **bestfacet, realT *distp, realT *mindistp, realT *maxdistp);
-facetT *qh_findbestneighbor(facetT *facet, realT *distp, realT *mindistp, realT *maxdistp);
-void qh_flippedmerges(facetT *facetlist, boolT *wasmerge);
-void qh_forcedmerges( boolT *wasmerge);
-void qh_getmergeset(facetT *facetlist);
-void qh_getmergeset_initial(facetT *facetlist);
-void qh_hashridge(setT *hashtable, int hashsize, ridgeT *ridge, vertexT *oldvertex);
-ridgeT *qh_hashridge_find(setT *hashtable, int hashsize, ridgeT *ridge,
- vertexT *vertex, vertexT *oldvertex, int *hashslot);
-void qh_makeridges(facetT *facet);
-void qh_mark_dupridges(facetT *facetlist);
-void qh_maydropneighbor(facetT *facet);
-int qh_merge_degenredundant(void);
-void qh_merge_nonconvex( facetT *facet1, facetT *facet2, mergeType mergetype);
-void qh_mergecycle(facetT *samecycle, facetT *newfacet);
-void qh_mergecycle_all(facetT *facetlist, boolT *wasmerge);
-void qh_mergecycle_facets( facetT *samecycle, facetT *newfacet);
-void qh_mergecycle_neighbors(facetT *samecycle, facetT *newfacet);
-void qh_mergecycle_ridges(facetT *samecycle, facetT *newfacet);
-void qh_mergecycle_vneighbors( facetT *samecycle, facetT *newfacet);
-void qh_mergefacet(facetT *facet1, facetT *facet2, realT *mindist, realT *maxdist, boolT mergeapex);
-void qh_mergefacet2d(facetT *facet1, facetT *facet2);
-void qh_mergeneighbors(facetT *facet1, facetT *facet2);
-void qh_mergeridges(facetT *facet1, facetT *facet2);
-void qh_mergesimplex(facetT *facet1, facetT *facet2, boolT mergeapex);
-void qh_mergevertex_del(vertexT *vertex, facetT *facet1, facetT *facet2);
-void qh_mergevertex_neighbors(facetT *facet1, facetT *facet2);
-void qh_mergevertices(setT *vertices1, setT **vertices);
-setT *qh_neighbor_intersections(vertexT *vertex);
-void qh_newvertices(setT *vertices);
-boolT qh_reducevertices(void);
-vertexT *qh_redundant_vertex(vertexT *vertex);
-boolT qh_remove_extravertices(facetT *facet);
-vertexT *qh_rename_sharedvertex(vertexT *vertex, facetT *facet);
-void qh_renameridgevertex(ridgeT *ridge, vertexT *oldvertex, vertexT *newvertex);
-void qh_renamevertex(vertexT *oldvertex, vertexT *newvertex, setT *ridges,
- facetT *oldfacet, facetT *neighborA);
-boolT qh_test_appendmerge(facetT *facet, facetT *neighbor);
-boolT qh_test_vneighbors(void /* qh newfacet_list */);
-void qh_tracemerge(facetT *facet1, facetT *facet2);
-void qh_tracemerging(void);
-void qh_updatetested( facetT *facet1, facetT *facet2);
-setT *qh_vertexridges(vertexT *vertex);
-void qh_vertexridges_facet(vertexT *vertex, facetT *facet, setT **ridges);
-void qh_willdelete(facetT *facet, facetT *replace);
-
-#endif /* qhDEFmerge */
diff --git a/PyMca/Object3D/Object3DQhull/src/poly.c b/PyMca/Object3D/Object3DQhull/src/poly.c
deleted file mode 100644
index a3a0a48..0000000
--- a/PyMca/Object3D/Object3DQhull/src/poly.c
+++ /dev/null
@@ -1,1199 +0,0 @@
-/*<html><pre> -<a href="qh-poly.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- poly.c
- implements polygons and simplices
-
- see qh-poly.htm, poly.h and libqhull.h
-
- infrequent code is in poly2.c
- (all but top 50 and their callers 12/3/95)
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/poly.c#5 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="appendfacet">-</a>
-
- qh_appendfacet( facet )
- appends facet to end of qh.facet_list,
-
- returns:
- updates qh.newfacet_list, facet_next, facet_list
- increments qh.numfacets
-
- notes:
- assumes qh.facet_list/facet_tail is defined (createsimplex)
-
- see:
- qh_removefacet()
-
-*/
-void qh_appendfacet(facetT *facet) {
- facetT *tail= qh facet_tail;
-
- if (tail == qh newfacet_list)
- qh newfacet_list= facet;
- if (tail == qh facet_next)
- qh facet_next= facet;
- facet->previous= tail->previous;
- facet->next= tail;
- if (tail->previous)
- tail->previous->next= facet;
- else
- qh facet_list= facet;
- tail->previous= facet;
- qh num_facets++;
- trace4((qh ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
-} /* appendfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="appendvertex">-</a>
-
- qh_appendvertex( vertex )
- appends vertex to end of qh.vertex_list,
-
- returns:
- sets vertex->newlist
- updates qh.vertex_list, newvertex_list
- increments qh.num_vertices
-
- notes:
- assumes qh.vertex_list/vertex_tail is defined (createsimplex)
-
-*/
-void qh_appendvertex(vertexT *vertex) {
- vertexT *tail= qh vertex_tail;
-
- if (tail == qh newvertex_list)
- qh newvertex_list= vertex;
- vertex->newlist= True;
- vertex->previous= tail->previous;
- vertex->next= tail;
- if (tail->previous)
- tail->previous->next= vertex;
- else
- qh vertex_list= vertex;
- tail->previous= vertex;
- qh num_vertices++;
- trace4((qh ferr, 4045, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
-} /* appendvertex */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="attachnewfacets">-</a>
-
- qh_attachnewfacets( )
- attach horizon facets to new facets in qh.newfacet_list
- newfacets have neighbor and ridge links to horizon but not vice versa
- only needed for qh.ONLYgood
-
- returns:
- set qh.NEWfacets
- horizon facets linked to new facets
- ridges changed from visible facets to new facets
- simplicial ridges deleted
- qh.visible_list, no ridges valid
- facet->f.replace is a newfacet (if any)
-
- design:
- delete interior ridges and neighbor sets by
- for each visible, non-simplicial facet
- for each ridge
- if last visit or if neighbor is simplicial
- if horizon neighbor
- delete ridge for horizon's ridge set
- delete ridge
- erase neighbor set
- attach horizon facets and new facets by
- for all new facets
- if corresponding horizon facet is simplicial
- locate corresponding visible facet {may be more than one}
- link visible facet to new facet
- replace visible facet with new facet in horizon
- else it's non-simplicial
- for all visible neighbors of the horizon facet
- link visible neighbor to new facet
- delete visible neighbor from horizon facet
- append new facet to horizon's neighbors
- the first ridge of the new facet is the horizon ridge
- link the new facet into the horizon ridge
-*/
-void qh_attachnewfacets(void ) {
- facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
- ridgeT *ridge, **ridgep;
-
- qh NEWfacets= True;
- trace3((qh ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
- qh visit_id++;
- FORALLvisible_facets {
- visible->visitid= qh visit_id;
- if (visible->ridges) {
- FOREACHridge_(visible->ridges) {
- neighbor= otherfacet_(ridge, visible);
- if (neighbor->visitid == qh visit_id
- || (!neighbor->visible && neighbor->simplicial)) {
- if (!neighbor->visible) /* delete ridge for simplicial horizon */
- qh_setdel(neighbor->ridges, ridge);
- qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
- qh_memfree(ridge, (int)sizeof(ridgeT));
- }
- }
- SETfirst_(visible->ridges)= NULL;
- }
- SETfirst_(visible->neighbors)= NULL;
- }
- trace1((qh ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
- FORALLnew_facets {
- horizon= SETfirstt_(newfacet->neighbors, facetT);
- if (horizon->simplicial) {
- visible= NULL;
- FOREACHneighbor_(horizon) { /* may have more than one horizon ridge */
- if (neighbor->visible) {
- if (visible) {
- if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
- SETindex_(horizon->neighbors, neighbor))) {
- visible= neighbor;
- break;
- }
- }else
- visible= neighbor;
- }
- }
- if (visible) {
- visible->f.replace= newfacet;
- qh_setreplace(horizon->neighbors, visible, newfacet);
- }else {
- qh_fprintf(qh ferr, 6102, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
- horizon->id, newfacet->id);
- qh_errexit2 (qh_ERRqhull, horizon, newfacet);
- }
- }else { /* non-simplicial, with a ridge for newfacet */
- FOREACHneighbor_(horizon) { /* may hold for many new facets */
- if (neighbor->visible) {
- neighbor->f.replace= newfacet;
- qh_setdelnth(horizon->neighbors,
- SETindex_(horizon->neighbors, neighbor));
- neighborp--; /* repeat */
- }
- }
- qh_setappend(&horizon->neighbors, newfacet);
- ridge= SETfirstt_(newfacet->ridges, ridgeT);
- if (ridge->top == horizon)
- ridge->bottom= newfacet;
- else
- ridge->top= newfacet;
- }
- } /* newfacets */
- if (qh PRINTstatistics) {
- FORALLvisible_facets {
- if (!visible->f.replace)
- zinc_(Zinsidevisible);
- }
- }
-} /* attachnewfacets */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkflipped">-</a>
-
- qh_checkflipped( facet, dist, allerror )
- checks facet orientation to interior point
-
- if allerror set,
- tests against qh.DISTround
- else
- tests against 0 since tested against DISTround before
-
- returns:
- False if it flipped orientation (sets facet->flipped)
- distance if non-NULL
-*/
-boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) {
- realT dist;
-
- if (facet->flipped && !distp)
- return False;
- zzinc_(Zdistcheck);
- qh_distplane(qh interior_point, facet, &dist);
- if (distp)
- *distp= dist;
- if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
- facet->flipped= True;
- zzinc_(Zflippedfacets);
- trace0((qh ferr, 19, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
- facet->id, dist, qh furthest_id));
- qh_precision("flipped facet");
- return False;
- }
- return True;
-} /* checkflipped */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="delfacet">-</a>
-
- qh_delfacet( facet )
- removes facet from facet_list and frees up its memory
-
- notes:
- assumes vertices and ridges already freed
-*/
-void qh_delfacet(facetT *facet) {
- void **freelistp; /* used !qh_NOmem */
-
- trace4((qh ferr, 4046, "qh_delfacet: delete f%d\n", facet->id));
- if (facet == qh tracefacet)
- qh tracefacet= NULL;
- if (facet == qh GOODclosest)
- qh GOODclosest= NULL;
- qh_removefacet(facet);
- if (!facet->tricoplanar || facet->keepcentrum) {
- qh_memfree_(facet->normal, qh normal_size, freelistp);
- if (qh CENTERtype == qh_ASvoronoi) { /* uses macro calls */
- qh_memfree_(facet->center, qh center_size, freelistp);
- }else /* AScentrum */ {
- qh_memfree_(facet->center, qh normal_size, freelistp);
- }
- }
- qh_setfree(&(facet->neighbors));
- if (facet->ridges)
- qh_setfree(&(facet->ridges));
- qh_setfree(&(facet->vertices));
- if (facet->outsideset)
- qh_setfree(&(facet->outsideset));
- if (facet->coplanarset)
- qh_setfree(&(facet->coplanarset));
- qh_memfree_(facet, (int)sizeof(facetT), freelistp);
-} /* delfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="deletevisible">-</a>
-
- qh_deletevisible()
- delete visible facets and vertices
-
- returns:
- deletes each facet and removes from facetlist
- at exit, qh.visible_list empty (== qh.newfacet_list)
-
- notes:
- ridges already deleted
- horizon facets do not reference facets on qh.visible_list
- new facets in qh.newfacet_list
- uses qh.visit_id;
-*/
-void qh_deletevisible(void /*qh visible_list*/) {
- facetT *visible, *nextfacet;
- vertexT *vertex, **vertexp;
- int numvisible= 0, numdel= qh_setsize(qh del_vertices);
-
- trace1((qh ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
- qh num_visible, numdel));
- for (visible= qh visible_list; visible && visible->visible;
- visible= nextfacet) { /* deleting current */
- nextfacet= visible->next;
- numvisible++;
- qh_delfacet(visible);
- }
- if (numvisible != qh num_visible) {
- qh_fprintf(qh ferr, 6103, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
- qh num_visible, numvisible);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- qh num_visible= 0;
- zadd_(Zvisfacettot, numvisible);
- zmax_(Zvisfacetmax, numvisible);
- zzadd_(Zdelvertextot, numdel);
- zmax_(Zdelvertexmax, numdel);
- FOREACHvertex_(qh del_vertices)
- qh_delvertex(vertex);
- qh_settruncate(qh del_vertices, 0);
-} /* deletevisible */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="facetintersect">-</a>
-
- qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
- return vertices for intersection of two simplicial facets
- may include 1 prepended entry (if more, need to settemppush)
-
- returns:
- returns set of qh.hull_dim-1 + prepend vertices
- returns skipped index for each test and checks for exactly one
-
- notes:
- does not need settemp since set in quick memory
-
- see also:
- qh_vertexintersect and qh_vertexintersect_new
- use qh_setnew_delnthsorted to get nth ridge (no skip information)
-
- design:
- locate skipped vertex by scanning facet A's neighbors
- locate skipped vertex by scanning facet B's neighbors
- intersect the vertex sets
-*/
-setT *qh_facetintersect(facetT *facetA, facetT *facetB,
- int *skipA,int *skipB, int prepend) {
- setT *intersect;
- int dim= qh hull_dim, i, j;
- facetT **neighborsA, **neighborsB;
-
- neighborsA= SETaddr_(facetA->neighbors, facetT);
- neighborsB= SETaddr_(facetB->neighbors, facetT);
- i= j= 0;
- if (facetB == *neighborsA++)
- *skipA= 0;
- else if (facetB == *neighborsA++)
- *skipA= 1;
- else if (facetB == *neighborsA++)
- *skipA= 2;
- else {
- for (i=3; i < dim; i++) {
- if (facetB == *neighborsA++) {
- *skipA= i;
- break;
- }
- }
- }
- if (facetA == *neighborsB++)
- *skipB= 0;
- else if (facetA == *neighborsB++)
- *skipB= 1;
- else if (facetA == *neighborsB++)
- *skipB= 2;
- else {
- for (j=3; j < dim; j++) {
- if (facetA == *neighborsB++) {
- *skipB= j;
- break;
- }
- }
- }
- if (i >= dim || j >= dim) {
- qh_fprintf(qh ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
- facetA->id, facetB->id);
- qh_errexit2 (qh_ERRqhull, facetA, facetB);
- }
- intersect= qh_setnew_delnthsorted(facetA->vertices, qh hull_dim, *skipA, prepend);
- trace4((qh ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
- facetA->id, *skipA, facetB->id, *skipB));
- return(intersect);
-} /* facetintersect */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="gethash">-</a>
-
- qh_gethash( hashsize, set, size, firstindex, skipelem )
- return hashvalue for a set with firstindex and skipelem
-
- notes:
- returned hash is in [0,hashsize)
- assumes at least firstindex+1 elements
- assumes skipelem is NULL, in set, or part of hash
-
- hashes memory addresses which may change over different runs of the same data
- using sum for hash does badly in high d
-*/
-int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) {
- void **elemp= SETelemaddr_(set, firstindex, void);
- ptr_intT hash = 0, elem;
- unsigned result;
- int i;
-#ifdef _MSC_VER /* Microsoft Visual C++ -- warn about 64-bit issues */
-#pragma warning( push) /* WARN64 -- ptr_intT holds a 64-bit pointer */
-#pragma warning( disable : 4311) /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
-#endif
-
- switch (size-firstindex) {
- case 1:
- hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
- break;
- case 2:
- hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
- break;
- case 3:
- hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
- - (ptr_intT) skipelem;
- break;
- case 4:
- hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
- + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
- break;
- case 5:
- hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
- + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
- break;
- case 6:
- hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
- + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
- - (ptr_intT) skipelem;
- break;
- default:
- hash= 0;
- i= 3;
- do { /* this is about 10% in 10-d */
- if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
- hash ^= (elem << i) + (elem >> (32-i));
- i += 3;
- if (i >= 32)
- i -= 32;
- }
- }while (*elemp);
- break;
- }
- if (hashsize<0) {
- qh_fprintf(qh ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize);
- qh_errexit2 (qh_ERRqhull, NULL, NULL);
- }
- result= (unsigned)hash;
- result %= (unsigned)hashsize;
- /* result= 0; for debugging */
- return result;
-#ifdef _MSC_VER
-#pragma warning( pop)
-#endif
-} /* gethash */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="makenewfacet">-</a>
-
- qh_makenewfacet( vertices, toporient, horizon )
- creates a toporient? facet from vertices
-
- returns:
- returns newfacet
- adds newfacet to qh.facet_list
- newfacet->vertices= vertices
- if horizon
- newfacet->neighbor= horizon, but not vice versa
- newvertex_list updated with vertices
-*/
-facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
- facetT *newfacet;
- vertexT *vertex, **vertexp;
-
- FOREACHvertex_(vertices) {
- if (!vertex->newlist) {
- qh_removevertex(vertex);
- qh_appendvertex(vertex);
- }
- }
- newfacet= qh_newfacet();
- newfacet->vertices= vertices;
- newfacet->toporient= (unsigned char)toporient;
- if (horizon)
- qh_setappend(&(newfacet->neighbors), horizon);
- qh_appendfacet(newfacet);
- return(newfacet);
-} /* makenewfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="makenewplanes">-</a>
-
- qh_makenewplanes()
- make new hyperplanes for facets on qh.newfacet_list
-
- returns:
- all facets have hyperplanes or are marked for merging
- doesn't create hyperplane if horizon is coplanar (will merge)
- updates qh.min_vertex if qh.JOGGLEmax
-
- notes:
- facet->f.samecycle is defined for facet->mergehorizon facets
-*/
-void qh_makenewplanes(void /* newfacet_list */) {
- facetT *newfacet;
-
- FORALLnew_facets {
- if (!newfacet->mergehorizon)
- qh_setfacetplane(newfacet);
- }
- if (qh JOGGLEmax < REALmax/2)
- minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
-} /* makenewplanes */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
-
- qh_makenew_nonsimplicial( visible, apex, numnew )
- make new facets for ridges of a visible facet
-
- returns:
- first newfacet, bumps numnew as needed
- attaches new facets if !qh.ONLYgood
- marks ridge neighbors for simplicial visible
- if (qh.ONLYgood)
- ridges on newfacet, horizon, and visible
- else
- ridge and neighbors between newfacet and horizon
- visible facet's ridges are deleted
-
- notes:
- qh.visit_id if visible has already been processed
- sets neighbor->seen for building f.samecycle
- assumes all 'seen' flags initially false
-
- design:
- for each ridge of visible facet
- get neighbor of visible facet
- if neighbor was already processed
- delete the ridge (will delete all visible facets later)
- if neighbor is a horizon facet
- create a new facet
- if neighbor coplanar
- adds newfacet to f.samecycle for later merging
- else
- updates neighbor's neighbor set
- (checks for non-simplicial facet with multiple ridges to visible facet)
- updates neighbor's ridge set
- (checks for simplicial neighbor to non-simplicial visible facet)
- (deletes ridge if neighbor is simplicial)
-
-*/
-#ifndef qh_NOmerge
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
- void **freelistp; /* used !qh_NOmem */
- ridgeT *ridge, **ridgep;
- facetT *neighbor, *newfacet= NULL, *samecycle;
- setT *vertices;
- boolT toporient;
- int ridgeid;
-
- FOREACHridge_(visible->ridges) {
- ridgeid= ridge->id;
- neighbor= otherfacet_(ridge, visible);
- if (neighbor->visible) {
- if (!qh ONLYgood) {
- if (neighbor->visitid == qh visit_id) {
- qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
- qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
- }
- }
- }else { /* neighbor is an horizon facet */
- toporient= (ridge->top == visible);
- vertices= qh_setnew(qh hull_dim); /* makes sure this is quick */
- qh_setappend(&vertices, apex);
- qh_setappend_set(&vertices, ridge->vertices);
- newfacet= qh_makenewfacet(vertices, toporient, neighbor);
- (*numnew)++;
- if (neighbor->coplanar) {
- newfacet->mergehorizon= True;
- if (!neighbor->seen) {
- newfacet->f.samecycle= newfacet;
- neighbor->f.newcycle= newfacet;
- }else {
- samecycle= neighbor->f.newcycle;
- newfacet->f.samecycle= samecycle->f.samecycle;
- samecycle->f.samecycle= newfacet;
- }
- }
- if (qh ONLYgood) {
- if (!neighbor->simplicial)
- qh_setappend(&(newfacet->ridges), ridge);
- }else { /* qh_attachnewfacets */
- if (neighbor->seen) {
- if (neighbor->simplicial) {
- qh_fprintf(qh ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
- neighbor->id, visible->id);
- qh_errexit2 (qh_ERRqhull, neighbor, visible);
- }
- qh_setappend(&(neighbor->neighbors), newfacet);
- }else
- qh_setreplace(neighbor->neighbors, visible, newfacet);
- if (neighbor->simplicial) {
- qh_setdel(neighbor->ridges, ridge);
- qh_setfree(&(ridge->vertices));
- qh_memfree(ridge, (int)sizeof(ridgeT));
- }else {
- qh_setappend(&(newfacet->ridges), ridge);
- if (toporient)
- ridge->top= newfacet;
- else
- ridge->bottom= newfacet;
- }
- trace4((qh ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
- newfacet->id, apex->id, ridgeid, neighbor->id));
- }
- }
- neighbor->seen= True;
- } /* for each ridge */
- if (!qh ONLYgood)
- SETfirst_(visible->ridges)= NULL;
- return newfacet;
-} /* makenew_nonsimplicial */
-#else /* qh_NOmerge */
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
- return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="makenew_simplicial">-</a>
-
- qh_makenew_simplicial( visible, apex, numnew )
- make new facets for simplicial visible facet and apex
-
- returns:
- attaches new facets if (!qh.ONLYgood)
- neighbors between newfacet and horizon
-
- notes:
- nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
-
- design:
- locate neighboring horizon facet for visible facet
- determine vertices and orientation
- create new facet
- if coplanar,
- add new facet to f.samecycle
- update horizon facet's neighbor list
-*/
-facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) {
- facetT *neighbor, **neighborp, *newfacet= NULL;
- setT *vertices;
- boolT flip, toporient;
- int horizonskip, visibleskip;
-
- FOREACHneighbor_(visible) {
- if (!neighbor->seen && !neighbor->visible) {
- vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
- SETfirst_(vertices)= apex;
- flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
- if (neighbor->toporient)
- toporient= horizonskip & 0x1;
- else
- toporient= (horizonskip & 0x1) ^ 0x1;
- newfacet= qh_makenewfacet(vertices, toporient, neighbor);
- (*numnew)++;
- if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
-#ifndef qh_NOmerge
- newfacet->f.samecycle= newfacet;
- newfacet->mergehorizon= True;
-#endif
- }
- if (!qh ONLYgood)
- SETelem_(neighbor->neighbors, horizonskip)= newfacet;
- trace4((qh ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
- newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
- neighbor->toporient, visible->id, visibleskip, flip));
- }
- }
- return newfacet;
-} /* makenew_simplicial */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="matchneighbor">-</a>
-
- qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
- either match subridge of newfacet with neighbor or add to hash_table
-
- returns:
- duplicate ridges are unmatched and marked by qh_DUPLICATEridge
-
- notes:
- ridge is newfacet->vertices w/o newskip vertex
- do not allocate memory (need to free hash_table cleanly)
- uses linear hash chains
-
- see also:
- qh_matchduplicates
-
- design:
- for each possible matching facet in qh.hash_table
- if vertices match
- set ismatch, if facets have opposite orientation
- if ismatch and matching facet doesn't have a match
- match the facets by updating their neighbor sets
- else
- indicate a duplicate ridge
- set facet hyperplane for later testing
- add facet to hashtable
- unless the other facet was already a duplicate ridge
- mark both facets with a duplicate ridge
- add other facet (if defined) to hash table
-*/
-void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) {
- boolT newfound= False; /* True, if new facet is already in hash chain */
- boolT same, ismatch;
- int hash, scan;
- facetT *facet, *matchfacet;
- int skip, matchskip;
-
- hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1,
- SETelem_(newfacet->vertices, newskip));
- trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
- newfacet->id, newskip, hash, *hashcount));
- zinc_(Zhashlookup);
- for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
- scan= (++scan >= hashsize ? 0 : scan)) {
- if (facet == newfacet) {
- newfound= True;
- continue;
- }
- zinc_(Zhashtests);
- if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
- if (SETelem_(newfacet->vertices, newskip) ==
- SETelem_(facet->vertices, skip)) {
- qh_precision("two facets with the same vertices");
- qh_fprintf(qh ferr, 6106, "qhull precision error: Vertex sets are the same for f%d and f%d. Can not force output.\n",
- facet->id, newfacet->id);
- qh_errexit2 (qh_ERRprec, facet, newfacet);
- }
- ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
- matchfacet= SETelemt_(facet->neighbors, skip, facetT);
- if (ismatch && !matchfacet) {
- SETelem_(facet->neighbors, skip)= newfacet;
- SETelem_(newfacet->neighbors, newskip)= facet;
- (*hashcount)--;
- trace4((qh ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
- facet->id, skip, newfacet->id, newskip));
- return;
- }
- if (!qh PREmerge && !qh MERGEexact) {
- qh_precision("a ridge with more than two neighbors");
- qh_fprintf(qh ferr, 6107, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors. Can not continue.\n",
- facet->id, newfacet->id, getid_(matchfacet));
- qh_errexit2 (qh_ERRprec, facet, newfacet);
- }
- SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
- newfacet->dupridge= True;
- if (!newfacet->normal)
- qh_setfacetplane(newfacet);
- qh_addhash(newfacet, qh hash_table, hashsize, hash);
- (*hashcount)++;
- if (!facet->normal)
- qh_setfacetplane(facet);
- if (matchfacet != qh_DUPLICATEridge) {
- SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
- facet->dupridge= True;
- if (!facet->normal)
- qh_setfacetplane(facet);
- if (matchfacet) {
- matchskip= qh_setindex(matchfacet->neighbors, facet);
- SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
- matchfacet->dupridge= True;
- if (!matchfacet->normal)
- qh_setfacetplane(matchfacet);
- qh_addhash(matchfacet, qh hash_table, hashsize, hash);
- *hashcount += 2;
- }
- }
- trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
- newfacet->id, newskip, facet->id, skip,
- (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
- ismatch, hash));
- return; /* end of duplicate ridge */
- }
- }
- if (!newfound)
- SETelem_(qh hash_table, scan)= newfacet; /* same as qh_addhash */
- (*hashcount)++;
- trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
- newfacet->id, newskip, hash));
-} /* matchneighbor */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="matchnewfacets">-</a>
-
- qh_matchnewfacets()
- match newfacets in qh.newfacet_list to their newfacet neighbors
-
- returns:
- qh.newfacet_list with full neighbor sets
- get vertices with nth neighbor by deleting nth vertex
- if qh.PREmerge/MERGEexact or qh.FORCEoutput
- sets facet->flippped if flipped normal (also prevents point partitioning)
- if duplicate ridges and qh.PREmerge/MERGEexact
- sets facet->dupridge
- missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
-
- notes:
- newfacets already have neighbor[0] (horizon facet)
- assumes qh.hash_table is NULL
- vertex->neighbors has not been updated yet
- do not allocate memory after qh.hash_table (need to free it cleanly)
-
- design:
- delete neighbor sets for all new facets
- initialize a hash table
- for all new facets
- match facet with neighbors
- if unmatched facets (due to duplicate ridges)
- for each new facet with a duplicate ridge
- match it with a facet
- check for flipped facets
-*/
-void qh_matchnewfacets(void /* qh newfacet_list */) {
- int numnew=0, hashcount=0, newskip;
- facetT *newfacet, *neighbor;
- int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
- setT *neighbors;
-#ifndef qh_NOtrace
- int facet_i, facet_n, numfree= 0;
- facetT *facet;
-#endif
-
- trace1((qh ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
- FORALLnew_facets {
- numnew++;
- { /* inline qh_setzero(newfacet->neighbors, 1, qh hull_dim); */
- neighbors= newfacet->neighbors;
- neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
- memset((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
- }
- }
-
- qh_newhashtable(numnew*(qh hull_dim-1)); /* twice what is normally needed,
- but every ridge could be DUPLICATEridge */
- hashsize= qh_setsize(qh hash_table);
- FORALLnew_facets {
- for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
- qh_matchneighbor(newfacet, newskip, hashsize, &hashcount);
-#if 0 /* use the following to trap hashcount errors */
- {
- int count= 0, k;
- facetT *facet, *neighbor;
-
- count= 0;
- FORALLfacet_(qh newfacet_list) { /* newfacet already in use */
- for (k=1; k < qh hull_dim; k++) {
- neighbor= SETelemt_(facet->neighbors, k, facetT);
- if (!neighbor || neighbor == qh_DUPLICATEridge)
- count++;
- }
- if (facet == newfacet)
- break;
- }
- if (count != hashcount) {
- qh_fprintf(qh ferr, 8088, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
- newfacet->id, hashcount, count);
- qh_errexit(qh_ERRqhull, newfacet, NULL);
- }
- }
-#endif /* end of trap code */
- }
- if (hashcount) {
- FORALLnew_facets {
- if (newfacet->dupridge) {
- FOREACHneighbor_i_(newfacet) {
- if (neighbor == qh_DUPLICATEridge) {
- qh_matchduplicates(newfacet, neighbor_i, hashsize, &hashcount);
- /* this may report MERGEfacet */
- }
- }
- }
- }
- }
- if (hashcount) {
- qh_fprintf(qh ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
- hashcount);
- qh_printhashtable(qh ferr);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
-#ifndef qh_NOtrace
- if (qh IStracing >= 2) {
- FOREACHfacet_i_(qh hash_table) {
- if (!facet)
- numfree++;
- }
- qh_fprintf(qh ferr, 8089, "qh_matchnewfacets: %d new facets, %d unused hash entries . hashsize %d\n",
- numnew, numfree, qh_setsize(qh hash_table));
- }
-#endif /* !qh_NOtrace */
- qh_setfree(&qh hash_table);
- if (qh PREmerge || qh MERGEexact) {
- if (qh IStracing >= 4)
- qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
- FORALLnew_facets {
- if (newfacet->normal)
- qh_checkflipped(newfacet, NULL, qh_ALL);
- }
- }else if (qh FORCEoutput)
- qh_checkflipped_all(qh newfacet_list); /* prints warnings for flipped */
-} /* matchnewfacets */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="matchvertices">-</a>
-
- qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
- tests whether vertices match with a single skip
- starts match at firstindex since all new facets have a common vertex
-
- returns:
- true if matched vertices
- skip index for each set
- sets same iff vertices have the same orientation
-
- notes:
- assumes skipA is in A and both sets are the same size
-
- design:
- set up pointers
- scan both sets checking for a match
- test orientation
-*/
-boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
- setT *verticesB, int *skipB, boolT *same) {
- vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
-
- elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
- elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
- skipAp= SETelemaddr_(verticesA, skipA, vertexT);
- do if (elemAp != skipAp) {
- while (*elemAp != *elemBp++) {
- if (skipBp)
- return False;
- skipBp= elemBp; /* one extra like FOREACH */
- }
- }while (*(++elemAp));
- if (!skipBp)
- skipBp= ++elemBp;
- *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB */
- *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
- trace4((qh ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
- skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
- return(True);
-} /* matchvertices */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="newfacet">-</a>
-
- qh_newfacet()
- return a new facet
-
- returns:
- all fields initialized or cleared (NULL)
- preallocates neighbors set
-*/
-facetT *qh_newfacet(void) {
- facetT *facet;
- void **freelistp; /* used !qh_NOmem */
-
- qh_memalloc_((int)sizeof(facetT), freelistp, facet, facetT);
- memset((char *)facet, (size_t)0, sizeof(facetT));
- if (qh facet_id == qh tracefacet_id)
- qh tracefacet= facet;
- facet->id= qh facet_id++;
- facet->neighbors= qh_setnew(qh hull_dim);
-#if !qh_COMPUTEfurthest
- facet->furthestdist= 0.0;
-#endif
-#if qh_MAXoutside
- if (qh FORCEoutput && qh APPROXhull)
- facet->maxoutside= qh MINoutside;
- else
- facet->maxoutside= qh DISTround;
-#endif
- facet->simplicial= True;
- facet->good= True;
- facet->newfacet= True;
- trace4((qh ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
- return(facet);
-} /* newfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="newridge">-</a>
-
- qh_newridge()
- return a new ridge
-*/
-ridgeT *qh_newridge(void) {
- ridgeT *ridge;
- void **freelistp; /* used !qh_NOmem */
-
- qh_memalloc_((int)sizeof(ridgeT), freelistp, ridge, ridgeT);
- memset((char *)ridge, (size_t)0, sizeof(ridgeT));
- zinc_(Ztotridges);
- if (qh ridge_id == 0xFFFFFF) {
- qh_fprintf(qh ferr, 7074, "\
-qhull warning: more than %d ridges. ID field overflows and two ridges\n\
-may have the same identifier. Otherwise output ok.\n", 0xFFFFFF);
- }
- ridge->id= qh ridge_id++;
- trace4((qh ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
- return(ridge);
-} /* newridge */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="pointid">-</a>
-
- qh_pointid( )
- return id for a point,
- returns -3 if null, -2 if interior, or -1 if not known
-
- alternative code:
- unsigned long id;
- id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
-
- notes:
- WARN64 -- id truncated to 32-bits, at most 2G points
- NOerrors returned (QhullPoint::id)
- if point not in point array
- the code does a comparison of unrelated pointers.
-*/
-int qh_pointid(pointT *point) {
- ptr_intT offset, id;
-
- if (!point)
- return -3;
- else if (point == qh interior_point)
- return -2;
- else if (point >= qh first_point
- && point < qh first_point + qh num_points * qh hull_dim) {
- offset= (ptr_intT)(point - qh first_point);
- id= offset / qh hull_dim;
- }else if ((id= qh_setindex(qh other_points, point)) != -1)
- id += qh num_points;
- else
- return -1;
- return (int)id;
-} /* pointid */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="removefacet">-</a>
-
- qh_removefacet( facet )
- unlinks facet from qh.facet_list,
-
- returns:
- updates qh.facet_list .newfacet_list .facet_next visible_list
- decrements qh.num_facets
-
- see:
- qh_appendfacet
-*/
-void qh_removefacet(facetT *facet) {
- facetT *next= facet->next, *previous= facet->previous;
-
- if (facet == qh newfacet_list)
- qh newfacet_list= next;
- if (facet == qh facet_next)
- qh facet_next= next;
- if (facet == qh visible_list)
- qh visible_list= next;
- if (previous) {
- previous->next= next;
- next->previous= previous;
- }else { /* 1st facet in qh facet_list */
- qh facet_list= next;
- qh facet_list->previous= NULL;
- }
- qh num_facets--;
- trace4((qh ferr, 4057, "qh_removefacet: remove f%d from facet_list\n", facet->id));
-} /* removefacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="removevertex">-</a>
-
- qh_removevertex( vertex )
- unlinks vertex from qh.vertex_list,
-
- returns:
- updates qh.vertex_list .newvertex_list
- decrements qh.num_vertices
-*/
-void qh_removevertex(vertexT *vertex) {
- vertexT *next= vertex->next, *previous= vertex->previous;
-
- if (vertex == qh newvertex_list)
- qh newvertex_list= next;
- if (previous) {
- previous->next= next;
- next->previous= previous;
- }else { /* 1st vertex in qh vertex_list */
- qh vertex_list= vertex->next;
- qh vertex_list->previous= NULL;
- }
- qh num_vertices--;
- trace4((qh ferr, 4058, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
-} /* removevertex */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="updatevertices">-</a>
-
- qh_updatevertices()
- update vertex neighbors and delete interior vertices
-
- returns:
- if qh.VERTEXneighbors, updates neighbors for each vertex
- if qh.newvertex_list,
- removes visible neighbors from vertex neighbors
- if qh.newfacet_list
- adds new facets to vertex neighbors
- if qh.visible_list
- interior vertices added to qh.del_vertices for later partitioning
-
- design:
- if qh.VERTEXneighbors
- deletes references to visible facets from vertex neighbors
- appends new facets to the neighbor list for each vertex
- checks all vertices of visible facets
- removes visible facets from neighbor lists
- marks unused vertices for deletion
-*/
-void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) {
- facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
- vertexT *vertex, **vertexp;
-
- trace3((qh ferr, 3013, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
- if (qh VERTEXneighbors) {
- FORALLvertex_(qh newvertex_list) {
- FOREACHneighbor_(vertex) {
- if (neighbor->visible)
- SETref_(neighbor)= NULL;
- }
- qh_setcompact(vertex->neighbors);
- }
- FORALLnew_facets {
- FOREACHvertex_(newfacet->vertices)
- qh_setappend(&vertex->neighbors, newfacet);
- }
- FORALLvisible_facets {
- FOREACHvertex_(visible->vertices) {
- if (!vertex->newlist && !vertex->deleted) {
- FOREACHneighbor_(vertex) { /* this can happen under merging */
- if (!neighbor->visible)
- break;
- }
- if (neighbor)
- qh_setdel(vertex->neighbors, visible);
- else {
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
- trace2((qh ferr, 2041, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
- qh_pointid(vertex->point), vertex->id, visible->id));
- }
- }
- }
- }
- }else { /* !VERTEXneighbors */
- FORALLvisible_facets {
- FOREACHvertex_(visible->vertices) {
- if (!vertex->newlist && !vertex->deleted) {
- vertex->deleted= True;
- qh_setappend(&qh del_vertices, vertex);
- trace2((qh ferr, 2042, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
- qh_pointid(vertex->point), vertex->id, visible->id));
- }
- }
- }
- }
-} /* updatevertices */
-
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/poly.h b/PyMca/Object3D/Object3DQhull/src/poly.h
deleted file mode 100644
index 9cf04cf..0000000
--- a/PyMca/Object3D/Object3DQhull/src/poly.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/*<html><pre> -<a href="qh-poly.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- poly.h
- header file for poly.c and poly2.c
-
- see qh-poly.htm, libqhull.h and poly.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/poly.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFpoly
-#define qhDEFpoly 1
-
-#include "libqhull.h"
-
-/*=============== constants ========================== */
-
-/*-<a href="qh-geom.htm#TOC"
- >--------------------------------</a><a name="ALGORITHMfault">-</a>
-
- ALGORITHMfault
- use as argument to checkconvex() to report errors during buildhull
-*/
-#define qh_ALGORITHMfault 0
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="DATAfault">-</a>
-
- DATAfault
- use as argument to checkconvex() to report errors during initialhull
-*/
-#define qh_DATAfault 1
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="DUPLICATEridge">-</a>
-
- DUPLICATEridge
- special value for facet->neighbor to indicate a duplicate ridge
-
- notes:
- set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_DUPLICATEridge (facetT *)1L
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="MERGEridge">-</a>
-
- MERGEridge flag in facet
- special value for facet->neighbor to indicate a merged ridge
-
- notes:
- set by matchneighbor, used by matchmatch and mark_dupridge
-*/
-#define qh_MERGEridge (facetT *)2L
-
-
-/*============ -structures- ====================*/
-
-/*=========== -macros- =========================*/
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLfacet_">-</a>
-
- FORALLfacet_( facetlist ) { ... }
- assign 'facet' to each facet in facetlist
-
- notes:
- uses 'facetT *facet;'
- assumes last facet is a sentinel
-
- see:
- FORALLfacets
-*/
-#define FORALLfacet_( facetlist ) if (facetlist ) for ( facet=( facetlist ); facet && facet->next; facet= facet->next )
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLnew_facets">-</a>
-
- FORALLnew_facets { ... }
- assign 'newfacet' to each facet in qh.newfacet_list
-
- notes:
- uses 'facetT *newfacet;'
- at exit, newfacet==NULL
-*/
-#define FORALLnew_facets for ( newfacet=qh newfacet_list;newfacet && newfacet->next;newfacet=newfacet->next )
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLvertex_">-</a>
-
- FORALLvertex_( vertexlist ) { ... }
- assign 'vertex' to each vertex in vertexlist
-
- notes:
- uses 'vertexT *vertex;'
- at exit, vertex==NULL
-*/
-#define FORALLvertex_( vertexlist ) for (vertex=( vertexlist );vertex && vertex->next;vertex= vertex->next )
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLvisible_facets">-</a>
-
- FORALLvisible_facets { ... }
- assign 'visible' to each visible facet in qh.visible_list
-
- notes:
- uses 'vacetT *visible;'
- at exit, visible==NULL
-*/
-#define FORALLvisible_facets for (visible=qh visible_list; visible && visible->visible; visible= visible->next)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLsame_">-</a>
-
- FORALLsame_( newfacet ) { ... }
- assign 'same' to each facet in newfacet->f.samecycle
-
- notes:
- uses 'facetT *same;'
- stops when it returns to newfacet
-*/
-#define FORALLsame_(newfacet) for (same= newfacet->f.samecycle; same != newfacet; same= same->f.samecycle)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FORALLsame_cycle_">-</a>
-
- FORALLsame_cycle_( newfacet ) { ... }
- assign 'same' to each facet in newfacet->f.samecycle
-
- notes:
- uses 'facetT *same;'
- at exit, same == NULL
-*/
-#define FORALLsame_cycle_(newfacet) \
- for (same= newfacet->f.samecycle; \
- same; same= (same == newfacet ? NULL : same->f.samecycle))
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHneighborA_">-</a>
-
- FOREACHneighborA_( facet ) { ... }
- assign 'neighborA' to each neighbor in facet->neighbors
-
- FOREACHneighborA_( vertex ) { ... }
- assign 'neighborA' to each neighbor in vertex->neighbors
-
- declare:
- facetT *neighborA, **neighborAp;
-
- see:
- <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHneighborA_(facet) FOREACHsetelement_(facetT, facet->neighbors, neighborA)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHvisible_">-</a>
-
- FOREACHvisible_( facets ) { ... }
- assign 'visible' to each facet in facets
-
- notes:
- uses 'facetT *facet, *facetp;'
- see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHvisible_(facets) FOREACHsetelement_(facetT, facets, visible)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHnewfacet_">-</a>
-
- FOREACHnewfacet_( facets ) { ... }
- assign 'newfacet' to each facet in facets
-
- notes:
- uses 'facetT *newfacet, *newfacetp;'
- see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHnewfacet_(facets) FOREACHsetelement_(facetT, facets, newfacet)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHvertexA_">-</a>
-
- FOREACHvertexA_( vertices ) { ... }
- assign 'vertexA' to each vertex in vertices
-
- notes:
- uses 'vertexT *vertexA, *vertexAp;'
- see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHvertexA_(vertices) FOREACHsetelement_(vertexT, vertices, vertexA)
-
-/*-<a href="qh-poly.htm#TOC"
- >--------------------------------</a><a name="FOREACHvertexreverse12_">-</a>
-
- FOREACHvertexreverse12_( vertices ) { ... }
- assign 'vertex' to each vertex in vertices
- reverse order of first two vertices
-
- notes:
- uses 'vertexT *vertex, *vertexp;'
- see <a href="qset.h#FOREACHsetelement_">FOREACHsetelement_</a>
-*/
-#define FOREACHvertexreverse12_(vertices) FOREACHsetelementreverse12_(vertexT, vertices, vertex)
-
-
-/*=============== prototypes poly.c in alphabetical order ================*/
-
-void qh_appendfacet(facetT *facet);
-void qh_appendvertex(vertexT *vertex);
-void qh_attachnewfacets(void);
-boolT qh_checkflipped(facetT *facet, realT *dist, boolT allerror);
-void qh_delfacet(facetT *facet);
-void qh_deletevisible(void /*qh visible_list, qh horizon_list*/);
-setT *qh_facetintersect(facetT *facetA, facetT *facetB, int *skipAp,int *skipBp, int extra);
-int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem);
-facetT *qh_makenewfacet(setT *vertices, boolT toporient, facetT *facet);
-void qh_makenewplanes(void /* newfacet_list */);
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew);
-facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew);
-void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize,
- int *hashcount);
-void qh_matchnewfacets(void);
-boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
- setT *verticesB, int *skipB, boolT *same);
-facetT *qh_newfacet(void);
-ridgeT *qh_newridge(void);
-int qh_pointid(pointT *point);
-void qh_removefacet(facetT *facet);
-void qh_removevertex(vertexT *vertex);
-void qh_updatevertices(void);
-
-
-/*========== -prototypes poly2.c in alphabetical order ===========*/
-
-void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash);
-void qh_check_bestdist(void);
-void qh_check_maxout(void);
-void qh_check_output(void);
-void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2);
-void qh_check_points(void);
-void qh_checkconvex(facetT *facetlist, int fault);
-void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp);
-void qh_checkflipped_all(facetT *facetlist);
-void qh_checkpolygon(facetT *facetlist);
-void qh_checkvertex(vertexT *vertex);
-void qh_clearcenters(qh_CENTER type);
-void qh_createsimplex(setT *vertices);
-void qh_delridge(ridgeT *ridge);
-void qh_delvertex(vertexT *vertex);
-setT *qh_facet3vertex(facetT *facet);
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
- realT *bestdist, boolT *isoutside);
-facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart);
-facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
- int *numpart);
-int qh_findgood(facetT *facetlist, int goodhorizon);
-void qh_findgood_all(facetT *facetlist);
-void qh_furthestnext(void /* qh facet_list */);
-void qh_furthestout(facetT *facet);
-void qh_infiniteloop(facetT *facet);
-void qh_initbuild(void);
-void qh_initialhull(setT *vertices);
-setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints);
-vertexT *qh_isvertex(pointT *point, setT *vertices);
-vertexT *qh_makenewfacets(pointT *point /*horizon_list, visible_list*/);
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount);
-void qh_nearcoplanar(void /* qh.facet_list */);
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp);
-int qh_newhashtable(int newsize);
-vertexT *qh_newvertex(pointT *point);
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp);
-void qh_outcoplanar(void /* facet_list */);
-pointT *qh_point(int id);
-void qh_point_add(setT *set, pointT *point, void *elem);
-setT *qh_pointfacet(void /*qh facet_list*/);
-setT *qh_pointvertex(void /*qh facet_list*/);
-void qh_prependfacet(facetT *facet, facetT **facetlist);
-void qh_printhashtable(FILE *fp);
-void qh_printlists(void);
-void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/);
-void qh_setvoronoi_all(void);
-void qh_triangulate(void /*qh facet_list*/);
-void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex);
-void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB);
-void qh_triangulate_mirror(facetT *facetA, facetT *facetB);
-void qh_triangulate_null(facetT *facetA);
-void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB);
-setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB);
-void qh_vertexneighbors(void /*qh facet_list*/);
-boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB);
-
-
-#endif /* qhDEFpoly */
diff --git a/PyMca/Object3D/Object3DQhull/src/poly2.c b/PyMca/Object3D/Object3DQhull/src/poly2.c
deleted file mode 100644
index 317461f..0000000
--- a/PyMca/Object3D/Object3DQhull/src/poly2.c
+++ /dev/null
@@ -1,3154 +0,0 @@
-/*<html><pre> -<a href="qh-poly.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- poly2.c
- implements polygons and simplices
-
- see qh-poly.htm, poly.h and libqhull.h
-
- frequently used code is in poly.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/poly2.c#5 $$Change: 1490 $
- $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="addhash">-</a>
-
- qh_addhash( newelem, hashtable, hashsize, hash )
- add newelem to linear hash table at hash if not already there
-*/
-void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) {
- int scan;
- void *elem;
-
- for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
- scan= (++scan >= hashsize ? 0 : scan)) {
- if (elem == newelem)
- break;
- }
- /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
- if (!elem)
- SETelem_(hashtable, scan)= newelem;
-} /* addhash */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="check_bestdist">-</a>
-
- qh_check_bestdist()
- check that all points are within max_outside of the nearest facet
- if qh.ONLYgood,
- ignores !good facets
-
- see:
- qh_check_maxout(), qh_outerinner()
-
- notes:
- only called from qh_check_points()
- seldom used since qh.MERGING is almost always set
- if notverified>0 at end of routine
- some points were well inside the hull. If the hull contains
- a lens-shaped component, these points were not verified. Use
- options 'Qi Tv' to verify all points. (Exhaustive check also verifies)
-
- design:
- determine facet for each point (if any)
- for each point
- start with the assigned facet or with the first facet
- find the best facet for the point and check all coplanar facets
- error if point is outside of facet
-*/
-void qh_check_bestdist(void) {
- boolT waserror= False, unassigned;
- facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
- facetT *facetlist;
- realT dist, maxoutside, maxdist= -REALmax;
- pointT *point;
- int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
- setT *facets;
-
- trace1((qh ferr, 1020, "qh_check_bestdist: check points below nearest facet. Facet_list f%d\n",
- qh facet_list->id));
- maxoutside= qh_maxouter();
- maxoutside += qh DISTround;
- /* one more qh.DISTround for check computation */
- trace1((qh ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
- facets= qh_pointfacet(/*qh facet_list*/);
- if (!qh_QUICKhelp && qh PRINTprecision)
- qh_fprintf(qh ferr, 8091, "\n\
-qhull output completed. Verifying that %d points are\n\
-below %2.2g of the nearest %sfacet.\n",
- qh_setsize(facets), maxoutside, (qh ONLYgood ? "good " : ""));
- FOREACHfacet_i_(facets) { /* for each point with facet assignment */
- if (facet)
- unassigned= False;
- else {
- unassigned= True;
- facet= qh facet_list;
- }
- point= qh_point(facet_i);
- if (point == qh GOODpointp)
- continue;
- qh_distplane(point, facet, &dist);
- numpart++;
- bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
- /* occurs after statistics reported */
- maximize_(maxdist, dist);
- if (dist > maxoutside) {
- if (qh ONLYgood && !bestfacet->good
- && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
- && dist > maxoutside))
- notgood++;
- else {
- waserror= True;
- qh_fprintf(qh ferr, 6109, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
- facet_i, bestfacet->id, dist, maxoutside);
- if (errfacet1 != bestfacet) {
- errfacet2= errfacet1;
- errfacet1= bestfacet;
- }
- }
- }else if (unassigned && dist < -qh MAXcoplanar)
- notverified++;
- }
- qh_settempfree(&facets);
- if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
- qh_fprintf(qh ferr, 8092, "\n%d points were well inside the hull. If the hull contains\n\
-a lens-shaped component, these points were not verified. Use\n\
-options 'Qci Tv' to verify all points.\n", notverified);
- if (maxdist > qh outside_err) {
- qh_fprintf(qh ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull. The maximum value(qh.outside_err) is %6.2g\n",
- maxdist, qh outside_err);
- qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
- }else if (waserror && qh outside_err > REALmax/2)
- qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
- /* else if waserror, the error was logged to qh.ferr but does not effect the output */
- trace0((qh ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
-} /* check_bestdist */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="check_maxout">-</a>
-
- qh_check_maxout()
- updates qh.max_outside by checking all points against bestfacet
- if qh.ONLYgood, ignores !good facets
-
- returns:
- updates facet->maxoutside via qh_findbesthorizon()
- sets qh.maxoutdone
- if printing qh.min_vertex (qh_outerinner),
- it is updated to the current vertices
- removes inside/coplanar points from coplanarset as needed
-
- notes:
- defines coplanar as min_vertex instead of MAXcoplanar
- may not need to check near-inside points because of qh.MAXcoplanar
- and qh.KEEPnearinside (before it was -DISTround)
-
- see also:
- qh_check_bestdist()
-
- design:
- if qh.min_vertex is needed
- for all neighbors of all vertices
- test distance from vertex to neighbor
- determine facet for each point (if any)
- for each point with an assigned facet
- find the best facet for the point and check all coplanar facets
- (updates outer planes)
- remove near-inside points from coplanar sets
-*/
-#ifndef qh_NOmerge
-void qh_check_maxout(void) {
- facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
- realT dist, maxoutside, minvertex, old_maxoutside;
- pointT *point;
- int numpart= 0, facet_i, facet_n, notgood= 0;
- setT *facets, *vertices;
- vertexT *vertex;
-
- trace1((qh ferr, 1022, "qh_check_maxout: check and update maxoutside for each facet.\n"));
- maxoutside= minvertex= 0;
- if (qh VERTEXneighbors
- && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
- || qh TRACElevel || qh PRINTstatistics
- || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
- trace1((qh ferr, 1023, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
- vertices= qh_pointvertex(/*qh facet_list*/);
- FORALLvertices {
- FOREACHneighbor_(vertex) {
- zinc_(Zdistvertex); /* distance also computed by main loop below */
- qh_distplane(vertex->point, neighbor, &dist);
- minimize_(minvertex, dist);
- if (-dist > qh TRACEdist || dist > qh TRACEdist
- || neighbor == qh tracefacet || vertex == qh tracevertex)
- qh_fprintf(qh ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d\n",
- qh_pointid(vertex->point), vertex->id, dist, neighbor->id);
- }
- }
- if (qh MERGING) {
- wmin_(Wminvertex, qh min_vertex);
- }
- qh min_vertex= minvertex;
- qh_settempfree(&vertices);
- }
- facets= qh_pointfacet(/*qh facet_list*/);
- do {
- old_maxoutside= fmax_(qh max_outside, maxoutside);
- FOREACHfacet_i_(facets) { /* for each point with facet assignment */
- if (facet) {
- point= qh_point(facet_i);
- if (point == qh GOODpointp)
- continue;
- zzinc_(Ztotcheck);
- qh_distplane(point, facet, &dist);
- numpart++;
- bestfacet= qh_findbesthorizon(qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
- if (bestfacet && dist > maxoutside) {
- if (qh ONLYgood && !bestfacet->good
- && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
- && dist > maxoutside))
- notgood++;
- else
- maxoutside= dist;
- }
- if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
- qh_fprintf(qh ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
- qh_pointid(point), dist, bestfacet->id);
- }
- }
- }while
- (maxoutside > 2*old_maxoutside);
- /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
- e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
- zzadd_(Zcheckpart, numpart);
- qh_settempfree(&facets);
- wval_(Wmaxout)= maxoutside - qh max_outside;
- wmax_(Wmaxoutside, qh max_outside);
- qh max_outside= maxoutside;
- qh_nearcoplanar(/*qh.facet_list*/);
- qh maxoutdone= True;
- trace1((qh ferr, 1024, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
- maxoutside, qh min_vertex, notgood));
-} /* check_maxout */
-#else /* qh_NOmerge */
-void qh_check_maxout(void) {
-}
-#endif
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="check_output">-</a>
-
- qh_check_output()
- performs the checks at the end of qhull algorithm
- Maybe called after voronoi output. Will recompute otherwise centrums are Voronoi centers instead
-*/
-void qh_check_output(void) {
- int i;
-
- if (qh STOPcone)
- return;
- if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
- qh_checkpolygon(qh facet_list);
- qh_checkflipped_all(qh facet_list);
- qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
- }else if (!qh MERGING && qh_newstats(qhstat precision, &i)) {
- qh_checkflipped_all(qh facet_list);
- qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
- }
-} /* check_output */
-
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="check_point">-</a>
-
- qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
- check that point is less than maxoutside from facet
-*/
-void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
- realT dist;
-
- /* occurs after statistics reported */
- qh_distplane(point, facet, &dist);
- if (dist > *maxoutside) {
- if (*errfacet1 != facet) {
- *errfacet2= *errfacet1;
- *errfacet1= facet;
- }
- qh_fprintf(qh ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
- qh_pointid(point), facet->id, dist, *maxoutside);
- }
- maximize_(*maxdist, dist);
-} /* qh_check_point */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="check_points">-</a>
-
- qh_check_points()
- checks that all points are inside all facets
-
- notes:
- if many points and qh_check_maxout not called (i.e., !qh.MERGING),
- calls qh_findbesthorizon (seldom done).
- ignores flipped facets
- maxoutside includes 2 qh.DISTrounds
- one qh.DISTround for the computed distances in qh_check_points
- qh_printafacet and qh_printsummary needs only one qh.DISTround
- the computation for qh.VERIFYdirect does not account for qh.other_points
-
- design:
- if many points
- use qh_check_bestdist()
- else
- for all facets
- for all points
- check that point is inside facet
-*/
-void qh_check_points(void) {
- facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
- realT total, maxoutside, maxdist= -REALmax;
- pointT *point, **pointp, *pointtemp;
- boolT testouter;
-
- maxoutside= qh_maxouter();
- maxoutside += qh DISTround;
- /* one more qh.DISTround for check computation */
- trace1((qh ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
- maxoutside));
- if (qh num_good) /* miss counts other_points and !good facets */
- total= (float)qh num_good * (float)qh num_points;
- else
- total= (float)qh num_facets * (float)qh num_points;
- if (total >= qh_VERIFYdirect && !qh maxoutdone) {
- if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
- qh_fprintf(qh ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').\n\
-Verify may report that a point is outside of a facet.\n");
- qh_check_bestdist();
- }else {
- if (qh_MAXoutside && qh maxoutdone)
- testouter= True;
- else
- testouter= False;
- if (!qh_QUICKhelp) {
- if (qh MERGEexact)
- qh_fprintf(qh ferr, 7076, "qhull input warning: exact merge ('Qx'). Verify may report that a point\n\
-is outside of a facet. See qh-optq.htm#Qx\n");
- else if (qh SKIPcheckmax || qh NOnearinside)
- qh_fprintf(qh ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of\n\
-near-inside points ('Q8'). Verify may report that a point is outside\n\
-of a facet.\n");
- }
- if (qh PRINTprecision) {
- if (testouter)
- qh_fprintf(qh ferr, 8098, "\n\
-Output completed. Verifying that all points are below outer planes of\n\
-all %sfacets. Will make %2.0f distance computations.\n",
- (qh ONLYgood ? "good " : ""), total);
- else
- qh_fprintf(qh ferr, 8099, "\n\
-Output completed. Verifying that all points are below %2.2g of\n\
-all %sfacets. Will make %2.0f distance computations.\n",
- maxoutside, (qh ONLYgood ? "good " : ""), total);
- }
- FORALLfacets {
- if (!facet->good && qh ONLYgood)
- continue;
- if (facet->flipped)
- continue;
- if (!facet->normal) {
- qh_fprintf(qh ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
- continue;
- }
- if (testouter) {
-#if qh_MAXoutside
- maxoutside= facet->maxoutside + 2* qh DISTround;
- /* one DISTround to actual point and another to computed point */
-#endif
- }
- FORALLpoints {
- if (point != qh GOODpointp)
- qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
- }
- FOREACHpoint_(qh other_points) {
- if (point != qh GOODpointp)
- qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
- }
- }
- if (maxdist > qh outside_err) {
- qh_fprintf(qh ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull. The maximum value(qh.outside_err) is %6.2g\n",
- maxdist, qh outside_err );
- qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
- }else if (errfacet1 && qh outside_err > REALmax/2)
- qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
- /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
- trace0((qh ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
- }
-} /* check_points */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkconvex">-</a>
-
- qh_checkconvex( facetlist, fault )
- check that each ridge in facetlist is convex
- fault = qh_DATAfault if reporting errors
- = qh_ALGORITHMfault otherwise
-
- returns:
- counts Zconcaveridges and Zcoplanarridges
- errors if concaveridge or if merging an coplanar ridge
-
- note:
- if not merging,
- tests vertices for neighboring simplicial facets
- else if ZEROcentrum,
- tests vertices for neighboring simplicial facets
- else
- tests centrums of neighboring facets
-
- design:
- for all facets
- report flipped facets
- if ZEROcentrum and simplicial neighbors
- test vertices for neighboring simplicial facets
- else
- test centrum against all neighbors
-*/
-void qh_checkconvex(facetT *facetlist, int fault) {
- facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
- vertexT *vertex;
- realT dist;
- pointT *centrum;
- boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
- int neighbor_i;
-
- trace1((qh ferr, 1026, "qh_checkconvex: check all ridges are convex\n"));
- if (!qh RERUN) {
- zzval_(Zconcaveridges)= 0;
- zzval_(Zcoplanarridges)= 0;
- }
- FORALLfacet_(facetlist) {
- if (facet->flipped) {
- qh_precision("flipped facet");
- qh_fprintf(qh ferr, 6113, "qhull precision error: f%d is flipped(interior point is outside)\n",
- facet->id);
- errfacet1= facet;
- waserror= True;
- continue;
- }
- if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
- allsimplicial= False;
- else {
- allsimplicial= True;
- neighbor_i= 0;
- FOREACHneighbor_(facet) {
- vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
- if (!neighbor->simplicial || neighbor->tricoplanar) {
- allsimplicial= False;
- continue;
- }
- qh_distplane(vertex->point, neighbor, &dist);
- if (dist > -qh DISTround) {
- if (fault == qh_DATAfault) {
- qh_precision("coplanar or concave ridge");
- qh_fprintf(qh ferr, 6114, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
- qh_errexit(qh_ERRsingular, NULL, NULL);
- }
- if (dist > qh DISTround) {
- zzinc_(Zconcaveridges);
- qh_precision("concave ridge");
- qh_fprintf(qh ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above\n",
- facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
- errfacet1= facet;
- errfacet2= neighbor;
- waserror= True;
- }else if (qh ZEROcentrum) {
- if (dist > 0) { /* qh_checkzero checks that dist < - qh DISTround */
- zzinc_(Zcoplanarridges);
- qh_precision("coplanar ridge");
- qh_fprintf(qh ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above\n",
- facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
- errfacet1= facet;
- errfacet2= neighbor;
- waserror= True;
- }
- }else {
- zzinc_(Zcoplanarridges);
- qh_precision("coplanar ridge");
- trace0((qh ferr, 22, "qhull precision error: f%d may be coplanar to f%d, since p%d(v%d) is within %6.4g during p%d\n",
- facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
- }
- }
- }
- }
- if (!allsimplicial) {
- if (qh CENTERtype == qh_AScentrum) {
- if (!facet->center)
- facet->center= qh_getcentrum(facet);
- centrum= facet->center;
- }else {
- if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
- centrum_warning= True;
- qh_fprintf(qh ferr, 7062, "qhull warning: recomputing centrums for convexity test. This may lead to false, precision errors.\n");
- }
- centrum= qh_getcentrum(facet);
- tempcentrum= True;
- }
- FOREACHneighbor_(facet) {
- if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
- continue;
- if (facet->tricoplanar || neighbor->tricoplanar)
- continue;
- zzinc_(Zdistconvex);
- qh_distplane(centrum, neighbor, &dist);
- if (dist > qh DISTround) {
- zzinc_(Zconcaveridges);
- qh_precision("concave ridge");
- qh_fprintf(qh ferr, 6117, "qhull precision error: f%d is concave to f%d. Centrum of f%d is %6.4g above f%d\n",
- facet->id, neighbor->id, facet->id, dist, neighbor->id);
- errfacet1= facet;
- errfacet2= neighbor;
- waserror= True;
- }else if (dist >= 0.0) { /* if arithmetic always rounds the same,
- can test against centrum radius instead */
- zzinc_(Zcoplanarridges);
- qh_precision("coplanar ridge");
- qh_fprintf(qh ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d. Centrum of f%d is %6.4g above f%d\n",
- facet->id, neighbor->id, facet->id, dist, neighbor->id);
- errfacet1= facet;
- errfacet2= neighbor;
- waserror= True;
- }
- }
- if (tempcentrum)
- qh_memfree(centrum, qh normal_size);
- }
- }
- if (waserror && !qh FORCEoutput)
- qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-} /* checkconvex */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkfacet">-</a>
-
- qh_checkfacet( facet, newmerge, waserror )
- checks for consistency errors in facet
- newmerge set if from merge.c
-
- returns:
- sets waserror if any error occurs
-
- checks:
- vertex ids are inverse sorted
- unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
- if non-simplicial, at least as many ridges as neighbors
- neighbors are not duplicated
- ridges are not duplicated
- in 3-d, ridges=verticies
- (qh.hull_dim-1) ridge vertices
- neighbors are reciprocated
- ridge neighbors are facet neighbors and a ridge for every neighbor
- simplicial neighbors match facetintersect
- vertex intersection matches vertices of common ridges
- vertex neighbors and facet vertices agree
- all ridges have distinct vertex sets
-
- notes:
- uses neighbor->seen
-
- design:
- check sets
- check vertices
- check sizes of neighbors and vertices
- check for qh_MERGEridge and qh_DUPLICATEridge flags
- check neighbor set
- check ridge set
- check ridges, neighbors, and vertices
-*/
-void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
- facetT *neighbor, **neighborp, *errother=NULL;
- ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
- vertexT *vertex, **vertexp;
- unsigned previousid= INT_MAX;
- int numneighbors, numvertices, numridges=0, numRvertices=0;
- boolT waserror= False;
- int skipA, skipB, ridge_i, ridge_n, i;
- setT *intersection;
-
- if (facet->visible) {
- qh_fprintf(qh ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
- facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- if (!facet->normal) {
- qh_fprintf(qh ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have a normal\n",
- facet->id);
- waserror= True;
- }
- qh_setcheck(facet->vertices, "vertices for f", facet->id);
- qh_setcheck(facet->ridges, "ridges for f", facet->id);
- qh_setcheck(facet->outsideset, "outsideset for f", facet->id);
- qh_setcheck(facet->coplanarset, "coplanarset for f", facet->id);
- qh_setcheck(facet->neighbors, "neighbors for f", facet->id);
- FOREACHvertex_(facet->vertices) {
- if (vertex->deleted) {
- qh_fprintf(qh ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
- qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
- waserror= True;
- }
- if (vertex->id >= previousid) {
- qh_fprintf(qh ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
- waserror= True;
- break;
- }
- previousid= vertex->id;
- }
- numneighbors= qh_setsize(facet->neighbors);
- numvertices= qh_setsize(facet->vertices);
- numridges= qh_setsize(facet->ridges);
- if (facet->simplicial) {
- if (numvertices+numneighbors != 2*qh hull_dim
- && !facet->degenerate && !facet->redundant) {
- qh_fprintf(qh ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
- facet->id, numvertices, numneighbors);
- qh_setprint(qh ferr, "", facet->neighbors);
- waserror= True;
- }
- }else { /* non-simplicial */
- if (!newmerge
- &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
- && !facet->degenerate && !facet->redundant) {
- qh_fprintf(qh ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
- facet->id, numvertices, numneighbors);
- waserror= True;
- }
- /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
- if (numridges < numneighbors
- ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
- ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
- if (!facet->degenerate && !facet->redundant) {
- qh_fprintf(qh ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
- facet->id, numridges, numneighbors, numvertices);
- waserror= True;
- }
- }
- }
- FOREACHneighbor_(facet) {
- if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
- qh_fprintf(qh ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- neighbor->seen= True;
- }
- FOREACHneighbor_(facet) {
- if (!qh_setin(neighbor->neighbors, facet)) {
- qh_fprintf(qh ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
- facet->id, neighbor->id, neighbor->id, facet->id);
- errother= neighbor;
- waserror= True;
- }
- if (!neighbor->seen) {
- qh_fprintf(qh ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
- facet->id, neighbor->id);
- errother= neighbor;
- waserror= True;
- }
- neighbor->seen= False;
- }
- FOREACHridge_(facet->ridges) {
- qh_setcheck(ridge->vertices, "vertices for r", ridge->id);
- ridge->seen= False;
- }
- FOREACHridge_(facet->ridges) {
- if (ridge->seen) {
- qh_fprintf(qh ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
- facet->id, ridge->id);
- errridge= ridge;
- waserror= True;
- }
- ridge->seen= True;
- numRvertices= qh_setsize(ridge->vertices);
- if (numRvertices != qh hull_dim - 1) {
- qh_fprintf(qh ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
- ridge->top->id, ridge->bottom->id, numRvertices);
- errridge= ridge;
- waserror= True;
- }
- neighbor= otherfacet_(ridge, facet);
- neighbor->seen= True;
- if (!qh_setin(facet->neighbors, neighbor)) {
- qh_fprintf(qh ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
- facet->id, neighbor->id, ridge->id);
- errridge= ridge;
- waserror= True;
- }
- }
- if (!facet->simplicial) {
- FOREACHneighbor_(facet) {
- if (!neighbor->seen) {
- qh_fprintf(qh ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
- facet->id, neighbor->id);
- errother= neighbor;
- waserror= True;
- }
- intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
- qh_settemppush(intersection);
- FOREACHvertex_(facet->vertices) {
- vertex->seen= False;
- vertex->seen2= False;
- }
- FOREACHvertex_(intersection)
- vertex->seen= True;
- FOREACHridge_(facet->ridges) {
- if (neighbor != otherfacet_(ridge, facet))
- continue;
- FOREACHvertex_(ridge->vertices) {
- if (!vertex->seen) {
- qh_fprintf(qh ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
- vertex->id, ridge->id, facet->id, neighbor->id);
- qh_errexit(qh_ERRqhull, facet, ridge);
- }
- vertex->seen2= True;
- }
- }
- if (!newmerge) {
- FOREACHvertex_(intersection) {
- if (!vertex->seen2) {
- if (qh IStracing >=3 || !qh MERGING) {
- qh_fprintf(qh ferr, 6134, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
- not in a ridge. This is ok under merging. Last point was p%d\n",
- vertex->id, facet->id, neighbor->id, qh furthest_id);
- if (!qh FORCEoutput && !qh MERGING) {
- qh_errprint("ERRONEOUS", facet, neighbor, NULL, vertex);
- if (!qh MERGING)
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- }
- }
- }
- }
- qh_settempfree(&intersection);
- }
- }else { /* simplicial */
- FOREACHneighbor_(facet) {
- if (neighbor->simplicial) {
- skipA= SETindex_(facet->neighbors, neighbor);
- skipB= qh_setindex(neighbor->neighbors, facet);
- if (!qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
- qh_fprintf(qh ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
- facet->id, skipA, neighbor->id, skipB);
- errother= neighbor;
- waserror= True;
- }
- }
- }
- }
- if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
- FOREACHridge_i_(facet->ridges) { /* expensive */
- for (i=ridge_i+1; i < ridge_n; i++) {
- ridge2= SETelemt_(facet->ridges, i, ridgeT);
- if (qh_setequal(ridge->vertices, ridge2->vertices)) {
- qh_fprintf(qh ferr, 6227, "Qhull internal error (qh_checkfacet): ridges r%d and r%d have the same vertices\n",
- ridge->id, ridge2->id);
- errridge= ridge;
- waserror= True;
- }
- }
- }
- }
- if (waserror) {
- qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
- *waserrorp= True;
- }
-} /* checkfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkflipped_all">-</a>
-
- qh_checkflipped_all( facetlist )
- checks orientation of facets in list against interior point
-*/
-void qh_checkflipped_all(facetT *facetlist) {
- facetT *facet;
- boolT waserror= False;
- realT dist;
-
- if (facetlist == qh facet_list)
- zzval_(Zflippedfacets)= 0;
- FORALLfacet_(facetlist) {
- if (facet->normal && !qh_checkflipped(facet, &dist, !qh_ALL)) {
- qh_fprintf(qh ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
- facet->id, dist);
- if (!qh FORCEoutput) {
- qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
- waserror= True;
- }
- }
- }
- if (waserror) {
- qh_fprintf(qh ferr, 8101, "\n\
-A flipped facet occurs when its distance to the interior point is\n\
-greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
- qh_errexit(qh_ERRprec, NULL, NULL);
- }
-} /* checkflipped_all */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkpolygon">-</a>
-
- qh_checkpolygon( facetlist )
- checks the correctness of the structure
-
- notes:
- call with either qh.facet_list or qh.newfacet_list
- checks num_facets and num_vertices if qh.facet_list
-
- design:
- for each facet
- checks facet and outside set
- initializes vertexlist
- for each facet
- checks vertex set
- if checking all facets(qh.facetlist)
- check facet count
- if qh.VERTEXneighbors
- check vertex neighbors and count
- check vertex count
-*/
-void qh_checkpolygon(facetT *facetlist) {
- facetT *facet;
- vertexT *vertex, **vertexp, *vertexlist;
- int numfacets= 0, numvertices= 0, numridges= 0;
- int totvneighbors= 0, totvertices= 0;
- boolT waserror= False, nextseen= False, visibleseen= False;
-
- trace1((qh ferr, 1027, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
- if (facetlist != qh facet_list || qh ONLYgood)
- nextseen= True;
- FORALLfacet_(facetlist) {
- if (facet == qh visible_list)
- visibleseen= True;
- if (!facet->visible) {
- if (!nextseen) {
- if (facet == qh facet_next)
- nextseen= True;
- else if (qh_setsize(facet->outsideset)) {
- if (!qh NARROWhull
-#if !qh_COMPUTEfurthest
- || facet->furthestdist >= qh MINoutside
-#endif
- ) {
- qh_fprintf(qh ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
- facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- }
- }
- numfacets++;
- qh_checkfacet(facet, False, &waserror);
- }
- }
- if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
- qh_fprintf(qh ferr, 6138, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
- qh_printlists();
- qh_errexit(qh_ERRqhull, qh visible_list, NULL);
- }
- if (facetlist == qh facet_list)
- vertexlist= qh vertex_list;
- else if (facetlist == qh newfacet_list)
- vertexlist= qh newvertex_list;
- else
- vertexlist= NULL;
- FORALLvertex_(vertexlist) {
- vertex->seen= False;
- vertex->visitid= 0;
- }
- FORALLfacet_(facetlist) {
- if (facet->visible)
- continue;
- if (facet->simplicial)
- numridges += qh hull_dim;
- else
- numridges += qh_setsize(facet->ridges);
- FOREACHvertex_(facet->vertices) {
- vertex->visitid++;
- if (!vertex->seen) {
- vertex->seen= True;
- numvertices++;
- if (qh_pointid(vertex->point) == -1) {
- qh_fprintf(qh ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
- vertex->point, vertex->id, qh first_point);
- waserror= True;
- }
- }
- }
- }
- qh vertex_visit += (unsigned int)numfacets;
- if (facetlist == qh facet_list) {
- if (numfacets != qh num_facets - qh num_visible) {
- qh_fprintf(qh ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
- numfacets, qh num_facets, qh num_visible);
- waserror= True;
- }
- qh vertex_visit++;
- if (qh VERTEXneighbors) {
- FORALLvertices {
- qh_setcheck(vertex->neighbors, "neighbors for v", vertex->id);
- if (vertex->deleted)
- continue;
- totvneighbors += qh_setsize(vertex->neighbors);
- }
- FORALLfacet_(facetlist)
- totvertices += qh_setsize(facet->vertices);
- if (totvneighbors != totvertices) {
- qh_fprintf(qh ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent. Totvneighbors %d, totvertices %d\n",
- totvneighbors, totvertices);
- waserror= True;
- }
- }
- if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
- qh_fprintf(qh ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
- numvertices, qh num_vertices - qh_setsize(qh del_vertices));
- waserror= True;
- }
- if (qh hull_dim == 2 && numvertices != numfacets) {
- qh_fprintf(qh ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
- numvertices, numfacets);
- waserror= True;
- }
- if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
- qh_fprintf(qh ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
- A vertex appears twice in a edge list. May occur during merging.",
- numvertices, numfacets, numridges/2);
- /* occurs if lots of merging and a vertex ends up twice in an edge list. e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
- }
- }
- if (waserror)
- qh_errexit(qh_ERRqhull, NULL, NULL);
-} /* checkpolygon */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="checkvertex">-</a>
-
- qh_checkvertex( vertex )
- check vertex for consistency
- checks vertex->neighbors
-
- notes:
- neighbors checked efficiently in checkpolygon
-*/
-void qh_checkvertex(vertexT *vertex) {
- boolT waserror= False;
- facetT *neighbor, **neighborp, *errfacet=NULL;
-
- if (qh_pointid(vertex->point) == -1) {
- qh_fprintf(qh ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
- waserror= True;
- }
- if (vertex->id >= qh vertex_id) {
- qh_fprintf(qh ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
- waserror= True;
- }
- if (!waserror && !vertex->deleted) {
- if (qh_setsize(vertex->neighbors)) {
- FOREACHneighbor_(vertex) {
- if (!qh_setin(neighbor->vertices, vertex)) {
- qh_fprintf(qh ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
- errfacet= neighbor;
- waserror= True;
- }
- }
- }
- }
- if (waserror) {
- qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
- qh_errexit(qh_ERRqhull, errfacet, NULL);
- }
-} /* checkvertex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="clearcenters">-</a>
-
- qh_clearcenters( type )
- clear old data from facet->center
-
- notes:
- sets new centertype
- nop if CENTERtype is the same
-*/
-void qh_clearcenters(qh_CENTER type) {
- facetT *facet;
-
- if (qh CENTERtype != type) {
- FORALLfacets {
- if (facet->tricoplanar && !facet->keepcentrum)
- facet->center= NULL;
- else if (qh CENTERtype == qh_ASvoronoi){
- if (facet->center) {
- qh_memfree(facet->center, qh center_size);
- facet->center= NULL;
- }
- }else /* qh CENTERtype == qh_AScentrum */ {
- if (facet->center) {
- qh_memfree(facet->center, qh normal_size);
- facet->center= NULL;
- }
- }
- }
- qh CENTERtype= type;
- }
- trace2((qh ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
-} /* clearcenters */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="createsimplex">-</a>
-
- qh_createsimplex( vertices )
- creates a simplex from a set of vertices
-
- returns:
- initializes qh.facet_list to the simplex
- initializes qh.newfacet_list, .facet_tail
- initializes qh.vertex_list, .newvertex_list, .vertex_tail
-
- design:
- initializes lists
- for each vertex
- create a new facet
- for each new facet
- create its neighbor set
-*/
-void qh_createsimplex(setT *vertices) {
- facetT *facet= NULL, *newfacet;
- boolT toporient= True;
- int vertex_i, vertex_n, nth;
- setT *newfacets= qh_settemp(qh hull_dim+1);
- vertexT *vertex;
-
- qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
- qh num_facets= qh num_vertices= qh num_visible= 0;
- qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
- FOREACHvertex_i_(vertices) {
- newfacet= qh_newfacet();
- newfacet->vertices= qh_setnew_delnthsorted(vertices, vertex_n,
- vertex_i, 0);
- newfacet->toporient= (unsigned char)toporient;
- qh_appendfacet(newfacet);
- newfacet->newfacet= True;
- qh_appendvertex(vertex);
- qh_setappend(&newfacets, newfacet);
- toporient ^= True;
- }
- FORALLnew_facets {
- nth= 0;
- FORALLfacet_(qh newfacet_list) {
- if (facet != newfacet)
- SETelem_(newfacet->neighbors, nth++)= facet;
- }
- qh_settruncate(newfacet->neighbors, qh hull_dim);
- }
- qh_settempfree(&newfacets);
- trace1((qh ferr, 1028, "qh_createsimplex: created simplex\n"));
-} /* createsimplex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="delridge">-</a>
-
- qh_delridge( ridge )
- deletes ridge from data structures it belongs to
- frees up its memory
-
- notes:
- in merge.c, caller sets vertex->delridge for each vertex
- ridges also freed in qh_freeqhull
-*/
-void qh_delridge(ridgeT *ridge) {
- void **freelistp; /* used !qh_NOmem */
-
- qh_setdel(ridge->top->ridges, ridge);
- qh_setdel(ridge->bottom->ridges, ridge);
- qh_setfree(&(ridge->vertices));
- qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-} /* delridge */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="delvertex">-</a>
-
- qh_delvertex( vertex )
- deletes a vertex and frees its memory
-
- notes:
- assumes vertex->adjacencies have been updated if needed
- unlinks from vertex_list
-*/
-void qh_delvertex(vertexT *vertex) {
-
- if (vertex == qh tracevertex)
- qh tracevertex= NULL;
- qh_removevertex(vertex);
- qh_setfree(&vertex->neighbors);
- qh_memfree(vertex, (int)sizeof(vertexT));
-} /* delvertex */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="facet3vertex">-</a>
-
- qh_facet3vertex( )
- return temporary set of 3-d vertices in qh_ORIENTclock order
-
- design:
- if simplicial facet
- build set from facet->vertices with facet->toporient
- else
- for each ridge in order
- build set from ridge's vertices
-*/
-setT *qh_facet3vertex(facetT *facet) {
- ridgeT *ridge, *firstridge;
- vertexT *vertex;
- int cntvertices, cntprojected=0;
- setT *vertices;
-
- cntvertices= qh_setsize(facet->vertices);
- vertices= qh_settemp(cntvertices);
- if (facet->simplicial) {
- if (cntvertices != 3) {
- qh_fprintf(qh ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
- cntvertices, facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- qh_setappend(&vertices, SETfirst_(facet->vertices));
- if (facet->toporient ^ qh_ORIENTclock)
- qh_setappend(&vertices, SETsecond_(facet->vertices));
- else
- qh_setaddnth(&vertices, 0, SETsecond_(facet->vertices));
- qh_setappend(&vertices, SETelem_(facet->vertices, 2));
- }else {
- ridge= firstridge= SETfirstt_(facet->ridges, ridgeT); /* no infinite */
- while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
- qh_setappend(&vertices, vertex);
- if (++cntprojected > cntvertices || ridge == firstridge)
- break;
- }
- if (!ridge || cntprojected != cntvertices) {
- qh_fprintf(qh ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up. got at least %d\n",
- facet->id, cntprojected);
- qh_errexit(qh_ERRqhull, facet, ridge);
- }
- }
- return vertices;
-} /* facet3vertex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="findbestfacet">-</a>
-
- qh_findbestfacet( point, bestoutside, bestdist, isoutside )
- find facet that is furthest below a point
-
- for Delaunay triangulations,
- Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
- Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
- returns:
- if bestoutside is set (e.g., qh_ALL)
- returns best facet that is not upperdelaunay
- if Delaunay and inside, point is outside circumsphere of bestfacet
- else
- returns first facet below point
- if point is inside, returns nearest, !upperdelaunay facet
- distance to facet
- isoutside set if outside of facet
-
- notes:
- For tricoplanar facets, this finds one of the tricoplanar facets closest
- to the point. For Delaunay triangulations, the point may be inside a
- different tricoplanar facet. See <a href="../html/qh-code.htm#findfacet">locate a facet with qh_findbestfacet()</a>
-
- If inside, qh_findbestfacet performs an exhaustive search
- this may be too conservative. Sometimes it is clearly required.
-
- qh_findbestfacet is not used by qhull.
- uses qh.visit_id and qh.coplanarset
-
- see:
- <a href="geom.c#findbest">qh_findbest</a>
-*/
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
- realT *bestdist, boolT *isoutside) {
- facetT *bestfacet= NULL;
- int numpart, totpart= 0;
-
- bestfacet= qh_findbest(point, qh facet_list,
- bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
- bestdist, isoutside, &totpart);
- if (*bestdist < -qh DISTround) {
- bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart);
- totpart += numpart;
- if ((isoutside && bestoutside)
- || (!isoutside && bestfacet->upperdelaunay)) {
- bestfacet= qh_findbest(point, bestfacet,
- bestoutside, False, bestoutside,
- bestdist, isoutside, &totpart);
- totpart += numpart;
- }
- }
- trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
- bestfacet->id, *bestdist, *isoutside, totpart));
- return bestfacet;
-} /* findbestfacet */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="findbestlower">-</a>
-
- qh_findbestlower( facet, point, bestdist, numpart )
- returns best non-upper, non-flipped neighbor of facet for point
- if needed, searches vertex neighbors
-
- returns:
- returns bestdist and updates numpart
-
- notes:
- if Delaunay and inside, point is outside of circumsphere of bestfacet
- called by qh_findbest() for points above an upperdelaunay facet
-
-*/
-facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
- facetT *neighbor, **neighborp, *bestfacet= NULL;
- realT bestdist= -REALmax/2 /* avoid underflow */;
- realT dist;
- vertexT *vertex;
-
- zinc_(Zbestlower);
- FOREACHneighbor_(upperfacet) {
- if (neighbor->upperdelaunay || neighbor->flipped)
- continue;
- (*numpart)++;
- qh_distplane(point, neighbor, &dist);
- if (dist > bestdist) {
- bestfacet= neighbor;
- bestdist= dist;
- }
- }
- if (!bestfacet) {
- zinc_(Zbestlowerv);
- /* rarely called, numpart does not count nearvertex computations */
- vertex= qh_nearvertex(upperfacet, point, &dist);
- qh_vertexneighbors();
- FOREACHneighbor_(vertex) {
- if (neighbor->upperdelaunay || neighbor->flipped)
- continue;
- (*numpart)++;
- qh_distplane(point, neighbor, &dist);
- if (dist > bestdist) {
- bestfacet= neighbor;
- bestdist= dist;
- }
- }
- }
- if (!bestfacet) {
- qh_fprintf(qh ferr, 6228, "\n\
-Qhull internal error (qh_findbestlower): all neighbors of facet %d are flipped or upper Delaunay.\n\
-Please report this error to qhull_bug@qhull.org with the input and all of the output.\n",
- upperfacet->id);
- qh_errexit(qh_ERRqhull, upperfacet, NULL);
- }
- *bestdistp= bestdist;
- trace3((qh ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
- bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
- return bestfacet;
-} /* findbestlower */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="findfacet_all">-</a>
-
- qh_findfacet_all( point, bestdist, isoutside, numpart )
- exhaustive search for facet below a point
-
- for Delaunay triangulations,
- Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
- Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
- returns:
- returns first facet below point
- if point is inside,
- returns nearest facet
- distance to facet
- isoutside if point is outside of the hull
- number of distance tests
-
- notes:
- for library users, not used by Qhull
-*/
-facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
- int *numpart) {
- facetT *bestfacet= NULL, *facet;
- realT dist;
- int totpart= 0;
-
- *bestdist= -REALmax;
- *isoutside= False;
- FORALLfacets {
- if (facet->flipped || !facet->normal)
- continue;
- totpart++;
- qh_distplane(point, facet, &dist);
- if (dist > *bestdist) {
- *bestdist= dist;
- bestfacet= facet;
- if (dist > qh MINoutside) {
- *isoutside= True;
- break;
- }
- }
- }
- *numpart= totpart;
- trace3((qh ferr, 3016, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
- getid_(bestfacet), *bestdist, *isoutside, totpart));
- return bestfacet;
-} /* findfacet_all */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="findgood">-</a>
-
- qh_findgood( facetlist, goodhorizon )
- identify good facets for qh.PRINTgood
- if qh.GOODvertex>0
- facet includes point as vertex
- if !match, returns goodhorizon
- inactive if qh.MERGING
- if qh.GOODpoint
- facet is visible or coplanar (>0) or not visible (<0)
- if qh.GOODthreshold
- facet->normal matches threshold
- if !goodhorizon and !match,
- selects facet with closest angle
- sets GOODclosest
-
- returns:
- number of new, good facets found
- determines facet->good
- may update qh.GOODclosest
-
- notes:
- qh_findgood_all further reduces the good region
-
- design:
- count good facets
- mark good facets for qh.GOODpoint
- mark good facets for qh.GOODthreshold
- if necessary
- update qh.GOODclosest
-*/
-int qh_findgood(facetT *facetlist, int goodhorizon) {
- facetT *facet, *bestfacet= NULL;
- realT angle, bestangle= REALmax, dist;
- int numgood=0;
-
- FORALLfacet_(facetlist) {
- if (facet->good)
- numgood++;
- }
- if (qh GOODvertex>0 && !qh MERGING) {
- FORALLfacet_(facetlist) {
- if (!qh_isvertex(qh GOODvertexp, facet->vertices)) {
- facet->good= False;
- numgood--;
- }
- }
- }
- if (qh GOODpoint && numgood) {
- FORALLfacet_(facetlist) {
- if (facet->good && facet->normal) {
- zinc_(Zdistgood);
- qh_distplane(qh GOODpointp, facet, &dist);
- if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
- facet->good= False;
- numgood--;
- }
- }
- }
- }
- if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
- FORALLfacet_(facetlist) {
- if (facet->good && facet->normal) {
- if (!qh_inthresholds(facet->normal, &angle)) {
- facet->good= False;
- numgood--;
- if (angle < bestangle) {
- bestangle= angle;
- bestfacet= facet;
- }
- }
- }
- }
- if (!numgood && (!goodhorizon || qh GOODclosest)) {
- if (qh GOODclosest) {
- if (qh GOODclosest->visible)
- qh GOODclosest= NULL;
- else {
- qh_inthresholds(qh GOODclosest->normal, &angle);
- if (angle < bestangle)
- bestfacet= qh GOODclosest;
- }
- }
- if (bestfacet && bestfacet != qh GOODclosest) {
- if (qh GOODclosest)
- qh GOODclosest->good= False;
- qh GOODclosest= bestfacet;
- bestfacet->good= True;
- numgood++;
- trace2((qh ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
- bestfacet->id, bestangle));
- return numgood;
- }
- }else if (qh GOODclosest) { /* numgood > 0 */
- qh GOODclosest->good= False;
- qh GOODclosest= NULL;
- }
- }
- zadd_(Zgoodfacet, numgood);
- trace2((qh ferr, 2045, "qh_findgood: found %d good facets with %d good horizon\n",
- numgood, goodhorizon));
- if (!numgood && qh GOODvertex>0 && !qh MERGING)
- return goodhorizon;
- return numgood;
-} /* findgood */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="findgood_all">-</a>
-
- qh_findgood_all( facetlist )
- apply other constraints for good facets (used by qh.PRINTgood)
- if qh.GOODvertex
- facet includes (>0) or doesn't include (<0) point as vertex
- if last good facet and ONLYgood, prints warning and continues
- if qh.SPLITthresholds
- facet->normal matches threshold, or if none, the closest one
- calls qh_findgood
- nop if good not used
-
- returns:
- clears facet->good if not good
- sets qh.num_good
-
- notes:
- this is like qh_findgood but more restrictive
-
- design:
- uses qh_findgood to mark good facets
- marks facets for qh.GOODvertex
- marks facets for qh.SPLITthreholds
-*/
-void qh_findgood_all(facetT *facetlist) {
- facetT *facet, *bestfacet=NULL;
- realT angle, bestangle= REALmax;
- int numgood=0, startgood;
-
- if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
- && !qh SPLITthresholds)
- return;
- if (!qh ONLYgood)
- qh_findgood(qh facet_list, 0);
- FORALLfacet_(facetlist) {
- if (facet->good)
- numgood++;
- }
- if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
- FORALLfacet_(facetlist) {
- if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex(qh GOODvertexp, facet->vertices))) {
- if (!--numgood) {
- if (qh ONLYgood) {
- qh_fprintf(qh ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d. Ignored.\n",
- qh_pointid(qh GOODvertexp), facet->id);
- return;
- }else if (qh GOODvertex > 0)
- qh_fprintf(qh ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
- qh GOODvertex-1, qh GOODvertex-1);
- else
- qh_fprintf(qh ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
- -qh GOODvertex - 1, -qh GOODvertex - 1);
- }
- facet->good= False;
- }
- }
- }
- startgood= numgood;
- if (qh SPLITthresholds) {
- FORALLfacet_(facetlist) {
- if (facet->good) {
- if (!qh_inthresholds(facet->normal, &angle)) {
- facet->good= False;
- numgood--;
- if (angle < bestangle) {
- bestangle= angle;
- bestfacet= facet;
- }
- }
- }
- }
- if (!numgood && bestfacet) {
- bestfacet->good= True;
- numgood++;
- trace0((qh ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to thresholds\n",
- bestfacet->id, bestangle));
- return;
- }
- }
- qh num_good= numgood;
- trace0((qh ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
- numgood, startgood));
-} /* findgood_all */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="furthestnext">-</a>
-
- qh_furthestnext()
- set qh.facet_next to facet with furthest of all furthest points
- searches all facets on qh.facet_list
-
- notes:
- this may help avoid precision problems
-*/
-void qh_furthestnext(void /* qh facet_list */) {
- facetT *facet, *bestfacet= NULL;
- realT dist, bestdist= -REALmax;
-
- FORALLfacets {
- if (facet->outsideset) {
-#if qh_COMPUTEfurthest
- pointT *furthest;
- furthest= (pointT*)qh_setlast(facet->outsideset);
- zinc_(Zcomputefurthest);
- qh_distplane(furthest, facet, &dist);
-#else
- dist= facet->furthestdist;
-#endif
- if (dist > bestdist) {
- bestfacet= facet;
- bestdist= dist;
- }
- }
- }
- if (bestfacet) {
- qh_removefacet(bestfacet);
- qh_prependfacet(bestfacet, &qh facet_next);
- trace1((qh ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
- bestfacet->id, bestdist));
- }
-} /* furthestnext */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="furthestout">-</a>
-
- qh_furthestout( facet )
- make furthest outside point the last point of outsideset
-
- returns:
- updates facet->outsideset
- clears facet->notfurthest
- sets facet->furthestdist
-
- design:
- determine best point of outsideset
- make it the last point of outsideset
-*/
-void qh_furthestout(facetT *facet) {
- pointT *point, **pointp, *bestpoint= NULL;
- realT dist, bestdist= -REALmax;
-
- FOREACHpoint_(facet->outsideset) {
- qh_distplane(point, facet, &dist);
- zinc_(Zcomputefurthest);
- if (dist > bestdist) {
- bestpoint= point;
- bestdist= dist;
- }
- }
- if (bestpoint) {
- qh_setdel(facet->outsideset, point);
- qh_setappend(&facet->outsideset, point);
-#if !qh_COMPUTEfurthest
- facet->furthestdist= bestdist;
-#endif
- }
- facet->notfurthest= False;
- trace3((qh ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
- qh_pointid(point), facet->id));
-} /* furthestout */
-
-
-/*-<a href="qh-qhull.htm#TOC"
- >-------------------------------</a><a name="infiniteloop">-</a>
-
- qh_infiniteloop( facet )
- report infinite loop error due to facet
-*/
-void qh_infiniteloop(facetT *facet) {
-
- qh_fprintf(qh ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
- qh_errexit(qh_ERRqhull, facet, NULL);
-} /* qh_infiniteloop */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="initbuild">-</a>
-
- qh_initbuild()
- initialize hull and outside sets with point array
- qh.FIRSTpoint/qh.NUMpoints is point array
- if qh.GOODpoint
- adds qh.GOODpoint to initial hull
-
- returns:
- qh_facetlist with initial hull
- points partioned into outside sets, coplanar sets, or inside
- initializes qh.GOODpointp, qh.GOODvertexp,
-
- design:
- initialize global variables used during qh_buildhull
- determine precision constants and points with max/min coordinate values
- if qh.SCALElast, scale last coordinate(for 'd')
- build initial simplex
- partition input points into facets of initial simplex
- set up lists
- if qh.ONLYgood
- check consistency
- add qh.GOODvertex if defined
-*/
-void qh_initbuild( void) {
- setT *maxpoints, *vertices;
- facetT *facet;
- int i, numpart;
- realT dist;
- boolT isoutside;
-
- qh furthest_id= -1;
- qh lastreport= 0;
- qh facet_id= qh vertex_id= qh ridge_id= 0;
- qh visit_id= qh vertex_visit= 0;
- qh maxoutdone= False;
-
- if (qh GOODpoint > 0)
- qh GOODpointp= qh_point(qh GOODpoint-1);
- else if (qh GOODpoint < 0)
- qh GOODpointp= qh_point(-qh GOODpoint-1);
- if (qh GOODvertex > 0)
- qh GOODvertexp= qh_point(qh GOODvertex-1);
- else if (qh GOODvertex < 0)
- qh GOODvertexp= qh_point(-qh GOODvertex-1);
- if ((qh GOODpoint
- && (qh GOODpointp < qh first_point /* also catches !GOODpointp */
- || qh GOODpointp > qh_point(qh num_points-1)))
- || (qh GOODvertex
- && (qh GOODvertexp < qh first_point /* also catches !GOODvertexp */
- || qh GOODvertexp > qh_point(qh num_points-1)))) {
- qh_fprintf(qh ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
- qh num_points-1);
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
- if (qh SCALElast)
- qh_scalelast(qh first_point, qh num_points, qh hull_dim,
- qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
- qh_detroundoff();
- if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
- && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
- for (i=qh_PRINTEND; i--; ) {
- if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
- && !qh GOODthreshold && !qh SPLITthresholds)
- break; /* in this case, don't set upper_threshold */
- }
- if (i < 0) {
- if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
- qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
- qh GOODthreshold= True;
- }else {
- qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
- if (!qh GOODthreshold)
- qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
- /* qh_initqhull_globals errors if Qg without Pdk/etc. */
- }
- }
- }
- vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
- qh_initialhull(vertices); /* initial qh facet_list */
- qh_partitionall(vertices, qh first_point, qh num_points);
- if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
- if (qh TRACElevel || qh IStracing)
- qh_fprintf(qh ferr, 8103, "\nTrace level %d for %s | %s\n",
- qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
- qh_fprintf(qh ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
- }
- qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
- qh facet_next= qh facet_list;
- qh_furthestnext(/* qh facet_list */);
- if (qh PREmerge) {
- qh cos_max= qh premerge_cos;
- qh centrum_radius= qh premerge_centrum;
- }
- if (qh ONLYgood) {
- if (qh GOODvertex > 0 && qh MERGING) {
- qh_fprintf(qh ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (!(qh GOODthreshold || qh GOODpoint
- || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
- qh_fprintf(qh ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a\n\
-good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (qh GOODvertex > 0 && !qh MERGING /* matches qh_partitionall */
- && !qh_isvertex(qh GOODvertexp, vertices)) {
- facet= qh_findbestnew(qh GOODvertexp, qh facet_list,
- &dist, !qh_ALL, &isoutside, &numpart);
- zadd_(Zdistgood, numpart);
- if (!isoutside) {
- qh_fprintf(qh ferr, 6153, "qhull input error: point for QV%d is inside initial simplex. It can not be made a vertex.\n",
- qh_pointid(qh GOODvertexp));
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- if (!qh_addpoint(qh GOODvertexp, facet, False)) {
- qh_settempfree(&vertices);
- qh_settempfree(&maxpoints);
- return;
- }
- }
- qh_findgood(qh facet_list, 0);
- }
- qh_settempfree(&vertices);
- qh_settempfree(&maxpoints);
- trace1((qh ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
-} /* initbuild */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="initialhull">-</a>
-
- qh_initialhull( vertices )
- constructs the initial hull as a DIM3 simplex of vertices
-
- design:
- creates a simplex (initializes lists)
- determines orientation of simplex
- sets hyperplanes for facets
- doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
- checks for flipped facets and qh.NARROWhull
- checks the result
-*/
-void qh_initialhull(setT *vertices) {
- facetT *facet, *firstfacet, *neighbor, **neighborp;
- realT dist, angle, minangle= REALmax;
-#ifndef qh_NOtrace
- int k;
-#endif
-
- qh_createsimplex(vertices); /* qh facet_list */
- qh_resetlists(False, qh_RESETvisible);
- qh facet_next= qh facet_list; /* advance facet when processed */
- qh interior_point= qh_getcenter(vertices);
- firstfacet= qh facet_list;
- qh_setfacetplane(firstfacet);
- zinc_(Znumvisibility); /* needs to be in printsummary */
- qh_distplane(qh interior_point, firstfacet, &dist);
- if (dist > 0) {
- FORALLfacets
- facet->toporient ^= (unsigned char)True;
- }
- FORALLfacets
- qh_setfacetplane(facet);
- FORALLfacets {
- if (!qh_checkflipped(facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
- trace1((qh ferr, 1031, "qh_initialhull: initial orientation incorrect. Correct all facets\n"));
- facet->flipped= False;
- FORALLfacets {
- facet->toporient ^= (unsigned char)True;
- qh_orientoutside(facet);
- }
- break;
- }
- }
- FORALLfacets {
- if (!qh_checkflipped(facet, NULL, !qh_ALL)) { /* can happen with 'R0.1' */
- if (qh DELAUNAY && ! qh ATinfinity) {
- if (qh UPPERdelaunay)
- qh_fprintf(qh ferr, 6240, "Qhull input error: Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
- else
- qh_fprintf(qh ferr, 6239, "Qhull input error: Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points. Option 'Qz' adds a point \"at infinity\" (above the corresponding paraboloid).\n");
- qh_errexit(qh_ERRinput, NULL, NULL);
- }
- qh_precision("initial facet is coplanar with interior point");
- qh_fprintf(qh ferr, 6154, "qhull precision error: initial facet %d is coplanar with the interior point\n",
- facet->id);
- qh_errexit(qh_ERRsingular, facet, NULL);
- }
- FOREACHneighbor_(facet) {
- angle= qh_getangle(facet->normal, neighbor->normal);
- minimize_( minangle, angle);
- }
- }
- if (minangle < qh_MAXnarrow && !qh NOnarrow) {
- realT diff= 1.0 + minangle;
-
- qh NARROWhull= True;
- qh_option("_narrow-hull", NULL, &diff);
- if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
- qh_printhelp_narrowhull(qh ferr, minangle);
- }
- zzval_(Zprocessed)= qh hull_dim+1;
- qh_checkpolygon(qh facet_list);
- qh_checkconvex(qh facet_list, qh_DATAfault);
-#ifndef qh_NOtrace
- if (qh IStracing >= 1) {
- qh_fprintf(qh ferr, 8105, "qh_initialhull: simplex constructed, interior point:");
- for (k=0; k < qh hull_dim; k++)
- qh_fprintf(qh ferr, 8106, " %6.4g", qh interior_point[k]);
- qh_fprintf(qh ferr, 8107, "\n");
- }
-#endif
-} /* initialhull */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="initialvertices">-</a>
-
- qh_initialvertices( dim, maxpoints, points, numpoints )
- determines a non-singular set of initial vertices
- maxpoints may include duplicate points
-
- returns:
- temporary set of dim+1 vertices in descending order by vertex id
- if qh.RANDOMoutside && !qh.ALLpoints
- picks random points
- if dim >= qh_INITIALmax,
- uses min/max x and max points with non-zero determinants
-
- notes:
- unless qh.ALLpoints,
- uses maxpoints as long as determinate is non-zero
-*/
-setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
- pointT *point, **pointp;
- setT *vertices, *simplex, *tested;
- realT randr;
- int idx, point_i, point_n, k;
- boolT nearzero= False;
-
- vertices= qh_settemp(dim + 1);
- simplex= qh_settemp(dim+1);
- if (qh ALLpoints)
- qh_maxsimplex(dim, NULL, points, numpoints, &simplex);
- else if (qh RANDOMoutside) {
- while (qh_setsize(simplex) != dim+1) {
- randr= qh_RANDOMint;
- randr= randr/(qh_RANDOMmax+1);
- idx= (int)floor(qh num_points * randr);
- while (qh_setin(simplex, qh_point(idx))) {
- idx++; /* in case qh_RANDOMint always returns the same value */
- idx= idx < qh num_points ? idx : 0;
- }
- qh_setappend(&simplex, qh_point(idx));
- }
- }else if (qh hull_dim >= qh_INITIALmax) {
- tested= qh_settemp(dim+1);
- qh_setappend(&simplex, SETfirst_(maxpoints)); /* max and min X coord */
- qh_setappend(&simplex, SETsecond_(maxpoints));
- qh_maxsimplex(fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
- k= qh_setsize(simplex);
- FOREACHpoint_i_(maxpoints) {
- if (point_i & 0x1) { /* first pick up max. coord. points */
- if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
- qh_detsimplex(point, simplex, k, &nearzero);
- if (nearzero)
- qh_setappend(&tested, point);
- else {
- qh_setappend(&simplex, point);
- if (++k == dim) /* use search for last point */
- break;
- }
- }
- }
- }
- while (k != dim && (point= (pointT*)qh_setdellast(maxpoints))) {
- if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
- qh_detsimplex(point, simplex, k, &nearzero);
- if (nearzero)
- qh_setappend(&tested, point);
- else {
- qh_setappend(&simplex, point);
- k++;
- }
- }
- }
- idx= 0;
- while (k != dim && (point= qh_point(idx++))) {
- if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
- qh_detsimplex(point, simplex, k, &nearzero);
- if (!nearzero){
- qh_setappend(&simplex, point);
- k++;
- }
- }
- }
- qh_settempfree(&tested);
- qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
- }else
- qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
- FOREACHpoint_(simplex)
- qh_setaddnth(&vertices, 0, qh_newvertex(point)); /* descending order */
- qh_settempfree(&simplex);
- return vertices;
-} /* initialvertices */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="isvertex">-</a>
-
- qh_isvertex( )
- returns vertex if point is in vertex set, else returns NULL
-
- notes:
- for qh.GOODvertex
-*/
-vertexT *qh_isvertex(pointT *point, setT *vertices) {
- vertexT *vertex, **vertexp;
-
- FOREACHvertex_(vertices) {
- if (vertex->point == point)
- return vertex;
- }
- return NULL;
-} /* isvertex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="makenewfacets">-</a>
-
- qh_makenewfacets( point )
- make new facets from point and qh.visible_list
-
- returns:
- qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
- qh.newvertex_list= list of vertices in new facets with ->newlist set
-
- if (qh.ONLYgood)
- newfacets reference horizon facets, but not vice versa
- ridges reference non-simplicial horizon ridges, but not vice versa
- does not change existing facets
- else
- sets qh.NEWfacets
- new facets attached to horizon facets and ridges
- for visible facets,
- visible->r.replace is corresponding new facet
-
- see also:
- qh_makenewplanes() -- make hyperplanes for facets
- qh_attachnewfacets() -- attachnewfacets if not done here(qh ONLYgood)
- qh_matchnewfacets() -- match up neighbors
- qh_updatevertices() -- update vertex neighbors and delvertices
- qh_deletevisible() -- delete visible facets
- qh_checkpolygon() --check the result
- qh_triangulate() -- triangulate a non-simplicial facet
-
- design:
- for each visible facet
- make new facets to its horizon facets
- update its f.replace
- clear its neighbor set
-*/
-vertexT *qh_makenewfacets(pointT *point /*visible_list*/) {
- facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
- vertexT *apex;
- int numnew=0;
-
- qh newfacet_list= qh facet_tail;
- qh newvertex_list= qh vertex_tail;
- apex= qh_newvertex(point);
- qh_appendvertex(apex);
- qh visit_id++;
- if (!qh ONLYgood)
- qh NEWfacets= True;
- FORALLvisible_facets {
- FOREACHneighbor_(visible)
- neighbor->seen= False;
- if (visible->ridges) {
- visible->visitid= qh visit_id;
- newfacet2= qh_makenew_nonsimplicial(visible, apex, &numnew);
- }
- if (visible->simplicial)
- newfacet= qh_makenew_simplicial(visible, apex, &numnew);
- if (!qh ONLYgood) {
- if (newfacet2) /* newfacet is null if all ridges defined */
- newfacet= newfacet2;
- if (newfacet)
- visible->f.replace= newfacet;
- else
- zinc_(Zinsidevisible);
- SETfirst_(visible->neighbors)= NULL;
- }
- }
- trace1((qh ferr, 1032, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
- numnew, qh_pointid(point)));
- if (qh IStracing >= 4)
- qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
- return apex;
-} /* makenewfacets */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="matchduplicates">-</a>
-
- qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
- match duplicate ridges in qh.hash_table for atfacet/atskip
- duplicates marked with ->dupridge and qh_DUPLICATEridge
-
- returns:
- picks match with worst merge (min distance apart)
- updates hashcount
-
- see also:
- qh_matchneighbor
-
- notes:
-
- design:
- compute hash value for atfacet and atskip
- repeat twice -- once to make best matches, once to match the rest
- for each possible facet in qh.hash_table
- if it is a matching facet and pass 2
- make match
- unless tricoplanar, mark match for merging (qh_MERGEridge)
- [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
- if it is a matching facet and pass 1
- test if this is a better match
- if pass 1,
- make best match (it will not be merged)
-*/
-#ifndef qh_NOmerge
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
- boolT same, ismatch;
- int hash, scan;
- facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
- int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
- realT maxdist= -REALmax, mindist, dist2, low, high;
-
- hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1,
- SETelem_(atfacet->vertices, atskip));
- trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
- atfacet->id, atskip, hash, *hashcount));
- for (makematch= 0; makematch < 2; makematch++) {
- qh visit_id++;
- for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
- zinc_(Zhashlookup);
- nextfacet= NULL;
- newfacet->visitid= qh visit_id;
- for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
- scan= (++scan >= hashsize ? 0 : scan)) {
- if (!facet->dupridge || facet->visitid == qh visit_id)
- continue;
- zinc_(Zhashtests);
- if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
- ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
- if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
- if (!makematch) {
- qh_fprintf(qh ferr, 6155, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
- facet->id, skip, newfacet->id, newskip, hash);
- qh_errexit2 (qh_ERRqhull, facet, newfacet);
- }
- }else if (ismatch && makematch) {
- if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
- SETelem_(facet->neighbors, skip)= newfacet;
- if (newfacet->tricoplanar)
- SETelem_(newfacet->neighbors, newskip)= facet;
- else
- SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
- *hashcount -= 2; /* removed two unmatched facets */
- trace4((qh ferr, 4059, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
- facet->id, skip, newfacet->id, newskip));
- }
- }else if (ismatch) {
- mindist= qh_getdistance(facet, newfacet, &low, &high);
- dist2= qh_getdistance(newfacet, facet, &low, &high);
- minimize_(mindist, dist2);
- if (mindist > maxdist) {
- maxdist= mindist;
- maxmatch= facet;
- maxskip= skip;
- maxmatch2= newfacet;
- maxskip2= newskip;
- }
- trace3((qh ferr, 3018, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
- facet->id, skip, newfacet->id, newskip, mindist,
- maxmatch->id, maxmatch2->id));
- }else { /* !ismatch */
- nextfacet= facet;
- nextskip= skip;
- }
- }
- if (makematch && !facet
- && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
- qh_fprintf(qh ferr, 6156, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
- newfacet->id, newskip, hash);
- qh_errexit(qh_ERRqhull, newfacet, NULL);
- }
- }
- } /* end of for each new facet at hash */
- if (!makematch) {
- if (!maxmatch) {
- qh_fprintf(qh ferr, 6157, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
- atfacet->id, atskip, hash);
- qh_errexit(qh_ERRqhull, atfacet, NULL);
- }
- SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
- SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
- *hashcount -= 2; /* removed two unmatched facets */
- zzinc_(Zmultiridge);
- trace0((qh ferr, 25, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
- maxmatch->id, maxskip, maxmatch2->id, maxskip2));
- qh_precision("ridge with multiple neighbors");
- if (qh IStracing >= 4)
- qh_errprint("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
- }
- }
-} /* matchduplicates */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="nearcoplanar">-</a>
-
- qh_nearcoplanar()
- for all facets, remove near-inside points from facet->coplanarset</li>
- coplanar points defined by innerplane from qh_outerinner()
-
- returns:
- if qh KEEPcoplanar && !qh KEEPinside
- facet->coplanarset only contains coplanar points
- if qh.JOGGLEmax
- drops inner plane by another qh.JOGGLEmax diagonal since a
- vertex could shift out while a coplanar point shifts in
-
- notes:
- used for qh.PREmerge and qh.JOGGLEmax
- must agree with computation of qh.NEARcoplanar in qh_detroundoff()
- design:
- if not keeping coplanar or inside points
- free all coplanar sets
- else if not keeping both coplanar and inside points
- remove !coplanar or !inside points from coplanar sets
-*/
-void qh_nearcoplanar(void /* qh.facet_list */) {
- facetT *facet;
- pointT *point, **pointp;
- int numpart;
- realT dist, innerplane;
-
- if (!qh KEEPcoplanar && !qh KEEPinside) {
- FORALLfacets {
- if (facet->coplanarset)
- qh_setfree( &facet->coplanarset);
- }
- }else if (!qh KEEPcoplanar || !qh KEEPinside) {
- qh_outerinner(NULL, NULL, &innerplane);
- if (qh JOGGLEmax < REALmax/2)
- innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
- numpart= 0;
- FORALLfacets {
- if (facet->coplanarset) {
- FOREACHpoint_(facet->coplanarset) {
- numpart++;
- qh_distplane(point, facet, &dist);
- if (dist < innerplane) {
- if (!qh KEEPinside)
- SETref_(point)= NULL;
- }else if (!qh KEEPcoplanar)
- SETref_(point)= NULL;
- }
- qh_setcompact(facet->coplanarset);
- }
- }
- zzadd_(Zcheckpart, numpart);
- }
-} /* nearcoplanar */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="nearvertex">-</a>
-
- qh_nearvertex( facet, point, bestdist )
- return nearest vertex in facet to point
-
- returns:
- vertex and its distance
-
- notes:
- if qh.DELAUNAY
- distance is measured in the input set
- searches neighboring tricoplanar facets (requires vertexneighbors)
- Slow implementation. Recomputes vertex set for each point.
- The vertex set could be stored in the qh.keepcentrum facet.
-*/
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) {
- realT bestdist= REALmax, dist;
- vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
- coordT *center;
- facetT *neighbor, **neighborp;
- setT *vertices;
- int dim= qh hull_dim;
-
- if (qh DELAUNAY)
- dim--;
- if (facet->tricoplanar) {
- if (!qh VERTEXneighbors || !facet->center) {
- qh_fprintf(qh ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- vertices= qh_settemp(qh TEMPsize);
- apex= SETfirstt_(facet->vertices, vertexT);
- center= facet->center;
- FOREACHneighbor_(apex) {
- if (neighbor->center == center) {
- FOREACHvertex_(neighbor->vertices)
- qh_setappend(&vertices, vertex);
- }
- }
- }else
- vertices= facet->vertices;
- FOREACHvertex_(vertices) {
- dist= qh_pointdist(vertex->point, point, -dim);
- if (dist < bestdist) {
- bestdist= dist;
- bestvertex= vertex;
- }
- }
- if (facet->tricoplanar)
- qh_settempfree(&vertices);
- *bestdistp= sqrt(bestdist);
- trace3((qh ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
- bestvertex->id, *bestdistp, facet->id, qh_pointid(point)));
- return bestvertex;
-} /* nearvertex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="newhashtable">-</a>
-
- qh_newhashtable( newsize )
- returns size of qh.hash_table of at least newsize slots
-
- notes:
- assumes qh.hash_table is NULL
- qh_HASHfactor determines the number of extra slots
- size is not divisible by 2, 3, or 5
-*/
-int qh_newhashtable(int newsize) {
- int size;
-
- size= ((newsize+1)*qh_HASHfactor) | 0x1; /* odd number */
- while (True) {
- if (newsize<0 || size<0) {
- qh_fprintf(qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d). Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
- qh_errexit(qhmem_ERRmem, NULL, NULL);
- }
- if ((size%3) && (size%5))
- break;
- size += 2;
- /* loop terminates because there is an infinite number of primes */
- }
- qh hash_table= qh_setnew(size);
- qh_setzero(qh hash_table, 0, size);
- return size;
-} /* newhashtable */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="newvertex">-</a>
-
- qh_newvertex( point )
- returns a new vertex for point
-*/
-vertexT *qh_newvertex(pointT *point) {
- vertexT *vertex;
-
- zinc_(Ztotvertices);
- vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT));
- memset((char *) vertex, (size_t)0, sizeof(vertexT));
- if (qh vertex_id == 0xFFFFFF) {
- qh_fprintf(qh ferr, 6159, "qhull error: more than %d vertices. ID field overflows and two vertices\n\
-may have the same identifier. Vertices will not be sorted correctly.\n", 0xFFFFFF);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }
- if (qh vertex_id == qh tracevertex_id)
- qh tracevertex= vertex;
- vertex->id= qh vertex_id++;
- vertex->point= point;
- vertex->dim= (unsigned char)(qh hull_dim <= MAX_vdim ? qh hull_dim : 0);
- trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point),
- vertex->id));
- return(vertex);
-} /* newvertex */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="nextridge3d">-</a>
-
- qh_nextridge3d( atridge, facet, vertex )
- return next ridge and vertex for a 3d facet
- returns NULL on error
- [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qh_qh.
-
- notes:
- in qh_ORIENTclock order
- this is a O(n^2) implementation to trace all ridges
- be sure to stop on any 2nd visit
- same as QhullRidge::nextRidge3d
- does not use qh_qh or qh_errexit [QhullFacet.cpp]
-
- design:
- for each ridge
- exit if it is the ridge after atridge
-*/
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
- vertexT *atvertex, *vertex, *othervertex;
- ridgeT *ridge, **ridgep;
-
- if ((atridge->top == facet) ^ qh_ORIENTclock)
- atvertex= SETsecondt_(atridge->vertices, vertexT);
- else
- atvertex= SETfirstt_(atridge->vertices, vertexT);
- FOREACHridge_(facet->ridges) {
- if (ridge == atridge)
- continue;
- if ((ridge->top == facet) ^ qh_ORIENTclock) {
- othervertex= SETsecondt_(ridge->vertices, vertexT);
- vertex= SETfirstt_(ridge->vertices, vertexT);
- }else {
- vertex= SETsecondt_(ridge->vertices, vertexT);
- othervertex= SETfirstt_(ridge->vertices, vertexT);
- }
- if (vertex == atvertex) {
- if (vertexp)
- *vertexp= othervertex;
- return ridge;
- }
- }
- return NULL;
-} /* nextridge3d */
-#else /* qh_NOmerge */
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-}
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-
- return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="outcoplanar">-</a>
-
- qh_outcoplanar()
- move points from all facets' outsidesets to their coplanarsets
-
- notes:
- for post-processing under qh.NARROWhull
-
- design:
- for each facet
- for each outside point for facet
- partition point into coplanar set
-*/
-void qh_outcoplanar(void /* facet_list */) {
- pointT *point, **pointp;
- facetT *facet;
- realT dist;
-
- trace1((qh ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
- FORALLfacets {
- FOREACHpoint_(facet->outsideset) {
- qh num_outside--;
- if (qh KEEPcoplanar || qh KEEPnearinside) {
- qh_distplane(point, facet, &dist);
- zinc_(Zpartition);
- qh_partitioncoplanar(point, facet, &dist);
- }
- }
- qh_setfree(&facet->outsideset);
- }
-} /* outcoplanar */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="point">-</a>
-
- qh_point( id )
- return point for a point id, or NULL if unknown
-
- alternative code:
- return((pointT *)((unsigned long)qh.first_point
- + (unsigned long)((id)*qh.normal_size)));
-*/
-pointT *qh_point(int id) {
-
- if (id < 0)
- return NULL;
- if (id < qh num_points)
- return qh first_point + id * qh hull_dim;
- id -= qh num_points;
- if (id < qh_setsize(qh other_points))
- return SETelemt_(qh other_points, id, pointT);
- return NULL;
-} /* point */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="point_add">-</a>
-
- qh_point_add( set, point, elem )
- stores elem at set[point.id]
-
- returns:
- access function for qh_pointfacet and qh_pointvertex
-
- notes:
- checks point.id
-*/
-void qh_point_add(setT *set, pointT *point, void *elem) {
- int id, size;
-
- SETreturnsize_(set, size);
- if ((id= qh_pointid(point)) < 0)
- qh_fprintf(qh ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
- point, id);
- else if (id >= size) {
- qh_fprintf(qh ferr, 6160, "qhull internal errror(point_add): point p%d is out of bounds(%d)\n",
- id, size);
- qh_errexit(qh_ERRqhull, NULL, NULL);
- }else
- SETelem_(set, id)= elem;
-} /* point_add */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="pointfacet">-</a>
-
- qh_pointfacet()
- return temporary set of facet for each point
- the set is indexed by point id
-
- notes:
- vertices assigned to one of the facets
- coplanarset assigned to the facet
- outside set assigned to the facet
- NULL if no facet for point (inside)
- includes qh.GOODpointp
-
- access:
- FOREACHfacet_i_(facets) { ... }
- SETelem_(facets, i)
-
- design:
- for each facet
- add each vertex
- add each coplanar point
- add each outside point
-*/
-setT *qh_pointfacet(void /*qh facet_list*/) {
- int numpoints= qh num_points + qh_setsize(qh other_points);
- setT *facets;
- facetT *facet;
- vertexT *vertex, **vertexp;
- pointT *point, **pointp;
-
- facets= qh_settemp(numpoints);
- qh_setzero(facets, 0, numpoints);
- qh vertex_visit++;
- FORALLfacets {
- FOREACHvertex_(facet->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- vertex->visitid= qh vertex_visit;
- qh_point_add(facets, vertex->point, facet);
- }
- }
- FOREACHpoint_(facet->coplanarset)
- qh_point_add(facets, point, facet);
- FOREACHpoint_(facet->outsideset)
- qh_point_add(facets, point, facet);
- }
- return facets;
-} /* pointfacet */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="pointvertex">-</a>
-
- qh_pointvertex( )
- return temporary set of vertices indexed by point id
- entry is NULL if no vertex for a point
- this will include qh.GOODpointp
-
- access:
- FOREACHvertex_i_(vertices) { ... }
- SETelem_(vertices, i)
-*/
-setT *qh_pointvertex(void /*qh facet_list*/) {
- int numpoints= qh num_points + qh_setsize(qh other_points);
- setT *vertices;
- vertexT *vertex;
-
- vertices= qh_settemp(numpoints);
- qh_setzero(vertices, 0, numpoints);
- FORALLvertices
- qh_point_add(vertices, vertex->point, vertex);
- return vertices;
-} /* pointvertex */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="prependfacet">-</a>
-
- qh_prependfacet( facet, facetlist )
- prepend facet to the start of a facetlist
-
- returns:
- increments qh.numfacets
- updates facetlist, qh.facet_list, facet_next
-
- notes:
- be careful of prepending since it can lose a pointer.
- e.g., can lose _next by deleting and then prepending before _next
-*/
-void qh_prependfacet(facetT *facet, facetT **facetlist) {
- facetT *prevfacet, *list;
-
-
- trace4((qh ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
- facet->id, getid_(*facetlist)));
- if (!*facetlist)
- (*facetlist)= qh facet_tail;
- list= *facetlist;
- prevfacet= list->previous;
- facet->previous= prevfacet;
- if (prevfacet)
- prevfacet->next= facet;
- list->previous= facet;
- facet->next= *facetlist;
- if (qh facet_list == list) /* this may change *facetlist */
- qh facet_list= facet;
- if (qh facet_next == list)
- qh facet_next= facet;
- *facetlist= facet;
- qh num_facets++;
-} /* prependfacet */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="printhashtable">-</a>
-
- qh_printhashtable( fp )
- print hash table to fp
-
- notes:
- not in I/O to avoid bringing io.c in
-
- design:
- for each hash entry
- if defined
- if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
- print entry and neighbors
-*/
-void qh_printhashtable(FILE *fp) {
- facetT *facet, *neighbor;
- int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
- vertexT *vertex, **vertexp;
-
- FOREACHfacet_i_(qh hash_table) {
- if (facet) {
- FOREACHneighbor_i_(facet) {
- if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
- break;
- }
- if (neighbor_i == neighbor_n)
- continue;
- qh_fprintf(fp, 9283, "hash %d f%d ", facet_i, facet->id);
- FOREACHvertex_(facet->vertices)
- qh_fprintf(fp, 9284, "v%d ", vertex->id);
- qh_fprintf(fp, 9285, "\n neighbors:");
- FOREACHneighbor_i_(facet) {
- if (neighbor == qh_MERGEridge)
- id= -3;
- else if (neighbor == qh_DUPLICATEridge)
- id= -2;
- else
- id= getid_(neighbor);
- qh_fprintf(fp, 9286, " %d", id);
- }
- qh_fprintf(fp, 9287, "\n");
- }
- }
-} /* printhashtable */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="printlists">-</a>
-
- qh_printlists( fp )
- print out facet and vertex list for debugging (without 'f/v' tags)
-*/
-void qh_printlists(void) {
- facetT *facet;
- vertexT *vertex;
- int count= 0;
-
- qh_fprintf(qh ferr, 8108, "qh_printlists: facets:");
- FORALLfacets {
- if (++count % 100 == 0)
- qh_fprintf(qh ferr, 8109, "\n ");
- qh_fprintf(qh ferr, 8110, " %d", facet->id);
- }
- qh_fprintf(qh ferr, 8111, "\n new facets %d visible facets %d next facet for qh_addpoint %d\n vertices(new %d):",
- getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
- getid_(qh newvertex_list));
- count = 0;
- FORALLvertices {
- if (++count % 100 == 0)
- qh_fprintf(qh ferr, 8112, "\n ");
- qh_fprintf(qh ferr, 8113, " %d", vertex->id);
- }
- qh_fprintf(qh ferr, 8114, "\n");
-} /* printlists */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="resetlists">-</a>
-
- qh_resetlists( stats, qh_RESETvisible )
- reset newvertex_list, newfacet_list, visible_list
- if stats,
- maintains statistics
-
- returns:
- visible_list is empty if qh_deletevisible was called
-*/
-void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
- vertexT *vertex;
- facetT *newfacet, *visible;
- int totnew=0, totver=0;
-
- if (stats) {
- FORALLvertex_(qh newvertex_list)
- totver++;
- FORALLnew_facets
- totnew++;
- zadd_(Zvisvertextot, totver);
- zmax_(Zvisvertexmax, totver);
- zadd_(Znewfacettot, totnew);
- zmax_(Znewfacetmax, totnew);
- }
- FORALLvertex_(qh newvertex_list)
- vertex->newlist= False;
- qh newvertex_list= NULL;
- FORALLnew_facets
- newfacet->newfacet= False;
- qh newfacet_list= NULL;
- if (resetVisible) {
- FORALLvisible_facets {
- visible->f.replace= NULL;
- visible->visible= False;
- }
- qh num_visible= 0;
- }
- qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
- qh NEWfacets= False;
-} /* resetlists */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="setvoronoi_all">-</a>
-
- qh_setvoronoi_all()
- compute Voronoi centers for all facets
- includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
-
- returns:
- facet->center is the Voronoi center
-
- notes:
- this is unused/untested code
- please email bradb@shore.net if this works ok for you
-
- use:
- FORALLvertices {...} to locate the vertex for a point.
- FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
-*/
-void qh_setvoronoi_all(void) {
- facetT *facet;
-
- qh_clearcenters(qh_ASvoronoi);
- qh_vertexneighbors();
-
- FORALLfacets {
- if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
- if (!facet->center)
- facet->center= qh_facetcenter(facet->vertices);
- }
- }
-} /* setvoronoi_all */
-
-#ifndef qh_NOmerge
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="triangulate">-</a>
-
- qh_triangulate()
- triangulate non-simplicial facets on qh.facet_list,
- if qh VORONOI, sets Voronoi centers of non-simplicial facets
- nop if hasTriangulation
-
- returns:
- all facets simplicial
- each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
-
- notes:
- call after qh_check_output since may switch to Voronoi centers
- Output may overwrite ->f.triowner with ->f.area
-*/
-void qh_triangulate(void /*qh facet_list*/) {
- facetT *facet, *nextfacet, *owner;
- int onlygood= qh ONLYgood;
- facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
- facetT *orig_neighbor= NULL, *otherfacet;
- vertexT *new_vertex_list= NULL;
- mergeT *merge;
- mergeType mergetype;
- int neighbor_i, neighbor_n;
-
- if (qh hasTriangulation)
- return;
- trace1((qh ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
- if (qh hull_dim == 2)
- return;
- if (qh VORONOI) { /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
- qh_clearcenters(qh_ASvoronoi);
- qh_vertexneighbors();
- }
- qh ONLYgood= False; /* for makenew_nonsimplicial */
- qh visit_id++;
- qh NEWfacets= True;
- qh degen_mergeset= qh_settemp(qh TEMPsize);
- qh newvertex_list= qh vertex_tail;
- for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
- nextfacet= facet->next;
- if (facet->visible || facet->simplicial)
- continue;
- /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
- if (!new_facet_list)
- new_facet_list= facet; /* will be moved to end */
- qh_triangulate_facet(facet, &new_vertex_list);
- }
- trace2((qh ferr, 2047, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
- for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
- nextfacet= facet->next;
- if (facet->visible)
- continue;
- if (facet->ridges) {
- if (qh_setsize(facet->ridges) > 0) {
- qh_fprintf(qh ferr, 6161, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
- qh_errexit(qh_ERRqhull, facet, NULL);
- }
- qh_setfree(&facet->ridges);
- }
- if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
- zinc_(Ztrinull);
- qh_triangulate_null(facet);
- }
- }
- trace2((qh ferr, 2048, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
- qh visible_list= qh facet_tail;
- while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
- facet1= merge->facet1;
- facet2= merge->facet2;
- mergetype= merge->type;
- qh_memfree(merge, (int)sizeof(mergeT));
- if (mergetype == MRGmirror) {
- zinc_(Ztrimirror);
- qh_triangulate_mirror(facet1, facet2);
- }
- }
- qh_settempfree(&qh degen_mergeset);
- trace2((qh ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
- qh newvertex_list= new_vertex_list; /* all vertices of new facets */
- qh visible_list= NULL;
- qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
- qh_resetlists(False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
-
- trace2((qh ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
- trace2((qh ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
- FORALLfacet_(new_facet_list) {
- if (facet->tricoplanar && !facet->visible) {
- FOREACHneighbor_i_(facet) {
- if (neighbor_i == 0) { /* first iteration */
- if (neighbor->tricoplanar)
- orig_neighbor= neighbor->f.triowner;
- else
- orig_neighbor= neighbor;
- }else {
- if (neighbor->tricoplanar)
- otherfacet= neighbor->f.triowner;
- else
- otherfacet= neighbor;
- if (orig_neighbor == otherfacet) {
- zinc_(Ztridegen);
- facet->degenerate= True;
- break;
- }
- }
- }
- }
- }
-
- trace2((qh ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
- owner= NULL;
- visible= NULL;
- for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
- nextfacet= facet->next;
- if (facet->visible) {
- if (facet->tricoplanar) { /* a null or mirrored facet */
- qh_delfacet(facet);
- qh num_visible--;
- }else { /* a non-simplicial facet followed by its tricoplanars */
- if (visible && !owner) {
- /* RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
- trace2((qh ferr, 2053, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
- visible->id));
- qh_delfacet(visible);
- qh num_visible--;
- }
- visible= facet;
- owner= NULL;
- }
- }else if (facet->tricoplanar) {
- if (facet->f.triowner != visible) {
- qh_fprintf(qh ferr, 6162, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
- qh_errexit2 (qh_ERRqhull, facet, visible);
- }
- if (owner)
- facet->f.triowner= owner;
- else if (!facet->degenerate) {
- owner= facet;
- nextfacet= visible->next; /* rescan tricoplanar facets with owner */
- facet->keepcentrum= True; /* one facet owns ->normal, etc. */
- facet->coplanarset= visible->coplanarset;
- facet->outsideset= visible->outsideset;
- visible->coplanarset= NULL;
- visible->outsideset= NULL;
- if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
- visible->center= NULL;
- visible->normal= NULL;
- }
- qh_delfacet(visible);
- qh num_visible--;
- }
- }
- }
- if (visible && !owner) {
- trace2((qh ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
- visible->id));
- qh_delfacet(visible);
- qh num_visible--;
- }
- qh NEWfacets= False;
- qh ONLYgood= onlygood; /* restore value */
- if (qh CHECKfrequently)
- qh_checkpolygon(qh facet_list);
- qh hasTriangulation= True;
-} /* triangulate */
-
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="triangulate_facet">-</a>
-
- qh_triangulate_facet(facetA)
- triangulate a non-simplicial facet
- if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
- returns:
- qh.newfacet_list == simplicial facets
- facet->tricoplanar set and ->keepcentrum false
- facet->degenerate set if duplicated apex
- facet->f.trivisible set to facetA
- facet->center copied from facetA (created if qh_ASvoronoi)
- qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
- facet->normal,offset,maxoutside copied from facetA
-
- notes:
- qh_makenew_nonsimplicial uses neighbor->seen for the same
-
- see also:
- qh_addpoint() -- add a point
- qh_makenewfacets() -- construct a cone of facets for a new vertex
-
- design:
- if qh_ASvoronoi,
- compute Voronoi center (facet->center)
- select first vertex (highest ID to preserve ID ordering of ->vertices)
- triangulate from vertex to ridges
- copy facet->center, normal, offset
- update vertex neighbors
-*/
-void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) {
- facetT *newfacet;
- facetT *neighbor, **neighborp;
- vertexT *apex;
- int numnew=0;
-
- trace3((qh ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
-
- if (qh IStracing >= 4)
- qh_printfacet(qh ferr, facetA);
- FOREACHneighbor_(facetA) {
- neighbor->seen= False;
- neighbor->coplanar= False;
- }
- if (qh CENTERtype == qh_ASvoronoi && !facetA->center /* matches upperdelaunay in qh_setfacetplane() */
- && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
- facetA->center= qh_facetcenter(facetA->vertices);
- }
- qh_willdelete(facetA, NULL);
- qh newfacet_list= qh facet_tail;
- facetA->visitid= qh visit_id;
- apex= SETfirstt_(facetA->vertices, vertexT);
- qh_makenew_nonsimplicial(facetA, apex, &numnew);
- SETfirst_(facetA->neighbors)= NULL;
- FORALLnew_facets {
- newfacet->tricoplanar= True;
- newfacet->f.trivisible= facetA;
- newfacet->degenerate= False;
- newfacet->upperdelaunay= facetA->upperdelaunay;
- newfacet->good= facetA->good;
- if (qh TRInormals) {
- newfacet->keepcentrum= True;
- newfacet->normal= qh_copypoints(facetA->normal, 1, qh hull_dim);
- if (qh CENTERtype == qh_AScentrum)
- newfacet->center= qh_getcentrum(newfacet);
- else
- newfacet->center= qh_copypoints(facetA->center, 1, qh hull_dim);
- }else {
- newfacet->keepcentrum= False;
- newfacet->normal= facetA->normal;
- newfacet->center= facetA->center;
- }
- newfacet->offset= facetA->offset;
-#if qh_MAXoutside
- newfacet->maxoutside= facetA->maxoutside;
-#endif
- }
- qh_matchnewfacets(/*qh newfacet_list*/);
- zinc_(Ztricoplanar);
- zadd_(Ztricoplanartot, numnew);
- zmax_(Ztricoplanarmax, numnew);
- qh visible_list= NULL;
- if (!(*first_vertex))
- (*first_vertex)= qh newvertex_list;
- qh newvertex_list= NULL;
- qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
- qh_resetlists(False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
-} /* triangulate_facet */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="triangulate_link">-</a>
-
- qh_triangulate_link(oldfacetA, facetA, oldfacetB, facetB)
- relink facetA to facetB via oldfacets
- returns:
- adds mirror facets to qh degen_mergeset (4-d and up only)
- design:
- if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
- int errmirror= False;
-
- trace3((qh ferr, 3021, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
- oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
- if (qh_setin(facetA->neighbors, facetB)) {
- if (!qh_setin(facetB->neighbors, facetA))
- errmirror= True;
- else
- qh_appendmergeset(facetA, facetB, MRGmirror, NULL);
- }else if (qh_setin(facetB->neighbors, facetA))
- errmirror= True;
- if (errmirror) {
- qh_fprintf(qh ferr, 6163, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
- facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
- qh_errexit2 (qh_ERRqhull, facetA, facetB);
- }
- qh_setreplace(facetB->neighbors, oldfacetB, facetA);
- qh_setreplace(facetA->neighbors, oldfacetA, facetB);
-} /* triangulate_link */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="triangulate_mirror">-</a>
-
- qh_triangulate_mirror(facetA, facetB)
- delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
- a mirrored facet shares the same vertices of a logical ridge
- design:
- since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
- if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_mirror(facetT *facetA, facetT *facetB) {
- facetT *neighbor, *neighborB;
- int neighbor_i, neighbor_n;
-
- trace3((qh ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
- facetA->id, facetB->id));
- FOREACHneighbor_i_(facetA) {
- neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
- if (neighbor == neighborB)
- continue; /* occurs twice */
- qh_triangulate_link(facetA, neighbor, facetB, neighborB);
- }
- qh_willdelete(facetA, NULL);
- qh_willdelete(facetB, NULL);
-} /* triangulate_mirror */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="triangulate_null">-</a>
-
- qh_triangulate_null(facetA)
- remove null facetA from qh_triangulate_facet()
- a null facet has vertex #1 (apex) == vertex #2
- returns:
- adds facetA to ->visible for deletion after qh_updatevertices
- qh degen_mergeset contains mirror facets (4-d and up only)
- design:
- since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
- if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_null(facetT *facetA) {
- facetT *neighbor, *otherfacet;
-
- trace3((qh ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
- neighbor= SETfirstt_(facetA->neighbors, facetT);
- otherfacet= SETsecondt_(facetA->neighbors, facetT);
- qh_triangulate_link(facetA, neighbor, facetA, otherfacet);
- qh_willdelete(facetA, NULL);
-} /* triangulate_null */
-
-#else /* qh_NOmerge */
-void qh_triangulate(void) {
-}
-#endif /* qh_NOmerge */
-
- /*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="vertexintersect">-</a>
-
- qh_vertexintersect( vertexsetA, vertexsetB )
- intersects two vertex sets (inverse id ordered)
- vertexsetA is a temporary set at the top of qhmem.tempstack
-
- returns:
- replaces vertexsetA with the intersection
-
- notes:
- could overwrite vertexsetA if currently too slow
-*/
-void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
- setT *intersection;
-
- intersection= qh_vertexintersect_new(*vertexsetA, vertexsetB);
- qh_settempfree(vertexsetA);
- *vertexsetA= intersection;
- qh_settemppush(intersection);
-} /* vertexintersect */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="vertexintersect_new">-</a>
-
- qh_vertexintersect_new( )
- intersects two vertex sets (inverse id ordered)
-
- returns:
- a new set
-*/
-setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) {
- setT *intersection= qh_setnew(qh hull_dim - 1);
- vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
- vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
-
- while (*vertexA && *vertexB) {
- if (*vertexA == *vertexB) {
- qh_setappend(&intersection, *vertexA);
- vertexA++; vertexB++;
- }else {
- if ((*vertexA)->id > (*vertexB)->id)
- vertexA++;
- else
- vertexB++;
- }
- }
- return intersection;
-} /* vertexintersect_new */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="vertexneighbors">-</a>
-
- qh_vertexneighbors()
- for each vertex in qh.facet_list,
- determine its neighboring facets
-
- returns:
- sets qh.VERTEXneighbors
- nop if qh.VERTEXneighbors already set
- qh_addpoint() will maintain them
-
- notes:
- assumes all vertex->neighbors are NULL
-
- design:
- for each facet
- for each vertex
- append facet to vertex->neighbors
-*/
-void qh_vertexneighbors(void /*qh facet_list*/) {
- facetT *facet;
- vertexT *vertex, **vertexp;
-
- if (qh VERTEXneighbors)
- return;
- trace1((qh ferr, 1035, "qh_vertexneighbors: determing neighboring facets for each vertex\n"));
- qh vertex_visit++;
- FORALLfacets {
- if (facet->visible)
- continue;
- FOREACHvertex_(facet->vertices) {
- if (vertex->visitid != qh vertex_visit) {
- vertex->visitid= qh vertex_visit;
- vertex->neighbors= qh_setnew(qh hull_dim);
- }
- qh_setappend(&vertex->neighbors, facet);
- }
- }
- qh VERTEXneighbors= True;
-} /* vertexneighbors */
-
-/*-<a href="qh-poly.htm#TOC"
- >-------------------------------</a><a name="vertexsubset">-</a>
-
- qh_vertexsubset( vertexsetA, vertexsetB )
- returns True if vertexsetA is a subset of vertexsetB
- assumes vertexsets are sorted
-
- note:
- empty set is a subset of any other set
-*/
-boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
- vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
- vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
-
- while (True) {
- if (!*vertexA)
- return True;
- if (!*vertexB)
- return False;
- if ((*vertexA)->id > (*vertexB)->id)
- return False;
- if (*vertexA == *vertexB)
- vertexA++;
- vertexB++;
- }
- return False; /* avoid warnings */
-} /* vertexsubset */
diff --git a/PyMca/Object3D/Object3DQhull/src/qhull_a.h b/PyMca/Object3D/Object3DQhull/src/qhull_a.h
deleted file mode 100644
index 27021b2..0000000
--- a/PyMca/Object3D/Object3DQhull/src/qhull_a.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*<html><pre> -<a href="qh-qhull.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- qhull_a.h
- all header files for compiling qhull
-
- see qh-qhull.htm
-
- see libqhull.h for user-level definitions
-
- see user.h for user-defineable constants
-
- defines internal functions for libqhull.c global.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/qhull_a.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
- Notes: grep for ((" and (" to catch fprintf("lkasdjf");
- full parens around (x?y:z)
- use '#include qhull/qhull_a.h' to avoid name clashes
-*/
-
-#ifndef qhDEFqhulla
-#define qhDEFqhulla 1
-
-#include "libqhull.h" /* Defines data types */
-
-#include "stat.h"
-#include "random.h"
-#include "mem.h"
-#include "qset.h"
-#include "geom.h"
-#include "merge.h"
-#include "poly.h"
-#include "io.h"
-
-#include <setjmp.h>
-#include <string.h>
-#include <math.h>
-#include <float.h> /* some compilers will not need float.h */
-#include <limits.h>
-#include <time.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-/*** uncomment here and qset.c
- if string.h does not define memcpy()
-#include <memory.h>
-*/
-
-#if qh_CLOCKtype == 2 /* defined in user.h from libqhull.h */
-#include <sys/types.h>
-#include <sys/times.h>
-#include <unistd.h>
-#endif
-
-#ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4100) /* unreferenced formal parameter */
-#pragma warning( disable : 4127) /* conditional expression is constant */
-#pragma warning( disable : 4706) /* assignment within conditional function */
-#pragma warning( disable : 4996) /* function was declared deprecated(strcpy, localtime, etc.) */
-#endif
-
-/* ======= -macros- =========== */
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="traceN">-</a>
-
- traceN((qh ferr, 0Nnnn, "format\n", vars));
- calls qh_fprintf if qh.IStracing >= N
-
- Add debugging traps to the end of qh_fprintf
-
- notes:
- removing tracing reduces code size but doesn't change execution speed
-*/
-#ifndef qh_NOtrace
-#define trace0(args) {if (qh IStracing) qh_fprintf args;}
-#define trace1(args) {if (qh IStracing >= 1) qh_fprintf args;}
-#define trace2(args) {if (qh IStracing >= 2) qh_fprintf args;}
-#define trace3(args) {if (qh IStracing >= 3) qh_fprintf args;}
-#define trace4(args) {if (qh IStracing >= 4) qh_fprintf args;}
-#define trace5(args) {if (qh IStracing >= 5) qh_fprintf args;}
-#else /* qh_NOtrace */
-#define trace0(args) {}
-#define trace1(args) {}
-#define trace2(args) {}
-#define trace3(args) {}
-#define trace4(args) {}
-#define trace5(args) {}
-#endif /* qh_NOtrace */
-
-/*-<a href="qh-qhull.htm#TOC"
- >--------------------------------</a><a name="QHULL_UNUSED">-</a>
-
-*/
-
-/* See Qt's qglobal.h */
-#if !defined(SAG_COM) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
-# define QHULL_OS_WIN
-#elif defined(__MWERKS__) && defined(__INTEL__)
-# define QHULL_OS_WIN
-#endif
-#if defined(__INTEL_COMPILER) && !defined(QHULL_OS_WIN)
-template <typename T>
-inline void qhullUnused(T &x) { (void)x; }
-# define QHULL_UNUSED(x) qhullUnused(x);
-#else
-# define QHULL_UNUSED(x) (void)x;
-#endif
-
-/***** -libqhull.c prototypes (alphabetical after qhull) ********************/
-
-void qh_qhull(void);
-boolT qh_addpoint(pointT *furthest, facetT *facet, boolT checkdist);
-void qh_buildhull(void);
-void qh_buildtracing(pointT *furthest, facetT *facet);
-void qh_build_withrestart(void);
-void qh_errexit2(int exitcode, facetT *facet, facetT *otherfacet);
-void qh_findhorizon(pointT *point, facetT *facet, int *goodvisible,int *goodhorizon);
-pointT *qh_nextfurthest(facetT **visible);
-void qh_partitionall(setT *vertices, pointT *points,int npoints);
-void qh_partitioncoplanar(pointT *point, facetT *facet, realT *dist);
-void qh_partitionpoint(pointT *point, facetT *facet);
-void qh_partitionvisible(boolT allpoints, int *numpoints);
-void qh_precision(const char *reason);
-void qh_printsummary(FILE *fp);
-
-/***** -global.c internal prototypes (alphabetical) ***********************/
-
-void qh_appendprint(qh_PRINT format);
-void qh_freebuild(boolT allmem);
-void qh_freebuffers(void);
-void qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-
-/***** -stat.c internal prototypes (alphabetical) ***********************/
-
-void qh_allstatA(void);
-void qh_allstatB(void);
-void qh_allstatC(void);
-void qh_allstatD(void);
-void qh_allstatE(void);
-void qh_allstatE2 (void);
-void qh_allstatF(void);
-void qh_allstatG(void);
-void qh_allstatH(void);
-void qh_freebuffers(void);
-void qh_initbuffers(coordT *points, int numpoints, int dim, boolT ismalloc);
-
-#endif /* qhDEFqhulla */
diff --git a/PyMca/Object3D/Object3DQhull/src/qset.c b/PyMca/Object3D/Object3DQhull/src/qset.c
deleted file mode 100644
index 8da46fb..0000000
--- a/PyMca/Object3D/Object3DQhull/src/qset.c
+++ /dev/null
@@ -1,1339 +0,0 @@
-/*<html><pre> -<a href="qh-set.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- qset.c
- implements set manipulations needed for quickhull
-
- see qh-set.htm and qset.h
-
- Be careful of strict aliasing (two pointers of different types
- that reference the same location). The last slot of a set is
- either the actual size of the set plus 1, or the NULL terminator
- of the set (i.e., setelemT).
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/qset.c#6 $$Change: 1475 $
- $DateTime: 2012/01/27 22:32:16 $$Author: bbarber $
-*/
-
-#include "qset.h"
-#include "mem.h"
-#include <stdio.h>
-#include <string.h>
-/*** uncomment here and qhull_a.h
- if string.h does not define memcpy()
-#include <memory.h>
-*/
-
-#ifndef qhDEFlibqhull
-typedef struct ridgeT ridgeT;
-typedef struct facetT facetT;
-void qh_errexit(int exitcode, facetT *, ridgeT *);
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... );
-# ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
-# pragma warning( disable : 4127) /* conditional expression is constant */
-# pragma warning( disable : 4706) /* assignment within conditional function */
-# endif
-#endif
-
-/*=============== internal macros ===========================*/
-
-/*============ functions in alphabetical order ===================*/
-
-/*-<a href="qh-set.htm#TOC"
- >--------------------------------<a name="setaddnth">-</a>
-
- qh_setaddnth( setp, nth, newelem)
- adds newelem as n'th element of sorted or unsorted *setp
-
- notes:
- *setp and newelem must be defined
- *setp may be a temp set
- nth=0 is first element
- errors if nth is out of bounds
-
- design:
- expand *setp if empty or full
- move tail of *setp up one
- insert newelem
-*/
-void qh_setaddnth(setT **setp, int nth, void *newelem) {
- int oldsize, i;
- setelemT *sizep; /* avoid strict aliasing */
- setelemT *oldp, *newp;
-
- if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
- qh_setlarger(setp);
- sizep= SETsizeaddr_(*setp);
- }
- oldsize= sizep->i - 1;
- if (nth < 0 || nth > oldsize) {
- qh_fprintf(qhmem.ferr, 6171, "qhull internal error (qh_setaddnth): nth %d is out-of-bounds for set:\n", nth);
- qh_setprint(qhmem.ferr, "", *setp);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- sizep->i++;
- oldp= (setelemT *)SETelemaddr_(*setp, oldsize, void); /* NULL */
- newp= oldp+1;
- for (i=oldsize-nth+1; i--; ) /* move at least NULL */
- (newp--)->p= (oldp--)->p; /* may overwrite *sizep */
- newp->p= newelem;
-} /* setaddnth */
-
-
-/*-<a href="qh-set.htm#TOC"
- >--------------------------------<a name="setaddsorted">-</a>
-
- setaddsorted( setp, newelem )
- adds an newelem into sorted *setp
-
- notes:
- *setp and newelem must be defined
- *setp may be a temp set
- nop if newelem already in set
-
- design:
- find newelem's position in *setp
- insert newelem
-*/
-void qh_setaddsorted(setT **setp, void *newelem) {
- int newindex=0;
- void *elem, **elemp;
-
- FOREACHelem_(*setp) { /* could use binary search instead */
- if (elem < newelem)
- newindex++;
- else if (elem == newelem)
- return;
- else
- break;
- }
- qh_setaddnth(setp, newindex, newelem);
-} /* setaddsorted */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setappend">-</a>
-
- qh_setappend( setp, newelem)
- append newelem to *setp
-
- notes:
- *setp may be a temp set
- *setp and newelem may be NULL
-
- design:
- expand *setp if empty or full
- append newelem to *setp
-
-*/
-void qh_setappend(setT **setp, void *newelem) {
- setelemT *sizep; /* Avoid strict aliasing. Writing to *endp may overwrite *sizep */
- setelemT *endp;
- int count;
-
- if (!newelem)
- return;
- if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
- qh_setlarger(setp);
- sizep= SETsizeaddr_(*setp);
- }
- count= (sizep->i)++ - 1;
- endp= (setelemT *)SETelemaddr_(*setp, count, void);
- (endp++)->p= newelem;
- endp->p= NULL;
-} /* setappend */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setappend_set">-</a>
-
- qh_setappend_set( setp, setA)
- appends setA to *setp
-
- notes:
- *setp can not be a temp set
- *setp and setA may be NULL
-
- design:
- setup for copy
- expand *setp if it is too small
- append all elements of setA to *setp
-*/
-void qh_setappend_set(setT **setp, setT *setA) {
- int sizeA, size;
- setT *oldset;
- setelemT *sizep;
-
- if (!setA)
- return;
- SETreturnsize_(setA, sizeA);
- if (!*setp)
- *setp= qh_setnew(sizeA);
- sizep= SETsizeaddr_(*setp);
- if (!(size= sizep->i))
- size= (*setp)->maxsize;
- else
- size--;
- if (size + sizeA > (*setp)->maxsize) {
- oldset= *setp;
- *setp= qh_setcopy(oldset, sizeA);
- qh_setfree(&oldset);
- sizep= SETsizeaddr_(*setp);
- }
- if (sizeA > 0) {
- sizep->i= size+sizeA+1; /* memcpy may overwrite */
- memcpy((char *)&((*setp)->e[size].p), (char *)&(setA->e[0].p), (size_t)(sizeA+1) * SETelemsize);
- }
-} /* setappend_set */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setappend2ndlast">-</a>
-
- qh_setappend2ndlast( setp, newelem )
- makes newelem the next to the last element in *setp
-
- notes:
- *setp must have at least one element
- newelem must be defined
- *setp may be a temp set
-
- design:
- expand *setp if empty or full
- move last element of *setp up one
- insert newelem
-*/
-void qh_setappend2ndlast(setT **setp, void *newelem) {
- setelemT *sizep; /* Avoid strict aliasing. Writing to *endp may overwrite *sizep */
- setelemT *endp, *lastp;
- int count;
-
- if (!*setp || (sizep= SETsizeaddr_(*setp))->i==0) {
- qh_setlarger(setp);
- sizep= SETsizeaddr_(*setp);
- }
- count= (sizep->i)++ - 1;
- endp= (setelemT *)SETelemaddr_(*setp, count, void); /* NULL */
- lastp= endp-1;
- *(endp++)= *lastp;
- endp->p= NULL; /* may overwrite *sizep */
- lastp->p= newelem;
-} /* setappend2ndlast */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setcheck">-</a>
-
- qh_setcheck( set, typename, id )
- check set for validity
- report errors with typename and id
-
- design:
- checks that maxsize, actual size, and NULL terminator agree
-*/
-void qh_setcheck(setT *set, const char *tname, unsigned id) {
- int maxsize, size;
- int waserr= 0;
-
- if (!set)
- return;
- SETreturnsize_(set, size);
- maxsize= set->maxsize;
- if (size > maxsize || !maxsize) {
- qh_fprintf(qhmem.ferr, 6172, "qhull internal error (qh_setcheck): actual size %d of %s%d is greater than max size %d\n",
- size, tname, id, maxsize);
- waserr= 1;
- }else if (set->e[size].p) {
- qh_fprintf(qhmem.ferr, 6173, "qhull internal error (qh_setcheck): %s%d(size %d max %d) is not null terminated.\n",
- tname, id, size-1, maxsize);
- waserr= 1;
- }
- if (waserr) {
- qh_setprint(qhmem.ferr, "ERRONEOUS", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
-} /* setcheck */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setcompact">-</a>
-
- qh_setcompact( set )
- remove internal NULLs from an unsorted set
-
- returns:
- updated set
-
- notes:
- set may be NULL
- it would be faster to swap tail of set into holes, like qh_setdel
-
- design:
- setup pointers into set
- skip NULLs while copying elements to start of set
- update the actual size
-*/
-void qh_setcompact(setT *set) {
- int size;
- void **destp, **elemp, **endp, **firstp;
-
- if (!set)
- return;
- SETreturnsize_(set, size);
- destp= elemp= firstp= SETaddr_(set, void);
- endp= destp + size;
- while (1) {
- if (!(*destp++ = *elemp++)) {
- destp--;
- if (elemp > endp)
- break;
- }
- }
- qh_settruncate(set, (int)(destp-firstp)); /* WARN64 */
-} /* setcompact */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setcopy">-</a>
-
- qh_setcopy( set, extra )
- make a copy of a sorted or unsorted set with extra slots
-
- returns:
- new set
-
- design:
- create a newset with extra slots
- copy the elements to the newset
-
-*/
-setT *qh_setcopy(setT *set, int extra) {
- setT *newset;
- int size;
-
- if (extra < 0)
- extra= 0;
- SETreturnsize_(set, size);
- newset= qh_setnew(size+extra);
- SETsizeaddr_(newset)->i= size+1; /* memcpy may overwrite */
- memcpy((char *)&(newset->e[0].p), (char *)&(set->e[0].p), (size_t)(size+1) * SETelemsize);
- return(newset);
-} /* setcopy */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setdel">-</a>
-
- qh_setdel( set, oldelem )
- delete oldelem from an unsorted set
-
- returns:
- returns oldelem if found
- returns NULL otherwise
-
- notes:
- set may be NULL
- oldelem must not be NULL;
- only deletes one copy of oldelem in set
-
- design:
- locate oldelem
- update actual size if it was full
- move the last element to the oldelem's location
-*/
-void *qh_setdel(setT *set, void *oldelem) {
- setelemT *sizep;
- setelemT *elemp;
- setelemT *lastp;
-
- if (!set)
- return NULL;
- elemp= (setelemT *)SETaddr_(set, void);
- while (elemp->p != oldelem && elemp->p)
- elemp++;
- if (elemp->p) {
- sizep= SETsizeaddr_(set);
- if (!(sizep->i)--) /* if was a full set */
- sizep->i= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
- lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
- elemp->p= lastp->p; /* may overwrite itself */
- lastp->p= NULL;
- return oldelem;
- }
- return NULL;
-} /* setdel */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setdellast">-</a>
-
- qh_setdellast( set)
- return last element of set or NULL
-
- notes:
- deletes element from set
- set may be NULL
-
- design:
- return NULL if empty
- if full set
- delete last element and set actual size
- else
- delete last element and update actual size
-*/
-void *qh_setdellast(setT *set) {
- int setsize; /* actually, actual_size + 1 */
- int maxsize;
- setelemT *sizep;
- void *returnvalue;
-
- if (!set || !(set->e[0].p))
- return NULL;
- sizep= SETsizeaddr_(set);
- if ((setsize= sizep->i)) {
- returnvalue= set->e[setsize - 2].p;
- set->e[setsize - 2].p= NULL;
- sizep->i--;
- }else {
- maxsize= set->maxsize;
- returnvalue= set->e[maxsize - 1].p;
- set->e[maxsize - 1].p= NULL;
- sizep->i= maxsize;
- }
- return returnvalue;
-} /* setdellast */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setdelnth">-</a>
-
- qh_setdelnth( set, nth )
- deletes nth element from unsorted set
- 0 is first element
-
- returns:
- returns the element (needs type conversion)
-
- notes:
- errors if nth invalid
-
- design:
- setup points and check nth
- delete nth element and overwrite with last element
-*/
-void *qh_setdelnth(setT *set, int nth) {
- void *elem;
- setelemT *sizep;
- setelemT *elemp, *lastp;
-
- elemp= (setelemT *)SETelemaddr_(set, nth, void);
- sizep= SETsizeaddr_(set);
- if ((sizep->i--)==0) /* if was a full set */
- sizep->i= set->maxsize; /* *sizep= (maxsize-1)+ 1 */
- if (nth < 0 || nth >= sizep->i) {
- qh_fprintf(qhmem.ferr, 6174, "qhull internal error (qh_setdelnth): nth %d is out-of-bounds for set:\n", nth);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- lastp= (setelemT *)SETelemaddr_(set, sizep->i-1, void);
- elem= elemp->p;
- elemp->p= lastp->p; /* may overwrite itself */
- lastp->p= NULL;
- return elem;
-} /* setdelnth */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setdelnthsorted">-</a>
-
- qh_setdelnthsorted( set, nth )
- deletes nth element from sorted set
-
- returns:
- returns the element (use type conversion)
-
- notes:
- errors if nth invalid
-
- see also:
- setnew_delnthsorted
-
- design:
- setup points and check nth
- copy remaining elements down one
- update actual size
-*/
-void *qh_setdelnthsorted(setT *set, int nth) {
- void *elem;
- setelemT *sizep;
- setelemT *newp, *oldp;
-
- sizep= SETsizeaddr_(set);
- if (nth < 0 || (sizep->i && nth >= sizep->i-1) || nth >= set->maxsize) {
- qh_fprintf(qhmem.ferr, 6175, "qhull internal error (qh_setdelnthsorted): nth %d is out-of-bounds for set:\n", nth);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- newp= (setelemT *)SETelemaddr_(set, nth, void);
- elem= newp->p;
- oldp= newp+1;
- while (((newp++)->p= (oldp++)->p))
- ; /* copy remaining elements and NULL */
- if ((sizep->i--)==0) /* if was a full set */
- sizep->i= set->maxsize; /* *sizep= (max size-1)+ 1 */
- return elem;
-} /* setdelnthsorted */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setdelsorted">-</a>
-
- qh_setdelsorted( set, oldelem )
- deletes oldelem from sorted set
-
- returns:
- returns oldelem if it was deleted
-
- notes:
- set may be NULL
-
- design:
- locate oldelem in set
- copy remaining elements down one
- update actual size
-*/
-void *qh_setdelsorted(setT *set, void *oldelem) {
- setelemT *sizep;
- setelemT *newp, *oldp;
-
- if (!set)
- return NULL;
- newp= (setelemT *)SETaddr_(set, void);
- while(newp->p != oldelem && newp->p)
- newp++;
- if (newp->p) {
- oldp= newp+1;
- while (((newp++)->p= (oldp++)->p))
- ; /* copy remaining elements */
- sizep= SETsizeaddr_(set);
- if ((sizep->i--)==0) /* if was a full set */
- sizep->i= set->maxsize; /* *sizep= (max size-1)+ 1 */
- return oldelem;
- }
- return NULL;
-} /* setdelsorted */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setduplicate">-</a>
-
- qh_setduplicate( set, elemsize )
- duplicate a set of elemsize elements
-
- notes:
- use setcopy if retaining old elements
-
- design:
- create a new set
- for each elem of the old set
- create a newelem
- append newelem to newset
-*/
-setT *qh_setduplicate(setT *set, int elemsize) {
- void *elem, **elemp, *newElem;
- setT *newSet;
- int size;
-
- if (!(size= qh_setsize(set)))
- return NULL;
- newSet= qh_setnew(size);
- FOREACHelem_(set) {
- newElem= qh_memalloc(elemsize);
- memcpy(newElem, elem, (size_t)elemsize);
- qh_setappend(&newSet, newElem);
- }
- return newSet;
-} /* setduplicate */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setendpointer">-</a>
-
- qh_setendpointer( set )
- Returns pointer to NULL terminator of a set's elements
- set can not be NULL
-
-*/
-void **qh_setendpointer(setT *set) {
-
- setelemT *sizep= SETsizeaddr_(set);
- int n= sizep->i;
- return (n ? &set->e[n-1].p : &sizep->p);
-} /* qh_setendpointer */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setequal">-</a>
-
- qh_setequal( )
- returns 1 if two sorted sets are equal, otherwise returns 0
-
- notes:
- either set may be NULL
-
- design:
- check size of each set
- setup pointers
- compare elements of each set
-*/
-int qh_setequal(setT *setA, setT *setB) {
- void **elemAp, **elemBp;
- int sizeA= 0, sizeB= 0;
-
- if (setA) {
- SETreturnsize_(setA, sizeA);
- }
- if (setB) {
- SETreturnsize_(setB, sizeB);
- }
- if (sizeA != sizeB)
- return 0;
- if (!sizeA)
- return 1;
- elemAp= SETaddr_(setA, void);
- elemBp= SETaddr_(setB, void);
- if (!memcmp((char *)elemAp, (char *)elemBp, sizeA*SETelemsize))
- return 1;
- return 0;
-} /* setequal */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setequal_except">-</a>
-
- qh_setequal_except( setA, skipelemA, setB, skipelemB )
- returns 1 if sorted setA and setB are equal except for skipelemA & B
-
- returns:
- false if either skipelemA or skipelemB are missing
-
- notes:
- neither set may be NULL
-
- if skipelemB is NULL,
- can skip any one element of setB
-
- design:
- setup pointers
- search for skipelemA, skipelemB, and mismatches
- check results
-*/
-int qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB) {
- void **elemA, **elemB;
- int skip=0;
-
- elemA= SETaddr_(setA, void);
- elemB= SETaddr_(setB, void);
- while (1) {
- if (*elemA == skipelemA) {
- skip++;
- elemA++;
- }
- if (skipelemB) {
- if (*elemB == skipelemB) {
- skip++;
- elemB++;
- }
- }else if (*elemA != *elemB) {
- skip++;
- if (!(skipelemB= *elemB++))
- return 0;
- }
- if (!*elemA)
- break;
- if (*elemA++ != *elemB++)
- return 0;
- }
- if (skip != 2 || *elemB)
- return 0;
- return 1;
-} /* setequal_except */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setequal_skip">-</a>
-
- qh_setequal_skip( setA, skipA, setB, skipB )
- returns 1 if sorted setA and setB are equal except for elements skipA & B
-
- returns:
- false if different size
-
- notes:
- neither set may be NULL
-
- design:
- setup pointers
- search for mismatches while skipping skipA and skipB
-*/
-int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB) {
- void **elemA, **elemB, **skipAp, **skipBp;
-
- elemA= SETaddr_(setA, void);
- elemB= SETaddr_(setB, void);
- skipAp= SETelemaddr_(setA, skipA, void);
- skipBp= SETelemaddr_(setB, skipB, void);
- while (1) {
- if (elemA == skipAp)
- elemA++;
- if (elemB == skipBp)
- elemB++;
- if (!*elemA)
- break;
- if (*elemA++ != *elemB++)
- return 0;
- }
- if (*elemB)
- return 0;
- return 1;
-} /* setequal_skip */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setfree">-</a>
-
- qh_setfree( setp )
- frees the space occupied by a sorted or unsorted set
-
- returns:
- sets setp to NULL
-
- notes:
- set may be NULL
-
- design:
- free array
- free set
-*/
-void qh_setfree(setT **setp) {
- int size;
- void **freelistp; /* used !qh_NOmem */
-
- if (*setp) {
- size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
- if (size <= qhmem.LASTsize) {
- qh_memfree_(*setp, size, freelistp);
- }else
- qh_memfree(*setp, size);
- *setp= NULL;
- }
-} /* setfree */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setfree2">-</a>
-
- qh_setfree2( setp, elemsize )
- frees the space occupied by a set and its elements
-
- notes:
- set may be NULL
-
- design:
- free each element
- free set
-*/
-void qh_setfree2 (setT **setp, int elemsize) {
- void *elem, **elemp;
-
- FOREACHelem_(*setp)
- qh_memfree(elem, elemsize);
- qh_setfree(setp);
-} /* setfree2 */
-
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setfreelong">-</a>
-
- qh_setfreelong( setp )
- frees a set only if it's in long memory
-
- returns:
- sets setp to NULL if it is freed
-
- notes:
- set may be NULL
-
- design:
- if set is large
- free it
-*/
-void qh_setfreelong(setT **setp) {
- int size;
-
- if (*setp) {
- size= sizeof(setT) + ((*setp)->maxsize)*SETelemsize;
- if (size > qhmem.LASTsize) {
- qh_memfree(*setp, size);
- *setp= NULL;
- }
- }
-} /* setfreelong */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setin">-</a>
-
- qh_setin( set, setelem )
- returns 1 if setelem is in a set, 0 otherwise
-
- notes:
- set may be NULL or unsorted
-
- design:
- scans set for setelem
-*/
-int qh_setin(setT *set, void *setelem) {
- void *elem, **elemp;
-
- FOREACHelem_(set) {
- if (elem == setelem)
- return 1;
- }
- return 0;
-} /* setin */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setindex">-</a>
-
- qh_setindex( set, atelem )
- returns the index of atelem in set.
- returns -1, if not in set or maxsize wrong
-
- notes:
- set may be NULL and may contain nulls.
- NOerrors returned (qh_pointid, QhullPoint::id)
-
- design:
- checks maxsize
- scans set for atelem
-*/
-int qh_setindex(setT *set, void *atelem) {
- void **elem;
- int size, i;
-
- if (!set)
- return -1;
- SETreturnsize_(set, size);
- if (size > set->maxsize)
- return -1;
- elem= SETaddr_(set, void);
- for (i=0; i < size; i++) {
- if (*elem++ == atelem)
- return i;
- }
- return -1;
-} /* setindex */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setlarger">-</a>
-
- qh_setlarger( oldsetp )
- returns a larger set that contains all elements of *oldsetp
-
- notes:
- the set is at least twice as large
- if temp set, updates qhmem.tempstack
-
- design:
- creates a new set
- copies the old set to the new set
- updates pointers in tempstack
- deletes the old set
-*/
-void qh_setlarger(setT **oldsetp) {
- int size= 1;
- setT *newset, *set, **setp, *oldset;
- setelemT *sizep;
- setelemT *newp, *oldp;
-
- if (*oldsetp) {
- oldset= *oldsetp;
- SETreturnsize_(oldset, size);
- qhmem.cntlarger++;
- qhmem.totlarger += size+1;
- newset= qh_setnew(2 * size);
- oldp= (setelemT *)SETaddr_(oldset, void);
- newp= (setelemT *)SETaddr_(newset, void);
- memcpy((char *)newp, (char *)oldp, (size_t)(size+1) * SETelemsize);
- sizep= SETsizeaddr_(newset);
- sizep->i= size+1;
- FOREACHset_((setT *)qhmem.tempstack) {
- if (set == oldset)
- *(setp-1)= newset;
- }
- qh_setfree(oldsetp);
- }else
- newset= qh_setnew(3);
- *oldsetp= newset;
-} /* setlarger */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setlast">-</a>
-
- qh_setlast( )
- return last element of set or NULL (use type conversion)
-
- notes:
- set may be NULL
-
- design:
- return last element
-*/
-void *qh_setlast(setT *set) {
- int size;
-
- if (set) {
- size= SETsizeaddr_(set)->i;
- if (!size)
- return SETelem_(set, set->maxsize - 1);
- else if (size > 1)
- return SETelem_(set, size - 2);
- }
- return NULL;
-} /* setlast */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setnew">-</a>
-
- qh_setnew( setsize )
- creates and allocates space for a set
-
- notes:
- setsize means the number of elements (!including the NULL terminator)
- use qh_settemp/qh_setfreetemp if set is temporary
-
- design:
- allocate memory for set
- roundup memory if small set
- initialize as empty set
-*/
-setT *qh_setnew(int setsize) {
- setT *set;
- int sizereceived; /* used !qh_NOmem */
- int size;
- void **freelistp; /* used !qh_NOmem */
-
- if (!setsize)
- setsize++;
- size= sizeof(setT) + setsize * SETelemsize;
- if (size>0 && size <= qhmem.LASTsize) {
- qh_memalloc_(size, freelistp, set, setT);
-#ifndef qh_NOmem
- sizereceived= qhmem.sizetable[ qhmem.indextable[size]];
- if (sizereceived > size)
- setsize += (sizereceived - size)/SETelemsize;
-#endif
- }else
- set= (setT*)qh_memalloc(size);
- set->maxsize= setsize;
- set->e[setsize].i= 1;
- set->e[0].p= NULL;
- return(set);
-} /* setnew */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setnew_delnthsorted">-</a>
-
- qh_setnew_delnthsorted( set, size, nth, prepend )
- creates a sorted set not containing nth element
- if prepend, the first prepend elements are undefined
-
- notes:
- set must be defined
- checks nth
- see also: setdelnthsorted
-
- design:
- create new set
- setup pointers and allocate room for prepend'ed entries
- append head of old set to new set
- append tail of old set to new set
-*/
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend) {
- setT *newset;
- void **oldp, **newp;
- int tailsize= size - nth -1, newsize;
-
- if (tailsize < 0) {
- qh_fprintf(qhmem.ferr, 6176, "qhull internal error (qh_setnew_delnthsorted): nth %d is out-of-bounds for set:\n", nth);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- newsize= size-1 + prepend;
- newset= qh_setnew(newsize);
- newset->e[newset->maxsize].i= newsize+1; /* may be overwritten */
- oldp= SETaddr_(set, void);
- newp= SETaddr_(newset, void) + prepend;
- switch (nth) {
- case 0:
- break;
- case 1:
- *(newp++)= *oldp++;
- break;
- case 2:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- case 3:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- case 4:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- default:
- memcpy((char *)newp, (char *)oldp, (size_t)nth * SETelemsize);
- newp += nth;
- oldp += nth;
- break;
- }
- oldp++;
- switch (tailsize) {
- case 0:
- break;
- case 1:
- *(newp++)= *oldp++;
- break;
- case 2:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- case 3:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- case 4:
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- *(newp++)= *oldp++;
- break;
- default:
- memcpy((char *)newp, (char *)oldp, (size_t)tailsize * SETelemsize);
- newp += tailsize;
- }
- *newp= NULL;
- return(newset);
-} /* setnew_delnthsorted */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setprint">-</a>
-
- qh_setprint( fp, string, set )
- print set elements to fp with identifying string
-
- notes:
- never errors
-*/
-void qh_setprint(FILE *fp, const char* string, setT *set) {
- int size, k;
-
- if (!set)
- qh_fprintf(fp, 9346, "%s set is null\n", string);
- else {
- SETreturnsize_(set, size);
- qh_fprintf(fp, 9347, "%s set=%p maxsize=%d size=%d elems=",
- string, set, set->maxsize, size);
- if (size > set->maxsize)
- size= set->maxsize+1;
- for (k=0; k < size; k++)
- qh_fprintf(fp, 9348, " %p", set->e[k].p);
- qh_fprintf(fp, 9349, "\n");
- }
-} /* setprint */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setreplace">-</a>
-
- qh_setreplace( set, oldelem, newelem )
- replaces oldelem in set with newelem
-
- notes:
- errors if oldelem not in the set
- newelem may be NULL, but it turns the set into an indexed set (no FOREACH)
-
- design:
- find oldelem
- replace with newelem
-*/
-void qh_setreplace(setT *set, void *oldelem, void *newelem) {
- void **elemp;
-
- elemp= SETaddr_(set, void);
- while (*elemp != oldelem && *elemp)
- elemp++;
- if (*elemp)
- *elemp= newelem;
- else {
- qh_fprintf(qhmem.ferr, 6177, "qhull internal error (qh_setreplace): elem %p not found in set\n",
- oldelem);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
-} /* setreplace */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setsize">-</a>
-
- qh_setsize( set )
- returns the size of a set
-
- notes:
- errors if set's maxsize is incorrect
- same as SETreturnsize_(set)
- same code for qh_setsize [qset.c] and QhullSetBase::count
-
- design:
- determine actual size of set from maxsize
-*/
-int qh_setsize(setT *set) {
- int size;
- setelemT *sizep;
-
- if (!set)
- return(0);
- sizep= SETsizeaddr_(set);
- if ((size= sizep->i)) {
- size--;
- if (size > set->maxsize) {
- qh_fprintf(qhmem.ferr, 6178, "qhull internal error (qh_setsize): current set size %d is greater than maximum size %d\n",
- size, set->maxsize);
- qh_setprint(qhmem.ferr, "set: ", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- }else
- size= set->maxsize;
- return size;
-} /* setsize */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settemp">-</a>
-
- qh_settemp( setsize )
- return a stacked, temporary set of upto setsize elements
-
- notes:
- use settempfree or settempfree_all to release from qhmem.tempstack
- see also qh_setnew
-
- design:
- allocate set
- append to qhmem.tempstack
-
-*/
-setT *qh_settemp(int setsize) {
- setT *newset;
-
- newset= qh_setnew(setsize);
- qh_setappend(&qhmem.tempstack, newset);
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8123, "qh_settemp: temp set %p of %d elements, depth %d\n",
- newset, newset->maxsize, qh_setsize(qhmem.tempstack));
- return newset;
-} /* settemp */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settempfree">-</a>
-
- qh_settempfree( set )
- free temporary set at top of qhmem.tempstack
-
- notes:
- nop if set is NULL
- errors if set not from previous qh_settemp
-
- to locate errors:
- use 'T2' to find source and then find mis-matching qh_settemp
-
- design:
- check top of qhmem.tempstack
- free it
-*/
-void qh_settempfree(setT **set) {
- setT *stackedset;
-
- if (!*set)
- return;
- stackedset= qh_settemppop();
- if (stackedset != *set) {
- qh_settemppush(stackedset);
- qh_fprintf(qhmem.ferr, 6179, "qhull internal error (qh_settempfree): set %p(size %d) was not last temporary allocated(depth %d, set %p, size %d)\n",
- *set, qh_setsize(*set), qh_setsize(qhmem.tempstack)+1,
- stackedset, qh_setsize(stackedset));
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- qh_setfree(set);
-} /* settempfree */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settempfree_all">-</a>
-
- qh_settempfree_all( )
- free all temporary sets in qhmem.tempstack
-
- design:
- for each set in tempstack
- free set
- free qhmem.tempstack
-*/
-void qh_settempfree_all(void) {
- setT *set, **setp;
-
- FOREACHset_(qhmem.tempstack)
- qh_setfree(&set);
- qh_setfree(&qhmem.tempstack);
-} /* settempfree_all */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settemppop">-</a>
-
- qh_settemppop( )
- pop and return temporary set from qhmem.tempstack
-
- notes:
- the returned set is permanent
-
- design:
- pop and check top of qhmem.tempstack
-*/
-setT *qh_settemppop(void) {
- setT *stackedset;
-
- stackedset= (setT*)qh_setdellast(qhmem.tempstack);
- if (!stackedset) {
- qh_fprintf(qhmem.ferr, 6180, "qhull internal error (qh_settemppop): pop from empty temporary stack\n");
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8124, "qh_settemppop: depth %d temp set %p of %d elements\n",
- qh_setsize(qhmem.tempstack)+1, stackedset, qh_setsize(stackedset));
- return stackedset;
-} /* settemppop */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settemppush">-</a>
-
- qh_settemppush( set )
- push temporary set unto qhmem.tempstack (makes it temporary)
-
- notes:
- duplicates settemp() for tracing
-
- design:
- append set to tempstack
-*/
-void qh_settemppush(setT *set) {
- if (!set) {
- fprintf (qhmem.ferr, "qhull error (qh_settemppush): can not push a NULL temp\n");
- qh_errexit (qhmem_ERRqhull, NULL, NULL);
- }
- qh_setappend(&qhmem.tempstack, set);
- if (qhmem.IStracing >= 5)
- qh_fprintf(qhmem.ferr, 8125, "qh_settemppush: depth %d temp set %p of %d elements\n",
- qh_setsize(qhmem.tempstack), set, qh_setsize(set));
-} /* settemppush */
-
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="settruncate">-</a>
-
- qh_settruncate( set, size )
- truncate set to size elements
-
- notes:
- set must be defined
-
- see:
- SETtruncate_
-
- design:
- check size
- update actual size of set
-*/
-void qh_settruncate(setT *set, int size) {
-
- if (size < 0 || size > set->maxsize) {
- qh_fprintf(qhmem.ferr, 6181, "qhull internal error (qh_settruncate): size %d out of bounds for set:\n", size);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- set->e[set->maxsize].i= size+1; /* maybe overwritten */
- set->e[size].p= NULL;
-} /* settruncate */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setunique">-</a>
-
- qh_setunique( set, elem )
- add elem to unsorted set unless it is already in set
-
- notes:
- returns 1 if it is appended
-
- design:
- if elem not in set
- append elem to set
-*/
-int qh_setunique(setT **set, void *elem) {
-
- if (!qh_setin(*set, elem)) {
- qh_setappend(set, elem);
- return 1;
- }
- return 0;
-} /* setunique */
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="setzero">-</a>
-
- qh_setzero( set, index, size )
- zero elements from index on
- set actual size of set to size
-
- notes:
- set must be defined
- the set becomes an indexed set (can not use FOREACH...)
-
- see also:
- qh_settruncate
-
- design:
- check index and size
- update actual size
- zero elements starting at e[index]
-*/
-void qh_setzero(setT *set, int idx, int size) {
- int count;
-
- if (idx < 0 || idx >= size || size > set->maxsize) {
- qh_fprintf(qhmem.ferr, 6182, "qhull internal error (qh_setzero): index %d or size %d out of bounds for set:\n", idx, size);
- qh_setprint(qhmem.ferr, "", set);
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
- }
- set->e[set->maxsize].i= size+1; /* may be overwritten */
- count= size - idx + 1; /* +1 for NULL terminator */
- memset((char *)SETelemaddr_(set, idx, void), 0, (size_t)count * SETelemsize);
-} /* setzero */
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/qset.h b/PyMca/Object3D/Object3DQhull/src/qset.h
deleted file mode 100644
index 759b501..0000000
--- a/PyMca/Object3D/Object3DQhull/src/qset.h
+++ /dev/null
@@ -1,488 +0,0 @@
-/*<html><pre> -<a href="qh-set.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- qset.h
- header file for qset.c that implements set
-
- see qh-set.htm and qset.c
-
- only uses mem.c, malloc/free
-
- for error handling, writes message and calls
- qh_errexit(qhmem_ERRqhull, NULL, NULL);
-
- set operations satisfy the following properties:
- - sets have a max size, the actual size (if different) is stored at the end
- - every set is NULL terminated
- - sets may be sorted or unsorted, the caller must distinguish this
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/qset.h#4 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFset
-#define qhDEFset 1
-
-#include <stdio.h>
-
-/*================= -structures- ===============*/
-
-#ifndef DEFsetT
-#define DEFsetT 1
-typedef struct setT setT; /* a set is a sorted or unsorted array of pointers */
-#endif
-
-/*-<a href="qh-set.htm#TOC"
->----------------------------------------</a><a name="setT">-</a>
-
-setT
- a set or list of pointers with maximum size and actual size.
-
-variations:
- unsorted, unique -- a list of unique pointers with NULL terminator
- user guarantees uniqueness
- sorted -- a sorted list of unique pointers with NULL terminator
- qset.c guarantees uniqueness
- unsorted -- a list of pointers terminated with NULL
- indexed -- an array of pointers with NULL elements
-
-structure for set of n elements:
-
- --------------
- | maxsize
- --------------
- | e[0] - a pointer, may be NULL for indexed sets
- --------------
- | e[1]
-
- --------------
- | ...
- --------------
- | e[n-1]
- --------------
- | e[n] = NULL
- --------------
- | ...
- --------------
- | e[maxsize] - n+1 or NULL (determines actual size of set)
- --------------
-
-*/
-
-/*-- setelemT -- internal type to allow both pointers and indices
-*/
-typedef union setelemT setelemT;
-union setelemT {
- void *p;
- int i; /* integer used for e[maxSize] */
-};
-
-struct setT {
- int maxsize; /* maximum number of elements (except NULL) */
- setelemT e[1]; /* array of pointers, tail is NULL */
- /* last slot (unless NULL) is actual size+1
- e[maxsize]==NULL or e[e[maxsize]-1]==NULL */
- /* this may generate a warning since e[] contains
- maxsize elements */
-};
-
-/*=========== -constants- =========================*/
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------</a><a name="SETelemsize">-</a>
-
- SETelemsize
- size of a set element in bytes
-*/
-#define SETelemsize ((int)sizeof(setelemT))
-
-
-/*=========== -macros- =========================*/
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------</a><a name="FOREACHsetelement_">-</a>
-
- FOREACHsetelement_(type, set, variable)
- define FOREACH iterator
-
- declare:
- assumes *variable and **variablep are declared
- no space in "variable)" [DEC Alpha cc compiler]
-
- each iteration:
- variable is set element
- variablep is one beyond variable.
-
- to repeat an element:
- variablep--; / *repeat* /
-
- at exit:
- variable is NULL at end of loop
-
- example:
- #define FOREACHfacet_( facets ) FOREACHsetelement_( facetT, facets, facet )
-
- notes:
- use FOREACHsetelement_i_() if need index or include NULLs
-
- WARNING:
- nested loops can't use the same variable (define another FOREACH)
-
- needs braces if nested inside another FOREACH
- this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_(type, set, variable) \
- if (((variable= NULL), set)) for (\
- variable##p= (type **)&((set)->e[0].p); \
- (variable= *variable##p++);)
-
-/*-<a href="qh-set.htm#TOC"
- >----------------------------------------</a><a name="FOREACHsetelement_i_">-</a>
-
- FOREACHsetelement_i_(type, set, variable)
- define indexed FOREACH iterator
-
- declare:
- type *variable, variable_n, variable_i;
-
- each iteration:
- variable is set element, may be NULL
- variable_i is index, variable_n is qh_setsize()
-
- to repeat an element:
- variable_i--; variable_n-- repeats for deleted element
-
- at exit:
- variable==NULL and variable_i==variable_n
-
- example:
- #define FOREACHfacet_i_( facets ) FOREACHsetelement_i_( facetT, facets, facet )
-
- WARNING:
- nested loops can't use the same variable (define another FOREACH)
-
- needs braces if nested inside another FOREACH
- this includes intervening blocks, e.g. FOREACH...{ if () FOREACH...} )
-*/
-#define FOREACHsetelement_i_(type, set, variable) \
- if (((variable= NULL), set)) for (\
- variable##_i= 0, variable= (type *)((set)->e[0].p), \
- variable##_n= qh_setsize(set);\
- variable##_i < variable##_n;\
- variable= (type *)((set)->e[++variable##_i].p) )
-
-/*-<a href="qh-set.htm#TOC"
- >--------------------------------------</a><a name="FOREACHsetelementreverse_">-</a>
-
- FOREACHsetelementreverse_(type, set, variable)-
- define FOREACH iterator in reverse order
-
- declare:
- assumes *variable and **variablep are declared
- also declare 'int variabletemp'
-
- each iteration:
- variable is set element
-
- to repeat an element:
- variabletemp++; / *repeat* /
-
- at exit:
- variable is NULL
-
- example:
- #define FOREACHvertexreverse_( vertices ) FOREACHsetelementreverse_( vertexT, vertices, vertex )
-
- notes:
- use FOREACHsetelementreverse12_() to reverse first two elements
- WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse_(type, set, variable) \
- if (((variable= NULL), set)) for (\
- variable##temp= qh_setsize(set)-1, variable= qh_setlast(set);\
- variable; variable= \
- ((--variable##temp >= 0) ? SETelemt_(set, variable##temp, type) : NULL))
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------</a><a name="FOREACHsetelementreverse12_">-</a>
-
- FOREACHsetelementreverse12_(type, set, variable)-
- define FOREACH iterator with e[1] and e[0] reversed
-
- declare:
- assumes *variable and **variablep are declared
-
- each iteration:
- variable is set element
- variablep is one after variable.
-
- to repeat an element:
- variablep--; / *repeat* /
-
- at exit:
- variable is NULL at end of loop
-
- example
- #define FOREACHvertexreverse12_( vertices ) FOREACHsetelementreverse12_( vertexT, vertices, vertex )
-
- notes:
- WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHsetelementreverse12_(type, set, variable) \
- if (((variable= NULL), set)) for (\
- variable##p= (type **)&((set)->e[1].p); \
- (variable= *variable##p); \
- variable##p == ((type **)&((set)->e[0].p))?variable##p += 2: \
- (variable##p == ((type **)&((set)->e[1].p))?variable##p--:variable##p++))
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------</a><a name="FOREACHelem_">-</a>
-
- FOREACHelem_( set )-
- iterate elements in a set
-
- declare:
- void *elem, *elemp;
-
- each iteration:
- elem is set element
- elemp is one beyond
-
- to repeat an element:
- elemp--; / *repeat* /
-
- at exit:
- elem == NULL at end of loop
-
- example:
- FOREACHelem_(set) {
-
- notes:
- WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHelem_(set) FOREACHsetelement_(void, set, elem)
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------</a><a name="FOREACHset_">-</a>
-
- FOREACHset_( set )-
- iterate a set of sets
-
- declare:
- setT *set, **setp;
-
- each iteration:
- set is set element
- setp is one beyond
-
- to repeat an element:
- setp--; / *repeat* /
-
- at exit:
- set == NULL at end of loop
-
- example
- FOREACHset_(sets) {
-
- notes:
- WARNING: needs braces if nested inside another FOREACH
-*/
-#define FOREACHset_(sets) FOREACHsetelement_(setT, sets, set)
-
-/*-<a href="qh-set.htm#TOC"
- >-----------------------------------------</a><a name="SETindex_">-</a>
-
- SETindex_( set, elem )
- return index of elem in set
-
- notes:
- for use with FOREACH iteration
- WARN64 -- Maximum set size is 2G
-
- example:
- i= SETindex_(ridges, ridge)
-*/
-#define SETindex_(set, elem) ((int)((void **)elem##p - (void **)&(set)->e[1].p))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETref_">-</a>
-
- SETref_( elem )
- l.h.s. for modifying the current element in a FOREACH iteration
-
- example:
- SETref_(ridge)= anotherridge;
-*/
-#define SETref_(elem) (elem##p[-1])
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETelem_">-</a>
-
- SETelem_(set, n)
- return the n'th element of set
-
- notes:
- assumes that n is valid [0..size] and that set is defined
- use SETelemt_() for type cast
-*/
-#define SETelem_(set, n) ((set)->e[n].p)
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETelemt_">-</a>
-
- SETelemt_(set, n, type)
- return the n'th element of set as a type
-
- notes:
- assumes that n is valid [0..size] and that set is defined
-*/
-#define SETelemt_(set, n, type) ((type*)((set)->e[n].p))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETelemaddr_">-</a>
-
- SETelemaddr_(set, n, type)
- return address of the n'th element of a set
-
- notes:
- assumes that n is valid [0..size] and set is defined
-*/
-#define SETelemaddr_(set, n, type) ((type **)(&((set)->e[n].p)))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETfirst_">-</a>
-
- SETfirst_(set)
- return first element of set
-
-*/
-#define SETfirst_(set) ((set)->e[0].p)
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETfirstt_">-</a>
-
- SETfirstt_(set, type)
- return first element of set as a type
-
-*/
-#define SETfirstt_(set, type) ((type*)((set)->e[0].p))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETsecond_">-</a>
-
- SETsecond_(set)
- return second element of set
-
-*/
-#define SETsecond_(set) ((set)->e[1].p)
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETsecondt_">-</a>
-
- SETsecondt_(set, type)
- return second element of set as a type
-*/
-#define SETsecondt_(set, type) ((type*)((set)->e[1].p))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETaddr_">-</a>
-
- SETaddr_(set, type)
- return address of set's elements
-*/
-#define SETaddr_(set,type) ((type **)(&((set)->e[0].p)))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETreturnsize_">-</a>
-
- SETreturnsize_(set, size)
- return size of a set
-
- notes:
- set must be defined
- use qh_setsize(set) unless speed is critical
-*/
-#define SETreturnsize_(set, size) (((size)= ((set)->e[(set)->maxsize].i))?(--(size)):((size)= (set)->maxsize))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETempty_">-</a>
-
- SETempty_(set)
- return true(1) if set is empty
-
- notes:
- set may be NULL
-*/
-#define SETempty_(set) (!set || (SETfirst_(set) ? 0 : 1))
-
-/*-<a href="qh-set.htm#TOC"
- >-------------------------------<a name="SETsizeaddr_">-</a>
-
- SETsizeaddr_(set)
- return pointer to 'actual size+1' of set (set CANNOT be NULL!!)
- Its type is setelemT* for strict aliasing
- All SETelemaddr_ must be cast to setelemT
-
-
- notes:
- *SETsizeaddr==NULL or e[*SETsizeaddr-1].p==NULL
-*/
-#define SETsizeaddr_(set) (&((set)->e[(set)->maxsize]))
-
-/*-<a href="qh-set.htm#TOC"
- >---------------------------------------</a><a name="SETtruncate_">-</a>
-
- SETtruncate_(set, size)
- truncate set to size
-
- see:
- qh_settruncate()
-
-*/
-#define SETtruncate_(set, size) {set->e[set->maxsize].i= size+1; /* maybe overwritten */ \
- set->e[size].p= NULL;}
-
-/*======= prototypes in alphabetical order ============*/
-
-void qh_setaddsorted(setT **setp, void *elem);
-void qh_setaddnth(setT **setp, int nth, void *newelem);
-void qh_setappend(setT **setp, void *elem);
-void qh_setappend_set(setT **setp, setT *setA);
-void qh_setappend2ndlast(setT **setp, void *elem);
-void qh_setcheck(setT *set, const char *tname, unsigned id);
-void qh_setcompact(setT *set);
-setT *qh_setcopy(setT *set, int extra);
-void *qh_setdel(setT *set, void *elem);
-void *qh_setdellast(setT *set);
-void *qh_setdelnth(setT *set, int nth);
-void *qh_setdelnthsorted(setT *set, int nth);
-void *qh_setdelsorted(setT *set, void *newelem);
-setT *qh_setduplicate( setT *set, int elemsize);
-int qh_setequal(setT *setA, setT *setB);
-int qh_setequal_except(setT *setA, void *skipelemA, setT *setB, void *skipelemB);
-int qh_setequal_skip(setT *setA, int skipA, setT *setB, int skipB);
-void **qh_setendpointer(setT *set);
-void qh_setfree(setT **set);
-void qh_setfree2( setT **setp, int elemsize);
-void qh_setfreelong(setT **set);
-int qh_setin(setT *set, void *setelem);
-int qh_setindex(setT *set, void *setelem);
-void qh_setlarger(setT **setp);
-void *qh_setlast(setT *set);
-setT *qh_setnew(int size);
-setT *qh_setnew_delnthsorted(setT *set, int size, int nth, int prepend);
-void qh_setprint(FILE *fp, const char* string, setT *set);
-void qh_setreplace(setT *set, void *oldelem, void *newelem);
-int qh_setsize(setT *set);
-setT *qh_settemp(int setsize);
-void qh_settempfree(setT **set);
-void qh_settempfree_all(void);
-setT *qh_settemppop(void);
-void qh_settemppush(setT *set);
-void qh_settruncate(setT *set, int size);
-int qh_setunique(setT **set, void *elem);
-void qh_setzero(setT *set, int idx, int size);
-
-
-#endif /* qhDEFset */
diff --git a/PyMca/Object3D/Object3DQhull/src/random.c b/PyMca/Object3D/Object3DQhull/src/random.c
deleted file mode 100644
index d2af5dd..0000000
--- a/PyMca/Object3D/Object3DQhull/src/random.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*<html><pre> -<a href="index.htm#TOC"
- >-------------------------------</a><a name="TOP">-</a>
-
- random.c -- utilities
- Park & Miller's minimimal standard random number generator
- argc/argv conversion
-
- Used by rbox. Do not use 'qh'
-*/
-
-#include "libqhull.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef _MSC_VER /* Microsoft Visual C++ -- warning level 4 */
-#pragma warning( disable : 4706) /* assignment within conditional function */
-#pragma warning( disable : 4996) /* function was declared deprecated(strcpy, localtime, etc.) */
-#endif
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="argv_to_command">-</a>
-
- qh_argv_to_command( argc, argv, command, max_size )
-
- build command from argc/argv
- max_size is at least
-
- returns:
- a space-delimited string of options (just as typed)
- returns false if max_size is too short
-
- notes:
- silently removes
- makes option string easy to input and output
- matches qh_argv_to_command_size()
-
- argc may be 0
-*/
-int qh_argv_to_command(int argc, char *argv[], char* command, int max_size) {
- int i, remaining;
- char *s;
- *command= '\0'; /* max_size > 0 */
-
- if (argc) {
- if ((s= strrchr( argv[0], '\\')) /* get filename w/o .exe extension */
- || (s= strrchr( argv[0], '/')))
- s++;
- else
- s= argv[0];
- if ((int)strlen(s) < max_size) /* WARN64 */
- strcpy(command, s);
- else
- goto error_argv;
- if ((s= strstr(command, ".EXE"))
- || (s= strstr(command, ".exe")))
- *s= '\0';
- }
- for (i=1; i < argc; i++) {
- s= argv[i];
- remaining= max_size - (int)strlen(command) - (int)strlen(s) - 2; /* WARN64 */
- if (!*s || strchr(s, ' ')) {
- char *t= command + strlen(command);
- remaining -= 2;
- if (remaining < 0) {
- goto error_argv;
- }
- *t++= ' ';
- *t++= '"';
- while (*s) {
- if (*s == '"') {
- if (--remaining < 0)
- goto error_argv;
- *t++= '\\';
- }
- *t++= *s++;
- }
- *t++= '"';
- *t= '\0';
- }else if (remaining < 0) {
- goto error_argv;
- }else
- strcat(command, " ");
- strcat(command, s);
- }
- return 1;
-
-error_argv:
- return 0;
-} /* argv_to_command */
-
-/*-<a href="qh-globa.htm#TOC"
->-------------------------------</a><a name="argv_to_command_size">-</a>
-
-qh_argv_to_command_size( argc, argv )
-
- return size to allocate for qh_argv_to_command()
-
-notes:
- argc may be 0
- actual size is usually shorter
-*/
-int qh_argv_to_command_size(int argc, char *argv[]) {
- unsigned int count= 1; /* null-terminator if argc==0 */
- int i;
- char *s;
-
- for (i=0; i<argc; i++){
- count += (int)strlen(argv[i]) + 1; /* WARN64 */
- if (i>0 && strchr(argv[i], ' ')) {
- count += 2; /* quote delimiters */
- for (s=argv[i]; *s; s++) {
- if (*s == '"') {
- count++;
- }
- }
- }
- }
- return count;
-} /* argv_to_command_size */
-
-/*-<a href="qh-geom.htm#TOC"
- >-------------------------------</a><a name="rand">-</a>
-
- qh_rand()
- qh_srand( seed )
- generate pseudo-random number between 1 and 2^31 -2
-
- notes:
- For qhull and rbox, called from qh_RANDOMint(),etc. [user.h]
-
- From Park & Miller's minimal standard random number generator
- Communications of the ACM, 31:1192-1201, 1988.
- Does not use 0 or 2^31 -1
- this is silently enforced by qh_srand()
- Can make 'Rn' much faster by moving qh_rand to qh_distplane
-*/
-
-/* Global variables and constants */
-
-int qh_rand_seed= 1; /* define as global variable instead of using qh */
-
-#define qh_rand_a 16807
-#define qh_rand_m 2147483647
-#define qh_rand_q 127773 /* m div a */
-#define qh_rand_r 2836 /* m mod a */
-
-int qh_rand( void) {
- int lo, hi, test;
- int seed = qh_rand_seed;
-
- hi = seed / qh_rand_q; /* seed div q */
- lo = seed % qh_rand_q; /* seed mod q */
- test = qh_rand_a * lo - qh_rand_r * hi;
- if (test > 0)
- seed= test;
- else
- seed= test + qh_rand_m;
- qh_rand_seed= seed;
- /* seed = seed < qh_RANDOMmax/2 ? 0 : qh_RANDOMmax; for testing */
- /* seed = qh_RANDOMmax; for testing */
- return seed;
-} /* rand */
-
-void qh_srand( int seed) {
- if (seed < 1)
- qh_rand_seed= 1;
- else if (seed >= qh_rand_m)
- qh_rand_seed= qh_rand_m - 1;
- else
- qh_rand_seed= seed;
-} /* qh_srand */
-
-/*-<a href="qh-geom.htm#TOC"
->-------------------------------</a><a name="randomfactor">-</a>
-
-qh_randomfactor( scale, offset )
-return a random factor r * scale + offset
-
-notes:
-qh.RANDOMa/b are defined in global.c
-*/
-realT qh_randomfactor(realT scale, realT offset) {
- realT randr;
-
- randr= qh_RANDOMint;
- return randr * scale + offset;
-} /* randomfactor */
-
-/*-<a href="qh-geom.htm#TOC"
->-------------------------------</a><a name="randommatrix">-</a>
-
-qh_randommatrix( buffer, dim, rows )
-generate a random dim X dim matrix in range [-1,1]
-assumes buffer is [dim+1, dim]
-
-returns:
-sets buffer to random numbers
-sets rows to rows of buffer
-sets row[dim] as scratch row
-*/
-void qh_randommatrix(realT *buffer, int dim, realT **rows) {
- int i, k;
- realT **rowi, *coord, realr;
-
- coord= buffer;
- rowi= rows;
- for (i=0; i < dim; i++) {
- *(rowi++)= coord;
- for (k=0; k < dim; k++) {
- realr= qh_RANDOMint;
- *(coord++)= 2.0 * realr/(qh_RANDOMmax+1) - 1.0;
- }
- }
- *rowi= coord;
-} /* randommatrix */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="strtol">-</a>
-
- qh_strtol( s, endp) qh_strtod( s, endp)
- internal versions of strtol() and strtod()
- does not skip trailing spaces
- notes:
- some implementations of strtol()/strtod() skip trailing spaces
-*/
-double qh_strtod(const char *s, char **endp) {
- double result;
-
- result= strtod(s, endp);
- if (s < (*endp) && (*endp)[-1] == ' ')
- (*endp)--;
- return result;
-} /* strtod */
-
-int qh_strtol(const char *s, char **endp) {
- int result;
-
- result= (int) strtol(s, endp, 10); /* WARN64 */
- if (s< (*endp) && (*endp)[-1] == ' ')
- (*endp)--;
- return result;
-} /* strtol */
diff --git a/PyMca/Object3D/Object3DQhull/src/random.h b/PyMca/Object3D/Object3DQhull/src/random.h
deleted file mode 100644
index 87371db..0000000
--- a/PyMca/Object3D/Object3DQhull/src/random.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*<html><pre> -<a href="qh-geom.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- random.h
- header file for random routines
-
- see qh-geom.htm and random.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/random.h#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#ifndef qhDEFrandom
-#define qhDEFrandom 1
-
-#include "libqhull.h"
-
-/*============= prototypes in alphabetical order ======= */
-
-
-int qh_argv_to_command(int argc, char *argv[], char* command, int max_size);
-int qh_argv_to_command_size(int argc, char *argv[]);
-int qh_rand( void);
-void qh_srand( int seed);
-realT qh_randomfactor(realT scale, realT offset);
-void qh_randommatrix(realT *buffer, int dim, realT **row);
-int qh_strtol(const char *s, char **endp);
-double qh_strtod(const char *s, char **endp);
-
-#endif /* qhDEFrandom */
-
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/stat.c b/PyMca/Object3D/Object3DQhull/src/stat.c
deleted file mode 100644
index 7dc60b9..0000000
--- a/PyMca/Object3D/Object3DQhull/src/stat.c
+++ /dev/null
@@ -1,714 +0,0 @@
-/*<html><pre> -<a href="qh-stat.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- stat.c
- contains all statistics that are collected for qhull
-
- see qh-stat.htm and stat.h
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/stat.c#3 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*============ global data structure ==========*/
-
-#if qh_QHpointer
-qhstatT *qh_qhstat=NULL; /* global data structure */
-#else
-qhstatT qh_qhstat; /* add "={0}" if this causes a compiler error */
-#endif
-
-/*========== functions in alphabetic order ================*/
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="allstatA">-</a>
-
- qh_allstatA()
- define statistics in groups of 20
-
- notes:
- (otherwise, 'gcc -O2' uses too much memory)
- uses qhstat.next
-*/
-void qh_allstatA(void) {
-
- /* zdef_(type,name,doc,average) */
- zzdef_(zdoc, Zdoc2, "precision statistics", -1);
- zdef_(zinc, Znewvertex, NULL, -1);
- zdef_(wadd, Wnewvertex, "ave. distance of a new vertex to a facet(!0s)", Znewvertex);
- zzdef_(wmax, Wnewvertexmax, "max. distance of a new vertex to a facet", -1);
- zdef_(wmax, Wvertexmax, "max. distance of an output vertex to a facet", -1);
- zdef_(wmin, Wvertexmin, "min. distance of an output vertex to a facet", -1);
- zdef_(wmin, Wmindenom, "min. denominator in hyperplane computation", -1);
-
- qhstat precision= qhstat next; /* call qh_precision for each of these */
- zzdef_(zdoc, Zdoc3, "precision problems (corrected unless 'Q0' or an error)", -1);
- zzdef_(zinc, Zcoplanarridges, "coplanar half ridges in output", -1);
- zzdef_(zinc, Zconcaveridges, "concave half ridges in output", -1);
- zzdef_(zinc, Zflippedfacets, "flipped facets", -1);
- zzdef_(zinc, Zcoplanarhorizon, "coplanar horizon facets for new vertices", -1);
- zzdef_(zinc, Zcoplanarpart, "coplanar points during partitioning", -1);
- zzdef_(zinc, Zminnorm, "degenerate hyperplanes recomputed with gaussian elimination", -1);
- zzdef_(zinc, Znearlysingular, "nearly singular or axis-parallel hyperplanes", -1);
- zzdef_(zinc, Zback0, "zero divisors during back substitute", -1);
- zzdef_(zinc, Zgauss0, "zero divisors during gaussian elimination", -1);
- zzdef_(zinc, Zmultiridge, "ridges with multiple neighbors", -1);
-}
-void qh_allstatB(void) {
- zzdef_(zdoc, Zdoc1, "summary information", -1);
- zdef_(zinc, Zvertices, "number of vertices in output", -1);
- zdef_(zinc, Znumfacets, "number of facets in output", -1);
- zdef_(zinc, Znonsimplicial, "number of non-simplicial facets in output", -1);
- zdef_(zinc, Znowsimplicial, "number of simplicial facets that were merged", -1);
- zdef_(zinc, Znumridges, "number of ridges in output", -1);
- zdef_(zadd, Znumridges, "average number of ridges per facet", Znumfacets);
- zdef_(zmax, Zmaxridges, "maximum number of ridges", -1);
- zdef_(zadd, Znumneighbors, "average number of neighbors per facet", Znumfacets);
- zdef_(zmax, Zmaxneighbors, "maximum number of neighbors", -1);
- zdef_(zadd, Znumvertices, "average number of vertices per facet", Znumfacets);
- zdef_(zmax, Zmaxvertices, "maximum number of vertices", -1);
- zdef_(zadd, Znumvneighbors, "average number of neighbors per vertex", Zvertices);
- zdef_(zmax, Zmaxvneighbors, "maximum number of neighbors", -1);
- zdef_(wadd, Wcpu, "cpu seconds for qhull after input", -1);
- zdef_(zinc, Ztotvertices, "vertices created altogether", -1);
- zzdef_(zinc, Zsetplane, "facets created altogether", -1);
- zdef_(zinc, Ztotridges, "ridges created altogether", -1);
- zdef_(zinc, Zpostfacets, "facets before post merge", -1);
- zdef_(zadd, Znummergetot, "average merges per facet(at most 511)", Znumfacets);
- zdef_(zmax, Znummergemax, " maximum merges for a facet(at most 511)", -1);
- zdef_(zinc, Zangle, NULL, -1);
- zdef_(wadd, Wangle, "average angle(cosine) of facet normals for all ridges", Zangle);
- zdef_(wmax, Wanglemax, " maximum angle(cosine) of facet normals across a ridge", -1);
- zdef_(wmin, Wanglemin, " minimum angle(cosine) of facet normals across a ridge", -1);
- zdef_(wadd, Wareatot, "total area of facets", -1);
- zdef_(wmax, Wareamax, " maximum facet area", -1);
- zdef_(wmin, Wareamin, " minimum facet area", -1);
-}
-void qh_allstatC(void) {
- zdef_(zdoc, Zdoc9, "build hull statistics", -1);
- zzdef_(zinc, Zprocessed, "points processed", -1);
- zzdef_(zinc, Zretry, "retries due to precision problems", -1);
- zdef_(wmax, Wretrymax, " max. random joggle", -1);
- zdef_(zmax, Zmaxvertex, "max. vertices at any one time", -1);
- zdef_(zinc, Ztotvisible, "ave. visible facets per iteration", Zprocessed);
- zdef_(zinc, Zinsidevisible, " ave. visible facets without an horizon neighbor", Zprocessed);
- zdef_(zadd, Zvisfacettot, " ave. facets deleted per iteration", Zprocessed);
- zdef_(zmax, Zvisfacetmax, " maximum", -1);
- zdef_(zadd, Zvisvertextot, "ave. visible vertices per iteration", Zprocessed);
- zdef_(zmax, Zvisvertexmax, " maximum", -1);
- zdef_(zinc, Ztothorizon, "ave. horizon facets per iteration", Zprocessed);
- zdef_(zadd, Znewfacettot, "ave. new or merged facets per iteration", Zprocessed);
- zdef_(zmax, Znewfacetmax, " maximum(includes initial simplex)", -1);
- zdef_(wadd, Wnewbalance, "average new facet balance", Zprocessed);
- zdef_(wadd, Wnewbalance2, " standard deviation", -1);
- zdef_(wadd, Wpbalance, "average partition balance", Zpbalance);
- zdef_(wadd, Wpbalance2, " standard deviation", -1);
- zdef_(zinc, Zpbalance, " number of trials", -1);
- zdef_(zinc, Zsearchpoints, "searches of all points for initial simplex", -1);
- zdef_(zinc, Zdetsimplex, "determinants computed(area & initial hull)", -1);
- zdef_(zinc, Znoarea, "determinants not computed because vertex too low", -1);
- zdef_(zinc, Znotmax, "points ignored(!above max_outside)", -1);
- zdef_(zinc, Znotgood, "points ignored(!above a good facet)", -1);
- zdef_(zinc, Znotgoodnew, "points ignored(didn't create a good new facet)", -1);
- zdef_(zinc, Zgoodfacet, "good facets found", -1);
- zzdef_(zinc, Znumvisibility, "distance tests for facet visibility", -1);
- zdef_(zinc, Zdistvertex, "distance tests to report minimum vertex", -1);
- zzdef_(zinc, Ztotcheck, "points checked for facets' outer planes", -1);
- zzdef_(zinc, Zcheckpart, " ave. distance tests per check", Ztotcheck);
-}
-void qh_allstatD(void) {
- zdef_(zinc, Zvisit, "resets of visit_id", -1);
- zdef_(zinc, Zvvisit, " resets of vertex_visit", -1);
- zdef_(zmax, Zvisit2max, " max visit_id/2", -1);
- zdef_(zmax, Zvvisit2max, " max vertex_visit/2", -1);
-
- zdef_(zdoc, Zdoc4, "partitioning statistics(see previous for outer planes)", -1);
- zzdef_(zadd, Zdelvertextot, "total vertices deleted", -1);
- zdef_(zmax, Zdelvertexmax, " maximum vertices deleted per iteration", -1);
- zdef_(zinc, Zfindbest, "calls to findbest", -1);
- zdef_(zadd, Zfindbesttot, " ave. facets tested", Zfindbest);
- zdef_(zmax, Zfindbestmax, " max. facets tested", -1);
- zdef_(zadd, Zfindcoplanar, " ave. coplanar search", Zfindbest);
- zdef_(zinc, Zfindnew, "calls to findbestnew", -1);
- zdef_(zadd, Zfindnewtot, " ave. facets tested", Zfindnew);
- zdef_(zmax, Zfindnewmax, " max. facets tested", -1);
- zdef_(zinc, Zfindnewjump, " ave. clearly better", Zfindnew);
- zdef_(zinc, Zfindnewsharp, " calls due to qh_sharpnewfacets", -1);
- zdef_(zinc, Zfindhorizon, "calls to findhorizon", -1);
- zdef_(zadd, Zfindhorizontot, " ave. facets tested", Zfindhorizon);
- zdef_(zmax, Zfindhorizonmax, " max. facets tested", -1);
- zdef_(zinc, Zfindjump, " ave. clearly better", Zfindhorizon);
- zdef_(zinc, Zparthorizon, " horizon facets better than bestfacet", -1);
- zdef_(zinc, Zpartangle, "angle tests for repartitioned coplanar points", -1);
- zdef_(zinc, Zpartflip, " repartitioned coplanar points for flipped orientation", -1);
-}
-void qh_allstatE(void) {
- zdef_(zinc, Zpartinside, "inside points", -1);
- zdef_(zinc, Zpartnear, " inside points kept with a facet", -1);
- zdef_(zinc, Zcoplanarinside, " inside points that were coplanar with a facet", -1);
- zdef_(zinc, Zbestlower, "calls to findbestlower", -1);
- zdef_(zinc, Zbestlowerv, " with search of vertex neighbors", -1);
- zdef_(wadd, Wmaxout, "difference in max_outside at final check", -1);
- zzdef_(zinc, Zpartitionall, "distance tests for initial partition", -1);
- zdef_(zinc, Ztotpartition, "partitions of a point", -1);
- zzdef_(zinc, Zpartition, "distance tests for partitioning", -1);
- zzdef_(zinc, Zdistcheck, "distance tests for checking flipped facets", -1);
- zzdef_(zinc, Zdistconvex, "distance tests for checking convexity", -1);
- zdef_(zinc, Zdistgood, "distance tests for checking good point", -1);
- zdef_(zinc, Zdistio, "distance tests for output", -1);
- zdef_(zinc, Zdiststat, "distance tests for statistics", -1);
- zdef_(zinc, Zdistplane, "total number of distance tests", -1);
- zdef_(zinc, Ztotpartcoplanar, "partitions of coplanar points or deleted vertices", -1);
- zzdef_(zinc, Zpartcoplanar, " distance tests for these partitions", -1);
- zdef_(zinc, Zcomputefurthest, "distance tests for computing furthest", -1);
-}
-void qh_allstatE2(void) {
- zdef_(zdoc, Zdoc5, "statistics for matching ridges", -1);
- zdef_(zinc, Zhashlookup, "total lookups for matching ridges of new facets", -1);
- zdef_(zinc, Zhashtests, "average number of tests to match a ridge", Zhashlookup);
- zdef_(zinc, Zhashridge, "total lookups of subridges(duplicates and boundary)", -1);
- zdef_(zinc, Zhashridgetest, "average number of tests per subridge", Zhashridge);
- zdef_(zinc, Zdupsame, "duplicated ridges in same merge cycle", -1);
- zdef_(zinc, Zdupflip, "duplicated ridges with flipped facets", -1);
-
- zdef_(zdoc, Zdoc6, "statistics for determining merges", -1);
- zdef_(zinc, Zangletests, "angles computed for ridge convexity", -1);
- zdef_(zinc, Zbestcentrum, "best merges used centrum instead of vertices",-1);
- zzdef_(zinc, Zbestdist, "distance tests for best merge", -1);
- zzdef_(zinc, Zcentrumtests, "distance tests for centrum convexity", -1);
- zzdef_(zinc, Zdistzero, "distance tests for checking simplicial convexity", -1);
- zdef_(zinc, Zcoplanarangle, "coplanar angles in getmergeset", -1);
- zdef_(zinc, Zcoplanarcentrum, "coplanar centrums in getmergeset", -1);
- zdef_(zinc, Zconcaveridge, "concave ridges in getmergeset", -1);
-}
-void qh_allstatF(void) {
- zdef_(zdoc, Zdoc7, "statistics for merging", -1);
- zdef_(zinc, Zpremergetot, "merge iterations", -1);
- zdef_(zadd, Zmergeinittot, "ave. initial non-convex ridges per iteration", Zpremergetot);
- zdef_(zadd, Zmergeinitmax, " maximum", -1);
- zdef_(zadd, Zmergesettot, " ave. additional non-convex ridges per iteration", Zpremergetot);
- zdef_(zadd, Zmergesetmax, " maximum additional in one pass", -1);
- zdef_(zadd, Zmergeinittot2, "initial non-convex ridges for post merging", -1);
- zdef_(zadd, Zmergesettot2, " additional non-convex ridges", -1);
- zdef_(wmax, Wmaxoutside, "max distance of vertex or coplanar point above facet(w/roundoff)", -1);
- zdef_(wmin, Wminvertex, "max distance of merged vertex below facet(or roundoff)", -1);
- zdef_(zinc, Zwidefacet, "centrums frozen due to a wide merge", -1);
- zdef_(zinc, Zwidevertices, "centrums frozen due to extra vertices", -1);
- zzdef_(zinc, Ztotmerge, "total number of facets or cycles of facets merged", -1);
- zdef_(zinc, Zmergesimplex, "merged a simplex", -1);
- zdef_(zinc, Zonehorizon, "simplices merged into coplanar horizon", -1);
- zzdef_(zinc, Zcyclehorizon, "cycles of facets merged into coplanar horizon", -1);
- zzdef_(zadd, Zcyclefacettot, " ave. facets per cycle", Zcyclehorizon);
- zdef_(zmax, Zcyclefacetmax, " max. facets", -1);
- zdef_(zinc, Zmergeintohorizon, "new facets merged into horizon", -1);
- zdef_(zinc, Zmergenew, "new facets merged", -1);
- zdef_(zinc, Zmergehorizon, "horizon facets merged into new facets", -1);
- zdef_(zinc, Zmergevertex, "vertices deleted by merging", -1);
- zdef_(zinc, Zcyclevertex, "vertices deleted by merging into coplanar horizon", -1);
- zdef_(zinc, Zdegenvertex, "vertices deleted by degenerate facet", -1);
- zdef_(zinc, Zmergeflipdup, "merges due to flipped facets in duplicated ridge", -1);
- zdef_(zinc, Zneighbor, "merges due to redundant neighbors", -1);
- zdef_(zadd, Ztestvneighbor, "non-convex vertex neighbors", -1);
-}
-void qh_allstatG(void) {
- zdef_(zinc, Zacoplanar, "merges due to angle coplanar facets", -1);
- zdef_(wadd, Wacoplanartot, " average merge distance", Zacoplanar);
- zdef_(wmax, Wacoplanarmax, " maximum merge distance", -1);
- zdef_(zinc, Zcoplanar, "merges due to coplanar facets", -1);
- zdef_(wadd, Wcoplanartot, " average merge distance", Zcoplanar);
- zdef_(wmax, Wcoplanarmax, " maximum merge distance", -1);
- zdef_(zinc, Zconcave, "merges due to concave facets", -1);
- zdef_(wadd, Wconcavetot, " average merge distance", Zconcave);
- zdef_(wmax, Wconcavemax, " maximum merge distance", -1);
- zdef_(zinc, Zavoidold, "coplanar/concave merges due to avoiding old merge", -1);
- zdef_(wadd, Wavoidoldtot, " average merge distance", Zavoidold);
- zdef_(wmax, Wavoidoldmax, " maximum merge distance", -1);
- zdef_(zinc, Zdegen, "merges due to degenerate facets", -1);
- zdef_(wadd, Wdegentot, " average merge distance", Zdegen);
- zdef_(wmax, Wdegenmax, " maximum merge distance", -1);
- zdef_(zinc, Zflipped, "merges due to removing flipped facets", -1);
- zdef_(wadd, Wflippedtot, " average merge distance", Zflipped);
- zdef_(wmax, Wflippedmax, " maximum merge distance", -1);
- zdef_(zinc, Zduplicate, "merges due to duplicated ridges", -1);
- zdef_(wadd, Wduplicatetot, " average merge distance", Zduplicate);
- zdef_(wmax, Wduplicatemax, " maximum merge distance", -1);
-}
-void qh_allstatH(void) {
- zdef_(zdoc, Zdoc8, "renamed vertex statistics", -1);
- zdef_(zinc, Zrenameshare, "renamed vertices shared by two facets", -1);
- zdef_(zinc, Zrenamepinch, "renamed vertices in a pinched facet", -1);
- zdef_(zinc, Zrenameall, "renamed vertices shared by multiple facets", -1);
- zdef_(zinc, Zfindfail, "rename failures due to duplicated ridges", -1);
- zdef_(zinc, Zdupridge, " duplicate ridges detected", -1);
- zdef_(zinc, Zdelridge, "deleted ridges due to renamed vertices", -1);
- zdef_(zinc, Zdropneighbor, "dropped neighbors due to renamed vertices", -1);
- zdef_(zinc, Zdropdegen, "degenerate facets due to dropped neighbors", -1);
- zdef_(zinc, Zdelfacetdup, " facets deleted because of no neighbors", -1);
- zdef_(zinc, Zremvertex, "vertices removed from facets due to no ridges", -1);
- zdef_(zinc, Zremvertexdel, " deleted", -1);
- zdef_(zinc, Zintersectnum, "vertex intersections for locating redundant vertices", -1);
- zdef_(zinc, Zintersectfail, "intersections failed to find a redundant vertex", -1);
- zdef_(zinc, Zintersect, "intersections found redundant vertices", -1);
- zdef_(zadd, Zintersecttot, " ave. number found per vertex", Zintersect);
- zdef_(zmax, Zintersectmax, " max. found for a vertex", -1);
- zdef_(zinc, Zvertexridge, NULL, -1);
- zdef_(zadd, Zvertexridgetot, " ave. number of ridges per tested vertex", Zvertexridge);
- zdef_(zmax, Zvertexridgemax, " max. number of ridges per tested vertex", -1);
-
- zdef_(zdoc, Zdoc10, "memory usage statistics(in bytes)", -1);
- zdef_(zadd, Zmemfacets, "for facets and their normals, neighbor and vertex sets", -1);
- zdef_(zadd, Zmemvertices, "for vertices and their neighbor sets", -1);
- zdef_(zadd, Zmempoints, "for input points and outside and coplanar sets",-1);
- zdef_(zadd, Zmemridges, "for ridges and their vertex sets", -1);
-} /* allstat */
-
-void qh_allstatI(void) {
- qhstat vridges= qhstat next;
- zzdef_(zdoc, Zdoc11, "Voronoi ridge statistics", -1);
- zzdef_(zinc, Zridge, "non-simplicial Voronoi vertices for all ridges", -1);
- zzdef_(wadd, Wridge, " ave. distance to ridge", Zridge);
- zzdef_(wmax, Wridgemax, " max. distance to ridge", -1);
- zzdef_(zinc, Zridgemid, "bounded ridges", -1);
- zzdef_(wadd, Wridgemid, " ave. distance of midpoint to ridge", Zridgemid);
- zzdef_(wmax, Wridgemidmax, " max. distance of midpoint to ridge", -1);
- zzdef_(zinc, Zridgeok, "bounded ridges with ok normal", -1);
- zzdef_(wadd, Wridgeok, " ave. angle to ridge", Zridgeok);
- zzdef_(wmax, Wridgeokmax, " max. angle to ridge", -1);
- zzdef_(zinc, Zridge0, "bounded ridges with near-zero normal", -1);
- zzdef_(wadd, Wridge0, " ave. angle to ridge", Zridge0);
- zzdef_(wmax, Wridge0max, " max. angle to ridge", -1);
-
- zdef_(zdoc, Zdoc12, "Triangulation statistics(Qt)", -1);
- zdef_(zinc, Ztricoplanar, "non-simplicial facets triangulated", -1);
- zdef_(zadd, Ztricoplanartot, " ave. new facets created(may be deleted)", Ztricoplanar);
- zdef_(zmax, Ztricoplanarmax, " max. new facets created", -1);
- zdef_(zinc, Ztrinull, "null new facets deleted(duplicated vertex)", -1);
- zdef_(zinc, Ztrimirror, "mirrored pairs of new facets deleted(same vertices)", -1);
- zdef_(zinc, Ztridegen, "degenerate new facets in output(same ridge)", -1);
-} /* allstat */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="allstatistics">-</a>
-
- qh_allstatistics()
- reset printed flag for all statistics
-*/
-void qh_allstatistics(void) {
- int i;
-
- for(i=ZEND; i--; )
- qhstat printed[i]= False;
-} /* allstatistics */
-
-#if qh_KEEPstatistics
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="collectstatistics">-</a>
-
- qh_collectstatistics()
- collect statistics for qh.facet_list
-
-*/
-void qh_collectstatistics(void) {
- facetT *facet, *neighbor, **neighborp;
- vertexT *vertex, **vertexp;
- realT dotproduct, dist;
- int sizneighbors, sizridges, sizvertices, i;
-
- qh old_randomdist= qh RANDOMdist;
- qh RANDOMdist= False;
- zval_(Zmempoints)= qh num_points * qh normal_size +
- sizeof(qhT) + sizeof(qhstatT);
- zval_(Zmemfacets)= 0;
- zval_(Zmemridges)= 0;
- zval_(Zmemvertices)= 0;
- zval_(Zangle)= 0;
- wval_(Wangle)= 0.0;
- zval_(Znumridges)= 0;
- zval_(Znumfacets)= 0;
- zval_(Znumneighbors)= 0;
- zval_(Znumvertices)= 0;
- zval_(Znumvneighbors)= 0;
- zval_(Znummergetot)= 0;
- zval_(Znummergemax)= 0;
- zval_(Zvertices)= qh num_vertices - qh_setsize(qh del_vertices);
- if (qh MERGING || qh APPROXhull || qh JOGGLEmax < REALmax/2)
- wmax_(Wmaxoutside, qh max_outside);
- if (qh MERGING)
- wmin_(Wminvertex, qh min_vertex);
- FORALLfacets
- facet->seen= False;
- if (qh DELAUNAY) {
- FORALLfacets {
- if (facet->upperdelaunay != qh UPPERdelaunay)
- facet->seen= True; /* remove from angle statistics */
- }
- }
- FORALLfacets {
- if (facet->visible && qh NEWfacets)
- continue;
- sizvertices= qh_setsize(facet->vertices);
- sizneighbors= qh_setsize(facet->neighbors);
- sizridges= qh_setsize(facet->ridges);
- zinc_(Znumfacets);
- zadd_(Znumvertices, sizvertices);
- zmax_(Zmaxvertices, sizvertices);
- zadd_(Znumneighbors, sizneighbors);
- zmax_(Zmaxneighbors, sizneighbors);
- zadd_(Znummergetot, facet->nummerge);
- i= facet->nummerge; /* avoid warnings */
- zmax_(Znummergemax, i);
- if (!facet->simplicial) {
- if (sizvertices == qh hull_dim) {
- zinc_(Znowsimplicial);
- }else {
- zinc_(Znonsimplicial);
- }
- }
- if (sizridges) {
- zadd_(Znumridges, sizridges);
- zmax_(Zmaxridges, sizridges);
- }
- zadd_(Zmemfacets, sizeof(facetT) + qh normal_size + 2*sizeof(setT)
- + SETelemsize * (sizneighbors + sizvertices));
- if (facet->ridges) {
- zadd_(Zmemridges,
- sizeof(setT) + SETelemsize * sizridges + sizridges *
- (sizeof(ridgeT) + sizeof(setT) + SETelemsize * (qh hull_dim-1))/2);
- }
- if (facet->outsideset)
- zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->outsideset));
- if (facet->coplanarset)
- zadd_(Zmempoints, sizeof(setT) + SETelemsize * qh_setsize(facet->coplanarset));
- if (facet->seen) /* Delaunay upper envelope */
- continue;
- facet->seen= True;
- FOREACHneighbor_(facet) {
- if (neighbor == qh_DUPLICATEridge || neighbor == qh_MERGEridge
- || neighbor->seen || !facet->normal || !neighbor->normal)
- continue;
- dotproduct= qh_getangle(facet->normal, neighbor->normal);
- zinc_(Zangle);
- wadd_(Wangle, dotproduct);
- wmax_(Wanglemax, dotproduct)
- wmin_(Wanglemin, dotproduct)
- }
- if (facet->normal) {
- FOREACHvertex_(facet->vertices) {
- zinc_(Zdiststat);
- qh_distplane(vertex->point, facet, &dist);
- wmax_(Wvertexmax, dist);
- wmin_(Wvertexmin, dist);
- }
- }
- }
- FORALLvertices {
- if (vertex->deleted)
- continue;
- zadd_(Zmemvertices, sizeof(vertexT));
- if (vertex->neighbors) {
- sizneighbors= qh_setsize(vertex->neighbors);
- zadd_(Znumvneighbors, sizneighbors);
- zmax_(Zmaxvneighbors, sizneighbors);
- zadd_(Zmemvertices, sizeof(vertexT) + SETelemsize * sizneighbors);
- }
- }
- qh RANDOMdist= qh old_randomdist;
-} /* collectstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="freestatistics">-</a>
-
- qh_freestatistics( )
- free memory used for statistics
-*/
-void qh_freestatistics(void) {
-
-#if qh_QHpointer
- qh_free(qh_qhstat);
- qh_qhstat= NULL;
-#endif
-} /* freestatistics */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="initstatistics">-</a>
-
- qh_initstatistics( )
- allocate and initialize statistics
-
- notes:
- uses qh_malloc() instead of qh_memalloc() since mem.c not set up yet
- NOerrors -- qh_initstatistics can not use qh_errexit(). One first call, qh_memalloc is not initialized. Also invoked by QhullQh().
-*/
-void qh_initstatistics(void) {
- int i;
- realT realx;
- int intx;
-
-#if qh_QHpointer
- if(qh_qhstat){ /* qh_initstatistics may be called from Qhull::resetStatistics() */
- qh_free(qh_qhstat);
- qh_qhstat= 0;
- }
- if (!(qh_qhstat= (qhstatT *)qh_malloc(sizeof(qhstatT)))) {
- qh_fprintf(qhmem.ferr, 6183, "qhull error (qh_initstatistics): insufficient memory\n");
- qh_exit(qh_ERRmem); /* can not use qh_errexit() */
- }
-#endif
-
- qhstat next= 0;
- qh_allstatA();
- qh_allstatB();
- qh_allstatC();
- qh_allstatD();
- qh_allstatE();
- qh_allstatE2();
- qh_allstatF();
- qh_allstatG();
- qh_allstatH();
- qh_allstatI();
- if (qhstat next > (int)sizeof(qhstat id)) {
- qh_fprintf(qhmem.ferr, 6184, "qhull error (qh_initstatistics): increase size of qhstat.id[].\n\
- qhstat.next %d should be <= sizeof(qhstat id) %d\n", qhstat next, (int)sizeof(qhstat id));
-#if 0 /* for locating error, Znumridges should be duplicated */
- for(i=0; i < ZEND; i++) {
- int j;
- for(j=i+1; j < ZEND; j++) {
- if (qhstat id[i] == qhstat id[j]) {
- qh_fprintf(qhmem.ferr, 6185, "qhull error (qh_initstatistics): duplicated statistic %d at indices %d and %d\n",
- qhstat id[i], i, j);
- }
- }
- }
-#endif
- qh_exit(qh_ERRqhull); /* can not use qh_errexit() */
- }
- qhstat init[zinc].i= 0;
- qhstat init[zadd].i= 0;
- qhstat init[zmin].i= INT_MAX;
- qhstat init[zmax].i= INT_MIN;
- qhstat init[wadd].r= 0;
- qhstat init[wmin].r= REALmax;
- qhstat init[wmax].r= -REALmax;
- for(i=0; i < ZEND; i++) {
- if (qhstat type[i] > ZTYPEreal) {
- realx= qhstat init[(unsigned char)(qhstat type[i])].r;
- qhstat stats[i].r= realx;
- }else if (qhstat type[i] != zdoc) {
- intx= qhstat init[(unsigned char)(qhstat type[i])].i;
- qhstat stats[i].i= intx;
- }
- }
-} /* initstatistics */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="newstats">-</a>
-
- qh_newstats( )
- returns True if statistics for zdoc
-
- returns:
- next zdoc
-*/
-boolT qh_newstats(int idx, int *nextindex) {
- boolT isnew= False;
- int start, i;
-
- if (qhstat type[qhstat id[idx]] == zdoc)
- start= idx+1;
- else
- start= idx;
- for(i= start; i < qhstat next && qhstat type[qhstat id[i]] != zdoc; i++) {
- if (!qh_nostatistic(qhstat id[i]) && !qhstat printed[qhstat id[i]])
- isnew= True;
- }
- *nextindex= i;
- return isnew;
-} /* newstats */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="nostatistic">-</a>
-
- qh_nostatistic( index )
- true if no statistic to print
-*/
-boolT qh_nostatistic(int i) {
-
- if ((qhstat type[i] > ZTYPEreal
- &&qhstat stats[i].r == qhstat init[(unsigned char)(qhstat type[i])].r)
- || (qhstat type[i] < ZTYPEreal
- &&qhstat stats[i].i == qhstat init[(unsigned char)(qhstat type[i])].i))
- return True;
- return False;
-} /* nostatistic */
-
-#if qh_KEEPstatistics
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="printallstatistics">-</a>
-
- qh_printallstatistics( fp, string )
- print all statistics with header 'string'
-*/
-void qh_printallstatistics(FILE *fp, const char *string) {
-
- qh_allstatistics();
- qh_collectstatistics();
- qh_printstatistics(fp, string);
- qh_memstatistics(fp);
-}
-
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="printstatistics">-</a>
-
- qh_printstatistics( fp, string )
- print statistics to a file with header 'string'
- skips statistics with qhstat.printed[] (reset with qh_allstatistics)
-
- see:
- qh_printallstatistics()
-*/
-void qh_printstatistics(FILE *fp, const char *string) {
- int i, k;
- realT ave;
-
- if (qh num_points != qh num_vertices) {
- wval_(Wpbalance)= 0;
- wval_(Wpbalance2)= 0;
- }else
- wval_(Wpbalance2)= qh_stddev(zval_(Zpbalance), wval_(Wpbalance),
- wval_(Wpbalance2), &ave);
- wval_(Wnewbalance2)= qh_stddev(zval_(Zprocessed), wval_(Wnewbalance),
- wval_(Wnewbalance2), &ave);
- qh_fprintf(fp, 9350, "\n\
-%s\n\
- qhull invoked by: %s | %s\n%s with options:\n%s\n", string, qh rbox_command,
- qh qhull_command, qh_version, qh qhull_options);
- qh_fprintf(fp, 9351, "\nprecision constants:\n\
- %6.2g max. abs. coordinate in the (transformed) input('Qbd:n')\n\
- %6.2g max. roundoff error for distance computation('En')\n\
- %6.2g max. roundoff error for angle computations\n\
- %6.2g min. distance for outside points ('Wn')\n\
- %6.2g min. distance for visible facets ('Vn')\n\
- %6.2g max. distance for coplanar facets ('Un')\n\
- %6.2g max. facet width for recomputing centrum and area\n\
-",
- qh MAXabs_coord, qh DISTround, qh ANGLEround, qh MINoutside,
- qh MINvisible, qh MAXcoplanar, qh WIDEfacet);
- if (qh KEEPnearinside)
- qh_fprintf(fp, 9352, "\
- %6.2g max. distance for near-inside points\n", qh NEARinside);
- if (qh premerge_cos < REALmax/2) qh_fprintf(fp, 9353, "\
- %6.2g max. cosine for pre-merge angle\n", qh premerge_cos);
- if (qh PREmerge) qh_fprintf(fp, 9354, "\
- %6.2g radius of pre-merge centrum\n", qh premerge_centrum);
- if (qh postmerge_cos < REALmax/2) qh_fprintf(fp, 9355, "\
- %6.2g max. cosine for post-merge angle\n", qh postmerge_cos);
- if (qh POSTmerge) qh_fprintf(fp, 9356, "\
- %6.2g radius of post-merge centrum\n", qh postmerge_centrum);
- qh_fprintf(fp, 9357, "\
- %6.2g max. distance for merging two simplicial facets\n\
- %6.2g max. roundoff error for arithmetic operations\n\
- %6.2g min. denominator for divisions\n\
- zero diagonal for Gauss: ", qh ONEmerge, REALepsilon, qh MINdenom);
- for(k=0; k < qh hull_dim; k++)
- qh_fprintf(fp, 9358, "%6.2e ", qh NEARzero[k]);
- qh_fprintf(fp, 9359, "\n\n");
- for(i=0 ; i < qhstat next; )
- qh_printstats(fp, i, &i);
-} /* printstatistics */
-#endif /* qh_KEEPstatistics */
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="printstatlevel">-</a>
-
- qh_printstatlevel( fp, id )
- print level information for a statistic
-
- notes:
- nop if id >= ZEND, printed, or same as initial value
-*/
-void qh_printstatlevel(FILE *fp, int id, int start) {
-#define NULLfield " "
-
- if (id >= ZEND || qhstat printed[id])
- return;
- if (qhstat type[id] == zdoc) {
- qh_fprintf(fp, 9360, "%s\n", qhstat doc[id]);
- return;
- }
- start= 0; /* not used */
- if (qh_nostatistic(id) || !qhstat doc[id])
- return;
- qhstat printed[id]= True;
- if (qhstat count[id] != -1
- && qhstat stats[(unsigned char)(qhstat count[id])].i == 0)
- qh_fprintf(fp, 9361, " *0 cnt*");
- else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] == -1)
- qh_fprintf(fp, 9362, "%7.2g", qhstat stats[id].r);
- else if (qhstat type[id] >= ZTYPEreal && qhstat count[id] != -1)
- qh_fprintf(fp, 9363, "%7.2g", qhstat stats[id].r/ qhstat stats[(unsigned char)(qhstat count[id])].i);
- else if (qhstat type[id] < ZTYPEreal && qhstat count[id] == -1)
- qh_fprintf(fp, 9364, "%7d", qhstat stats[id].i);
- else if (qhstat type[id] < ZTYPEreal && qhstat count[id] != -1)
- qh_fprintf(fp, 9365, "%7.3g", (realT) qhstat stats[id].i / qhstat stats[(unsigned char)(qhstat count[id])].i);
- qh_fprintf(fp, 9366, " %s\n", qhstat doc[id]);
-} /* printstatlevel */
-
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="printstats">-</a>
-
- qh_printstats( fp, index, nextindex )
- print statistics for a zdoc group
-
- returns:
- next zdoc if non-null
-*/
-void qh_printstats(FILE *fp, int idx, int *nextindex) {
- int j, nexti;
-
- if (qh_newstats(idx, &nexti)) {
- qh_fprintf(fp, 9367, "\n");
- for (j=idx; j<nexti; j++)
- qh_printstatlevel(fp, qhstat id[j], 0);
- }
- if (nextindex)
- *nextindex= nexti;
-} /* printstats */
-
-#if qh_KEEPstatistics
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="stddev">-</a>
-
- qh_stddev( num, tot, tot2, ave )
- compute the standard deviation and average from statistics
-
- tot2 is the sum of the squares
- notes:
- computes r.m.s.:
- (x-ave)^2
- == x^2 - 2x tot/num + (tot/num)^2
- == tot2 - 2 tot tot/num + tot tot/num
- == tot2 - tot ave
-*/
-realT qh_stddev(int num, realT tot, realT tot2, realT *ave) {
- realT stddev;
-
- *ave= tot/num;
- stddev= sqrt(tot2/num - *ave * *ave);
- return stddev;
-} /* stddev */
-
-#endif /* qh_KEEPstatistics */
-
-#if !qh_KEEPstatistics
-void qh_collectstatistics(void) {}
-void qh_printallstatistics(FILE *fp, char *string) {};
-void qh_printstatistics(FILE *fp, char *string) {}
-#endif
-
diff --git a/PyMca/Object3D/Object3DQhull/src/stat.h b/PyMca/Object3D/Object3DQhull/src/stat.h
deleted file mode 100644
index 97d8efa..0000000
--- a/PyMca/Object3D/Object3DQhull/src/stat.h
+++ /dev/null
@@ -1,541 +0,0 @@
-/*<html><pre> -<a href="qh-stat.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- stat.h
- contains all statistics that are collected for qhull
-
- see qh-stat.htm and stat.c
-
- Copyright (c) 1993-2012 The Geometry Center.
- $Id: //main/2011/qhull/src/libqhull/stat.h#5 $$Change: 1464 $
- $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
- recompile qhull if you change this file
-
- Integer statistics are Z* while real statistics are W*.
-
- define maydebugx to call a routine at every statistic event
-
-*/
-
-#ifndef qhDEFstat
-#define qhDEFstat 1
-
-#include "libqhull.h"
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="KEEPstatistics">-</a>
-
- qh_KEEPstatistics
- 0 turns off statistic gathering (except zzdef/zzinc/zzadd/zzval/wwval)
-*/
-#ifndef qh_KEEPstatistics
-#define qh_KEEPstatistics 1
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="statistics">-</a>
-
- Zxxx for integers, Wxxx for reals
-
- notes:
- be sure that all statistics are defined in stat.c
- otherwise initialization may core dump
- can pick up all statistics by:
- grep '[zw].*_[(][ZW]' *.c >z.x
- remove trailers with query">-</a>
- remove leaders with query-replace-regexp [ ^I]+ (
-*/
-#if qh_KEEPstatistics
-enum statistics { /* alphabetical after Z/W */
- Zacoplanar,
- Wacoplanarmax,
- Wacoplanartot,
- Zangle,
- Wangle,
- Wanglemax,
- Wanglemin,
- Zangletests,
- Wareatot,
- Wareamax,
- Wareamin,
- Zavoidold,
- Wavoidoldmax,
- Wavoidoldtot,
- Zback0,
- Zbestcentrum,
- Zbestdist,
- Zbestlower,
- Zbestlowerv,
- Zcentrumtests,
- Zcheckpart,
- Zcomputefurthest,
- Zconcave,
- Wconcavemax,
- Wconcavetot,
- Zconcaveridges,
- Zconcaveridge,
- Zcoplanar,
- Wcoplanarmax,
- Wcoplanartot,
- Zcoplanarangle,
- Zcoplanarcentrum,
- Zcoplanarhorizon,
- Zcoplanarinside,
- Zcoplanarpart,
- Zcoplanarridges,
- Wcpu,
- Zcyclefacetmax,
- Zcyclefacettot,
- Zcyclehorizon,
- Zcyclevertex,
- Zdegen,
- Wdegenmax,
- Wdegentot,
- Zdegenvertex,
- Zdelfacetdup,
- Zdelridge,
- Zdelvertextot,
- Zdelvertexmax,
- Zdetsimplex,
- Zdistcheck,
- Zdistconvex,
- Zdistgood,
- Zdistio,
- Zdistplane,
- Zdiststat,
- Zdistvertex,
- Zdistzero,
- Zdoc1,
- Zdoc2,
- Zdoc3,
- Zdoc4,
- Zdoc5,
- Zdoc6,
- Zdoc7,
- Zdoc8,
- Zdoc9,
- Zdoc10,
- Zdoc11,
- Zdoc12,
- Zdropdegen,
- Zdropneighbor,
- Zdupflip,
- Zduplicate,
- Wduplicatemax,
- Wduplicatetot,
- Zdupridge,
- Zdupsame,
- Zflipped,
- Wflippedmax,
- Wflippedtot,
- Zflippedfacets,
- Zfindbest,
- Zfindbestmax,
- Zfindbesttot,
- Zfindcoplanar,
- Zfindfail,
- Zfindhorizon,
- Zfindhorizonmax,
- Zfindhorizontot,
- Zfindjump,
- Zfindnew,
- Zfindnewmax,
- Zfindnewtot,
- Zfindnewjump,
- Zfindnewsharp,
- Zgauss0,
- Zgoodfacet,
- Zhashlookup,
- Zhashridge,
- Zhashridgetest,
- Zhashtests,
- Zinsidevisible,
- Zintersect,
- Zintersectfail,
- Zintersectmax,
- Zintersectnum,
- Zintersecttot,
- Zmaxneighbors,
- Wmaxout,
- Wmaxoutside,
- Zmaxridges,
- Zmaxvertex,
- Zmaxvertices,
- Zmaxvneighbors,
- Zmemfacets,
- Zmempoints,
- Zmemridges,
- Zmemvertices,
- Zmergeflipdup,
- Zmergehorizon,
- Zmergeinittot,
- Zmergeinitmax,
- Zmergeinittot2,
- Zmergeintohorizon,
- Zmergenew,
- Zmergesettot,
- Zmergesetmax,
- Zmergesettot2,
- Zmergesimplex,
- Zmergevertex,
- Wmindenom,
- Wminvertex,
- Zminnorm,
- Zmultiridge,
- Znearlysingular,
- Zneighbor,
- Wnewbalance,
- Wnewbalance2,
- Znewfacettot,
- Znewfacetmax,
- Znewvertex,
- Wnewvertex,
- Wnewvertexmax,
- Znoarea,
- Znonsimplicial,
- Znowsimplicial,
- Znotgood,
- Znotgoodnew,
- Znotmax,
- Znumfacets,
- Znummergemax,
- Znummergetot,
- Znumneighbors,
- Znumridges,
- Znumvertices,
- Znumvisibility,
- Znumvneighbors,
- Zonehorizon,
- Zpartangle,
- Zpartcoplanar,
- Zpartflip,
- Zparthorizon,
- Zpartinside,
- Zpartition,
- Zpartitionall,
- Zpartnear,
- Zpbalance,
- Wpbalance,
- Wpbalance2,
- Zpostfacets,
- Zpremergetot,
- Zprocessed,
- Zremvertex,
- Zremvertexdel,
- Zrenameall,
- Zrenamepinch,
- Zrenameshare,
- Zretry,
- Wretrymax,
- Zridge,
- Wridge,
- Wridgemax,
- Zridge0,
- Wridge0,
- Wridge0max,
- Zridgemid,
- Wridgemid,
- Wridgemidmax,
- Zridgeok,
- Wridgeok,
- Wridgeokmax,
- Zsearchpoints,
- Zsetplane,
- Ztestvneighbor,
- Ztotcheck,
- Ztothorizon,
- Ztotmerge,
- Ztotpartcoplanar,
- Ztotpartition,
- Ztotridges,
- Ztotvertices,
- Ztotvisible,
- Ztricoplanar,
- Ztricoplanarmax,
- Ztricoplanartot,
- Ztridegen,
- Ztrimirror,
- Ztrinull,
- Wvertexmax,
- Wvertexmin,
- Zvertexridge,
- Zvertexridgetot,
- Zvertexridgemax,
- Zvertices,
- Zvisfacettot,
- Zvisfacetmax,
- Zvisit,
- Zvisit2max,
- Zvisvertextot,
- Zvisvertexmax,
- Zvvisit,
- Zvvisit2max,
- Zwidefacet,
- Zwidevertices,
- ZEND};
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="ZZstat">-</a>
-
- Zxxx/Wxxx statistics that remain defined if qh_KEEPstatistics=0
-
- notes:
- be sure to use zzdef, zzinc, etc. with these statistics (no double checking!)
-*/
-#else
-enum statistics { /* for zzdef etc. macros */
- Zback0,
- Zbestdist,
- Zcentrumtests,
- Zcheckpart,
- Zconcaveridges,
- Zcoplanarhorizon,
- Zcoplanarpart,
- Zcoplanarridges,
- Zcyclefacettot,
- Zcyclehorizon,
- Zdelvertextot,
- Zdistcheck,
- Zdistconvex,
- Zdistzero,
- Zdoc1,
- Zdoc2,
- Zdoc3,
- Zdoc11,
- Zflippedfacets,
- Zgauss0,
- Zminnorm,
- Zmultiridge,
- Znearlysingular,
- Wnewvertexmax,
- Znumvisibility,
- Zpartcoplanar,
- Zpartition,
- Zpartitionall,
- Zprocessed,
- Zretry,
- Zridge,
- Wridge,
- Wridgemax,
- Zridge0,
- Wridge0,
- Wridge0max,
- Zridgemid,
- Wridgemid,
- Wridgemidmax,
- Zridgeok,
- Wridgeok,
- Wridgeokmax,
- Zsetplane,
- Ztotcheck,
- Ztotmerge,
- ZEND};
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >-------------------------------</a><a name="ztype">-</a>
-
- ztype
- the type of a statistic sets its initial value.
-
- notes:
- The type should be the same as the macro for collecting the statistic
-*/
-enum ztypes {zdoc,zinc,zadd,zmax,zmin,ZTYPEreal,wadd,wmax,wmin,ZTYPEend};
-
-/*========== macros and constants =============*/
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="MAYdebugx">-</a>
-
- MAYdebugx
- define as maydebug() to be called frequently for error trapping
-*/
-#define MAYdebugx
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zdef_">-</a>
-
- zzdef_, zdef_( type, name, doc, -1)
- define a statistic (assumes 'qhstat.next= 0;')
-
- zdef_( type, name, doc, count)
- define an averaged statistic
- printed as name/count
-*/
-#define zzdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
- qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#if qh_KEEPstatistics
-#define zdef_(stype,name,string,cnt) qhstat id[qhstat next++]=name; \
- qhstat doc[name]= string; qhstat count[name]= cnt; qhstat type[name]= stype
-#else
-#define zdef_(type,name,doc,count)
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zinc_">-</a>
-
- zzinc_( name ), zinc_( name)
- increment an integer statistic
-*/
-#define zzinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#if qh_KEEPstatistics
-#define zinc_(id) {MAYdebugx; qhstat stats[id].i++;}
-#else
-#define zinc_(id) {}
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zadd_">-</a>
-
- zzadd_( name, value ), zadd_( name, value ), wadd_( name, value )
- add value to an integer or real statistic
-*/
-#define zzadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wwadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#if qh_KEEPstatistics
-#define zadd_(id, val) {MAYdebugx; qhstat stats[id].i += (val);}
-#define wadd_(id, val) {MAYdebugx; qhstat stats[id].r += (val);}
-#else
-#define zadd_(id, val) {}
-#define wadd_(id, val) {}
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zval_">-</a>
-
- zzval_( name ), zval_( name ), wwval_( name )
- set or return value of a statistic
-*/
-#define zzval_(id) ((qhstat stats[id]).i)
-#define wwval_(id) ((qhstat stats[id]).r)
-#if qh_KEEPstatistics
-#define zval_(id) ((qhstat stats[id]).i)
-#define wval_(id) ((qhstat stats[id]).r)
-#else
-#define zval_(id) qhstat tempi
-#define wval_(id) qhstat tempr
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zmax_">-</a>
-
- zmax_( id, val ), wmax_( id, value )
- maximize id with val
-*/
-#define wwmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#if qh_KEEPstatistics
-#define zmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].i,(val));}
-#define wmax_(id, val) {MAYdebugx; maximize_(qhstat stats[id].r,(val));}
-#else
-#define zmax_(id, val) {}
-#define wmax_(id, val) {}
-#endif
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="zmin_">-</a>
-
- zmin_( id, val ), wmin_( id, value )
- minimize id with val
-*/
-#if qh_KEEPstatistics
-#define zmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].i,(val));}
-#define wmin_(id, val) {MAYdebugx; minimize_(qhstat stats[id].r,(val));}
-#else
-#define zmin_(id, val) {}
-#define wmin_(id, val) {}
-#endif
-
-/*================== stat.h types ==============*/
-
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="intrealT">-</a>
-
- intrealT
- union of integer and real, used for statistics
-*/
-typedef union intrealT intrealT; /* union of int and realT */
-union intrealT {
- int i;
- realT r;
-};
-
-/*-<a href="qh-stat.htm#TOC"
- >--------------------------------</a><a name="qhstat">-</a>
-
- qhstat
- global data structure for statistics, similar to qh and qhrbox
-
- notes:
- access to qh_qhstat is via the "qhstat" macro. There are two choices
- qh_QHpointer = 1 access globals via a pointer
- enables qh_saveqhull() and qh_restoreqhull()
- = 0 qh_qhstat is a static data structure
- only one instance of qhull() can be active at a time
- default value
- qh_QHpointer is defined in libqhull.h
- qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
-
- allocated in stat.c using qh_malloc()
-*/
-#ifndef DEFqhstatT
-#define DEFqhstatT 1
-typedef struct qhstatT qhstatT;
-#endif
-
-#if qh_QHpointer_dllimport
-#define qhstat qh_qhstat->
-__declspec(dllimport) extern qhstatT *qh_qhstat;
-#elif qh_QHpointer
-#define qhstat qh_qhstat->
-extern qhstatT *qh_qhstat;
-#elif qh_dllimport
-#define qhstat qh_qhstat.
-__declspec(dllimport) extern qhstatT qh_qhstat;
-#else
-#define qhstat qh_qhstat.
-extern qhstatT qh_qhstat;
-#endif
-struct qhstatT {
- intrealT stats[ZEND]; /* integer and real statistics */
- unsigned char id[ZEND+10]; /* id's in print order */
- const char *doc[ZEND]; /* array of documentation strings */
- short int count[ZEND]; /* -1 if none, else index of count to use */
- char type[ZEND]; /* type, see ztypes above */
- char printed[ZEND]; /* true, if statistic has been printed */
- intrealT init[ZTYPEend]; /* initial values by types, set initstatistics */
-
- int next; /* next index for zdef_ */
- int precision; /* index for precision problems */
- int vridges; /* index for Voronoi ridges */
- int tempi;
- realT tempr;
-};
-
-/*========== function prototypes ===========*/
-
-void qh_allstatA(void);
-void qh_allstatB(void);
-void qh_allstatC(void);
-void qh_allstatD(void);
-void qh_allstatE(void);
-void qh_allstatE2(void);
-void qh_allstatF(void);
-void qh_allstatG(void);
-void qh_allstatH(void);
-void qh_allstatI(void);
-void qh_allstatistics(void);
-void qh_collectstatistics(void);
-void qh_freestatistics(void);
-void qh_initstatistics(void);
-boolT qh_newstats(int idx, int *nextindex);
-boolT qh_nostatistic(int i);
-void qh_printallstatistics(FILE *fp, const char *string);
-void qh_printstatistics(FILE *fp, const char *string);
-void qh_printstatlevel(FILE *fp, int id, int start);
-void qh_printstats(FILE *fp, int idx, int *nextindex);
-realT qh_stddev(int num, realT tot, realT tot2, realT *ave);
-
-#endif /* qhDEFstat */
diff --git a/PyMca/Object3D/Object3DQhull/src/user.c b/PyMca/Object3D/Object3DQhull/src/user.c
deleted file mode 100644
index 653c5a4..0000000
--- a/PyMca/Object3D/Object3DQhull/src/user.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*<html><pre> -<a href="qh-user.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- user.c
- user redefinable functions
-
- see user2.c for qh_fprintf, qh_malloc, qh_free
-
- see README.txt see COPYING.txt for copyright information.
-
- see libqhull.h for data structures, macros, and user-callable functions.
-
- see user_eg.c, unix.c, and qhull_interface.cpp for examples.
-
- see user.h for user-definable constants
-
- use qh_NOmem in mem.h to turn off memory management
- use qh_NOmerge in user.h to turn off facet merging
- set qh_KEEPstatistics in user.h to 0 to turn off statistics
-
- This is unsupported software. You're welcome to make changes,
- but you're on your own if something goes wrong. Use 'Tc' to
- check frequently. Usually qhull will report an error if
- a data structure becomes inconsistent. If so, it also reports
- the last point added to the hull, e.g., 102. You can then trace
- the execution of qhull with "T4P102".
-
- Please report any errors that you fix to qhull@qhull.org
-
- call_qhull is a template for calling qhull from within your application
-
- if you recompile and load this module, then user.o will not be loaded
- from qhull.a
-
- you can add additional quick allocation sizes in qh_user_memsizes
-
- if the other functions here are redefined to not use qh_print...,
- then io.o will not be loaded from qhull.a. See user_eg.c for an
- example. We recommend keeping io.o for the extra debugging
- information it supplies.
-*/
-
-#include "qhull_a.h"
-
-#include <stdarg.h>
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="call_qhull">-</a>
-
- qh_call_qhull( void )
- template for calling qhull from inside your program
- remove #if 0, #endif to compile
-
- returns:
- exit code(see qh_ERR... in libqhull.h)
- all memory freed
-
- notes:
- This can be called any number of times.
-
- see:
- qh_call_qhull_once()
-
-*/
-#if 0
-{
- int dim; /* dimension of points */
- int numpoints; /* number of points */
- coordT *points; /* array of coordinates for each point */
- boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
- char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
- FILE *outfile= stdout; /* output from qh_produce_output()
- use NULL to skip qh_produce_output() */
- FILE *errfile= stderr; /* error messages from qhull code */
- int exitcode; /* 0 if no error from qhull */
- facetT *facet; /* set by FORALLfacets */
- int curlong, totlong; /* memory remaining after qh_memfreeshort */
-
-#if qh_QHpointer /* see user.h */
- if (qh_qh){
- printf ("QH6238: Qhull link error. The global variable qh_qh was not initialized\n\
- to NULL by global.c. Please compile this program with -Dqh_QHpointer_dllimport\n\
- as well as -Dqh_QHpointer, or use libqhullstatic, or use a different tool chain.\n\n");
- exit -1;
- }
-#endif
-
- /* initialize dim, numpoints, points[], ismalloc here */
- exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
- flags, outfile, errfile);
- if (!exitcode) { /* if no error */
- /* 'qh facet_list' contains the convex hull */
- FORALLfacets {
- /* ... your code ... */
- }
- }
- qh_freeqhull(!qh_ALL);
- qh_memfreeshort(&curlong, &totlong);
- if (curlong || totlong)
- qh_fprintf(errfile, 7068, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
-}
-#endif
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="new_qhull">-</a>
-
- qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
- build new qhull data structure and return exitcode (0 if no errors)
-
- notes:
- do not modify points until finished with results.
- The qhull data structure contains pointers into the points array.
- do not call qhull functions before qh_new_qhull().
- The qhull data structure is not initialized until qh_new_qhull().
-
- outfile may be null
- qhull_cmd must start with "qhull "
- projects points to a new point array for Delaunay triangulations ('d' and 'v')
- transforms points into a new point array for halfspace intersection ('H')
-
-
- To allow multiple, concurrent calls to qhull()
- - set qh_QHpointer in user.h
- - use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
- - use qh_freeqhull(qh_ALL) to free intermediate convex hulls
-
- see:
- user_eg.c for an example
-*/
-int qh_new_qhull(int dim, int numpoints, coordT *points, boolT ismalloc,
- char *qhull_cmd, FILE *outfile, FILE *errfile) {
- int exitcode, hulldim;
- boolT new_ismalloc;
- static boolT firstcall = True;
- coordT *new_points;
-
- if (firstcall) {
- qh_meminit(errfile);
- firstcall= False;
- }
- if (strncmp(qhull_cmd,"qhull ", (size_t)6)) {
- qh_fprintf(errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \"\n");
- qh_exit(qh_ERRinput);
- }
- qh_initqhull_start(NULL, outfile, errfile);
- trace1((qh ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
- exitcode = setjmp(qh errexit);
- if (!exitcode)
- {
- qh NOerrexit = False;
- qh_initflags(qhull_cmd);
- if (qh DELAUNAY)
- qh PROJECTdelaunay= True;
- if (qh HALFspace) {
- /* points is an array of halfspaces,
- the last coordinate of each halfspace is its offset */
- hulldim= dim-1;
- qh_setfeasible(hulldim);
- new_points= qh_sethalfspace_all(dim, numpoints, points, qh feasible_point);
- new_ismalloc= True;
- if (ismalloc)
- qh_free(points);
- }else {
- hulldim= dim;
- new_points= points;
- new_ismalloc= ismalloc;
- }
- qh_init_B(new_points, numpoints, hulldim, new_ismalloc);
- qh_qhull();
- qh_check_output();
- if (outfile) {
- qh_produce_output();
- }else {
- qh_prepare_output();
- }
- if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
- qh_check_points();
- }
- qh NOerrexit = True;
- return exitcode;
-} /* new_qhull */
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="errexit">-</a>
-
- qh_errexit( exitcode, facet, ridge )
- report and exit from an error
- report facet and ridge if non-NULL
- reports useful information such as last point processed
- set qh.FORCEoutput to print neighborhood of facet
-
- see:
- qh_errexit2() in libqhull.c for printing 2 facets
-
- design:
- check for error within error processing
- compute qh.hulltime
- print facet and ridge (if any)
- report commandString, options, qh.furthest_id
- print summary and statistics (including precision statistics)
- if qh_ERRsingular
- print help text for singular data set
- exit program via long jump (if defined) or exit()
-*/
-void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
-
- if (qh ERREXITcalled) {
- qh_fprintf(qh ferr, 8126, "\nqhull error while processing previous error. Exit program\n");
- qh_exit(qh_ERRqhull);
- }
- qh ERREXITcalled= True;
- if (!qh QHULLfinished)
- qh hulltime= qh_CPUclock - qh hulltime;
- qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
- qh_fprintf(qh ferr, 8127, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
- qh_fprintf(qh ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
- if (qh furthest_id >= 0) {
- qh_fprintf(qh ferr, 8129, "Last point added to hull was p%d.", qh furthest_id);
- if (zzval_(Ztotmerge))
- qh_fprintf(qh ferr, 8130, " Last merge was #%d.", zzval_(Ztotmerge));
- if (qh QHULLfinished)
- qh_fprintf(qh ferr, 8131, "\nQhull has finished constructing the hull.");
- else if (qh POSTmerging)
- qh_fprintf(qh ferr, 8132, "\nQhull has started post-merging.");
- qh_fprintf(qh ferr, 8133, "\n");
- }
- if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
- qh_produce_output();
- else if (exitcode != qh_ERRinput) {
- if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
- qh_fprintf(qh ferr, 8134, "\nAt error exit:\n");
- qh_printsummary(qh ferr);
- if (qh PRINTstatistics) {
- qh_collectstatistics();
- qh_printstatistics(qh ferr, "at error exit");
- qh_memstatistics(qh ferr);
- }
- }
- if (qh PRINTprecision)
- qh_printstats(qh ferr, qhstat precision, NULL);
- }
- if (!exitcode)
- exitcode= qh_ERRqhull;
- else if (exitcode == qh_ERRsingular)
- qh_printhelp_singular(qh ferr);
- else if (exitcode == qh_ERRprec && !qh PREmerge)
- qh_printhelp_degenerate(qh ferr);
- if (qh NOerrexit) {
- qh_fprintf(qh ferr, 6187, "qhull error while ending program. Exit program\n");
- qh_exit(qh_ERRqhull);
- }
- qh ERREXITcalled= False;
- qh NOerrexit= True;
- longjmp(qh errexit, exitcode);
-} /* errexit */
-
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="errprint">-</a>
-
- qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
- prints out the information of facets and ridges to fp
- also prints neighbors and geomview output
-
- notes:
- except for string, any parameter may be NULL
-*/
-void qh_errprint(const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
- int i;
-
- if (atfacet) {
- qh_fprintf(qh ferr, 8135, "%s FACET:\n", string);
- qh_printfacet(qh ferr, atfacet);
- }
- if (otherfacet) {
- qh_fprintf(qh ferr, 8136, "%s OTHER FACET:\n", string);
- qh_printfacet(qh ferr, otherfacet);
- }
- if (atridge) {
- qh_fprintf(qh ferr, 8137, "%s RIDGE:\n", string);
- qh_printridge(qh ferr, atridge);
- if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
- qh_printfacet(qh ferr, atridge->top);
- if (atridge->bottom
- && atridge->bottom != atfacet && atridge->bottom != otherfacet)
- qh_printfacet(qh ferr, atridge->bottom);
- if (!atfacet)
- atfacet= atridge->top;
- if (!otherfacet)
- otherfacet= otherfacet_(atridge, atfacet);
- }
- if (atvertex) {
- qh_fprintf(qh ferr, 8138, "%s VERTEX:\n", string);
- qh_printvertex(qh ferr, atvertex);
- }
- if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
- qh_fprintf(qh ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
- for (i=0; i < qh_PRINTEND; i++) /* use fout for geomview output */
- qh_printneighborhood(qh fout, qh PRINTout[i], atfacet, otherfacet,
- !qh_ALL);
- }
-} /* errprint */
-
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="printfacetlist">-</a>
-
- qh_printfacetlist( fp, facetlist, facets, printall )
- print all fields for a facet list and/or set of facets to fp
- if !printall,
- only prints good facets
-
- notes:
- also prints all vertices
-*/
-void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
- facetT *facet, **facetp;
-
- qh_printbegin(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
- FORALLfacet_(facetlist)
- qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
- FOREACHfacet_(facets)
- qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
- qh_printend(qh ferr, qh_PRINTfacets, facetlist, facets, printall);
-} /* printfacetlist */
-
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printhelp_degenerate">-</a>
-
- qh_printhelp_degenerate( fp )
- prints descriptive message for precision error
-
- notes:
- no message if qh_QUICKhelp
-*/
-void qh_printhelp_degenerate(FILE *fp) {
-
- if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2)
- qh_fprintf(fp, 9368, "\n\
-A Qhull error has occurred. Qhull should have corrected the above\n\
-precision error. Please send the input and all of the output to\n\
-qhull_bug@qhull.org\n");
- else if (!qh_QUICKhelp) {
- qh_fprintf(fp, 9369, "\n\
-Precision problems were detected during construction of the convex hull.\n\
-This occurs because convex hull algorithms assume that calculations are\n\
-exact, but floating-point arithmetic has roundoff errors.\n\
-\n\
-To correct for precision problems, do not use 'Q0'. By default, Qhull\n\
-selects 'C-0' or 'Qx' and merges non-convex facets. With option 'QJ',\n\
-Qhull joggles the input to prevent precision problems. See \"Imprecision\n\
-in Qhull\" (qh-impre.htm).\n\
-\n\
-If you use 'Q0', the output may include\n\
-coplanar ridges, concave ridges, and flipped facets. In 4-d and higher,\n\
-Qhull may produce a ridge with four neighbors or two facets with the same \n\
-vertices. Qhull reports these events when they occur. It stops when a\n\
-concave ridge, flipped facet, or duplicate facet occurs.\n");
-#if REALfloat
- qh_fprintf(fp, 9370, "\
-\n\
-Qhull is currently using single precision arithmetic. The following\n\
-will probably remove the precision problems:\n\
- - recompile qhull for realT precision(#define REALfloat 0 in user.h).\n");
-#endif
- if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4)
- qh_fprintf(fp, 9371, "\
-\n\
-When computing the Delaunay triangulation of coordinates > 1.0,\n\
- - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
- if (qh DELAUNAY && !qh ATinfinity)
- qh_fprintf(fp, 9372, "\
-When computing the Delaunay triangulation:\n\
- - use 'Qz' to add a point at-infinity. This reduces precision problems.\n");
-
- qh_fprintf(fp, 9373, "\
-\n\
-If you need triangular output:\n\
- - use option 'Qt' to triangulate the output\n\
- - use option 'QJ' to joggle the input points and remove precision errors\n\
- - use option 'Ft'. It triangulates non-simplicial facets with added points.\n\
-\n\
-If you must use 'Q0',\n\
-try one or more of the following options. They can not guarantee an output.\n\
- - use 'QbB' to scale the input to a cube.\n\
- - use 'Po' to produce output and prevent partitioning for flipped facets\n\
- - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
- - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
- - options 'Qf', 'Qbb', and 'QR0' may also help\n",
- qh DISTround);
- qh_fprintf(fp, 9374, "\
-\n\
-To guarantee simplicial output:\n\
- - use option 'Qt' to triangulate the output\n\
- - use option 'QJ' to joggle the input points and remove precision errors\n\
- - use option 'Ft' to triangulate the output by adding points\n\
- - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
-");
- }
-} /* printhelp_degenerate */
-
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="printhelp_narrowhull">-</a>
-
- qh_printhelp_narrowhull( minangle )
- Warn about a narrow hull
-
- notes:
- Alternatively, reduce qh_WARNnarrow in user.h
-
-*/
-void qh_printhelp_narrowhull(FILE *fp, realT minangle) {
-
- qh_fprintf(fp, 9375, "qhull precision warning: \n\
-The initial hull is narrow (cosine of min. angle is %.16f).\n\
-Is the input lower dimensional (e.g., on a plane in 3-d)? Qhull may\n\
-produce a wide facet. Options 'QbB' (scale to unit box) or 'Qbb' (scale\n\
-last coordinate) may remove this warning. Use 'Pp' to skip this warning.\n\
-See 'Limitations' in qh-impre.htm.\n",
- -minangle); /* convert from angle between normals to angle between facets */
-} /* printhelp_narrowhull */
-
-/*-<a href="qh-io.htm#TOC"
- >-------------------------------</a><a name="printhelp_singular">-</a>
-
- qh_printhelp_singular( fp )
- prints descriptive message for singular input
-*/
-void qh_printhelp_singular(FILE *fp) {
- facetT *facet;
- vertexT *vertex, **vertexp;
- realT min, max, *coord, dist;
- int i,k;
-
- qh_fprintf(fp, 9376, "\n\
-The input to qhull appears to be less than %d dimensional, or a\n\
-computation has overflowed.\n\n\
-Qhull could not construct a clearly convex simplex from points:\n",
- qh hull_dim);
- qh_printvertexlist(fp, "", qh facet_list, NULL, qh_ALL);
- if (!qh_QUICKhelp)
- qh_fprintf(fp, 9377, "\n\
-The center point is coplanar with a facet, or a vertex is coplanar\n\
-with a neighboring facet. The maximum round off error for\n\
-computing distances is %2.2g. The center point, facets and distances\n\
-to the center point are as follows:\n\n", qh DISTround);
- qh_printpointid(fp, "center point", qh hull_dim, qh interior_point, -1);
- qh_fprintf(fp, 9378, "\n");
- FORALLfacets {
- qh_fprintf(fp, 9379, "facet");
- FOREACHvertex_(facet->vertices)
- qh_fprintf(fp, 9380, " p%d", qh_pointid(vertex->point));
- zinc_(Zdistio);
- qh_distplane(qh interior_point, facet, &dist);
- qh_fprintf(fp, 9381, " distance= %4.2g\n", dist);
- }
- if (!qh_QUICKhelp) {
- if (qh HALFspace)
- qh_fprintf(fp, 9382, "\n\
-These points are the dual of the given halfspaces. They indicate that\n\
-the intersection is degenerate.\n");
- qh_fprintf(fp, 9383,"\n\
-These points either have a maximum or minimum x-coordinate, or\n\
-they maximize the determinant for k coordinates. Trial points\n\
-are first selected from points that maximize a coordinate.\n");
- if (qh hull_dim >= qh_INITIALmax)
- qh_fprintf(fp, 9384, "\n\
-Because of the high dimension, the min x-coordinate and max-coordinate\n\
-points are used if the determinant is non-zero. Option 'Qs' will\n\
-do a better, though much slower, job. Instead of 'Qs', you can change\n\
-the points by randomly rotating the input with 'QR0'.\n");
- }
- qh_fprintf(fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
- for (k=0; k < qh hull_dim; k++) {
- min= REALmax;
- max= -REALmin;
- for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) {
- maximize_(max, *coord);
- minimize_(min, *coord);
- }
- qh_fprintf(fp, 9386, " %d: %8.4g %8.4g difference= %4.4g\n", k, min, max, max-min);
- }
- if (!qh_QUICKhelp) {
- qh_fprintf(fp, 9387, "\n\
-If the input should be full dimensional, you have several options that\n\
-may determine an initial simplex:\n\
- - use 'QJ' to joggle the input and make it full dimensional\n\
- - use 'QbB' to scale the points to the unit cube\n\
- - use 'QR0' to randomly rotate the input for different maximum points\n\
- - use 'Qs' to search all points for the initial simplex\n\
- - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
- - trace execution with 'T3' to see the determinant for each point.\n",
- qh DISTround);
-#if REALfloat
- qh_fprintf(fp, 9388, "\
- - recompile qhull for realT precision(#define REALfloat 0 in libqhull.h).\n");
-#endif
- qh_fprintf(fp, 9389, "\n\
-If the input is lower dimensional:\n\
- - use 'QJ' to joggle the input and make it full dimensional\n\
- - use 'Qbk:0Bk:0' to delete coordinate k from the input. You should\n\
- pick the coordinate with the least range. The hull will have the\n\
- correct topology.\n\
- - determine the flat containing the points, rotate the points\n\
- into a coordinate plane, and delete the other coordinates.\n\
- - add one or more points to make the input full dimensional.\n\
-");
- }
-} /* printhelp_singular */
-
-/*-<a href="qh-globa.htm#TOC"
- >-------------------------------</a><a name="user_memsizes">-</a>
-
- qh_user_memsizes()
- allocate up to 10 additional, quick allocation sizes
-
- notes:
- increase maximum number of allocations in qh_initqhull_mem()
-*/
-void qh_user_memsizes(void) {
-
- /* qh_memsize(size); */
-} /* user_memsizes */
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/user.h b/PyMca/Object3D/Object3DQhull/src/user.h
deleted file mode 100644
index a3322aa..0000000
--- a/PyMca/Object3D/Object3DQhull/src/user.h
+++ /dev/null
@@ -1,858 +0,0 @@
-/*<html><pre> -<a href="qh-user.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- user.h
- user redefinable constants
-
- see qh-user.htm. see COPYING for copyright information.
-
- before reading any code, review libqhull.h for data structure definitions and
- the "qh" macro.
-
-Sections:
- ============= qhull library constants ======================
- ============= data types and configuration macros ==========
- ============= performance related constants ================
- ============= memory constants =============================
- ============= joggle constants =============================
- ============= conditional compilation ======================
- ============= -merge constants- ============================
-
-Code flags --
- NOerrors -- the code does not call qh_errexit()
- WARN64 -- the code may be incompatible with 64-bit pointers
-
-*/
-
-#include <time.h>
-
-#ifndef qhDEFuser
-#define qhDEFuser 1
-
-/*============================================================*/
-/*============= qhull library constants ======================*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="filenamelen">-</a>
-
- FILENAMElen -- max length for TI and TO filenames
-
-*/
-
-#define qh_FILENAMElen 500
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="msgcode">-</a>
-
- msgcode -- Unique message codes for qh_fprintf
-
- If add new messages, assign these values and increment.
-
- def counters = [27, 1047, 2059, 3025, 4068, 5003,
- 6241, 7079, 8143, 9410, 10000, 11026]
-
- See: qh_ERR* [libqhull.h]
-*/
-
-#define MSG_TRACE0 0
-#define MSG_TRACE1 1000
-#define MSG_TRACE2 2000
-#define MSG_TRACE3 3000
-#define MSG_TRACE4 4000
-#define MSG_TRACE5 5000
-#define MSG_ERROR 6000 /* errors written to qh.ferr */
-#define MSG_WARNING 7000
-#define MSG_STDERR 8000 /* log messages Written to qh.ferr */
-#define MSG_OUTPUT 9000
-#define MSG_QHULL_ERROR 10000 /* errors thrown by QhullError [QhullError.h] */
-#define MSG_FIXUP 11000 /* FIXUP QH11... */
-#define MSG_MAXLEN 3000 /* qh_printhelp_degenerate() in user.c */
-
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="qh_OPTIONline">-</a>
-
- qh_OPTIONline -- max length of an option line 'FO'
-*/
-#define qh_OPTIONline 80
-
-/*============================================================*/
-/*============= data types and configuration macros ==========*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="realT">-</a>
-
- realT
- set the size of floating point numbers
-
- qh_REALdigits
- maximimum number of significant digits
-
- qh_REAL_1, qh_REAL_2n, qh_REAL_3n
- format strings for printf
-
- qh_REALmax, qh_REALmin
- maximum and minimum (near zero) values
-
- qh_REALepsilon
- machine roundoff. Maximum roundoff error for addition and multiplication.
-
- notes:
- Select whether to store floating point numbers in single precision (float)
- or double precision (double).
-
- Use 'float' to save about 8% in time and 25% in space. This is particularly
- helpful if high-d where convex hulls are space limited. Using 'float' also
- reduces the printed size of Qhull's output since numbers have 8 digits of
- precision.
-
- Use 'double' when greater arithmetic precision is needed. This is needed
- for Delaunay triangulations and Voronoi diagrams when you are not merging
- facets.
-
- If 'double' gives insufficient precision, your data probably includes
- degeneracies. If so you should use facet merging (done by default)
- or exact arithmetic (see imprecision section of manual, qh-impre.htm).
- You may also use option 'Po' to force output despite precision errors.
-
- You may use 'long double', but many format statements need to be changed
- and you may need a 'long double' square root routine. S. Grundmann
- (sg@eeiwzb.et.tu-dresden.de) has done this. He reports that the code runs
- much slower with little gain in precision.
-
- WARNING: on some machines, int f(){realT a= REALmax;return (a == REALmax);}
- returns False. Use (a > REALmax/2) instead of (a == REALmax).
-
- REALfloat = 1 all numbers are 'float' type
- = 0 all numbers are 'double' type
-*/
-#define REALfloat 0
-
-#if (REALfloat == 1)
-#define realT float
-#define REALmax FLT_MAX
-#define REALmin FLT_MIN
-#define REALepsilon FLT_EPSILON
-#define qh_REALdigits 8 /* maximum number of significant digits */
-#define qh_REAL_1 "%6.8g "
-#define qh_REAL_2n "%6.8g %6.8g\n"
-#define qh_REAL_3n "%6.8g %6.8g %6.8g\n"
-
-#elif (REALfloat == 0)
-#define realT double
-#define REALmax DBL_MAX
-#define REALmin DBL_MIN
-#define REALepsilon DBL_EPSILON
-#define qh_REALdigits 16 /* maximum number of significant digits */
-#define qh_REAL_1 "%6.16g "
-#define qh_REAL_2n "%6.16g %6.16g\n"
-#define qh_REAL_3n "%6.16g %6.16g %6.16g\n"
-
-#else
-#error unknown float option
-#endif
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="CPUclock">-</a>
-
- qh_CPUclock
- define the clock() function for reporting the total time spent by Qhull
- returns CPU ticks as a 'long int'
- qh_CPUclock is only used for reporting the total time spent by Qhull
-
- qh_SECticks
- the number of clock ticks per second
-
- notes:
- looks for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or assumes microseconds
- to define a custom clock, set qh_CLOCKtype to 0
-
- if your system does not use clock() to return CPU ticks, replace
- qh_CPUclock with the corresponding function. It is converted
- to 'unsigned long' to prevent wrap-around during long runs. By default,
- <time.h> defines clock_t as 'long'
-
- Set qh_CLOCKtype to
-
- 1 for CLOCKS_PER_SEC, CLOCKS_PER_SECOND, or microsecond
- Note: may fail if more than 1 hour elapsed time
-
- 2 use qh_clock() with POSIX times() (see global.c)
-*/
-#define qh_CLOCKtype 1 /* change to the desired number */
-
-#if (qh_CLOCKtype == 1)
-
-#if defined(CLOCKS_PER_SECOND)
-#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SECOND
-
-#elif defined(CLOCKS_PER_SEC)
-#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
-#define qh_SECticks CLOCKS_PER_SEC
-
-#elif defined(CLK_TCK)
-#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
-#define qh_SECticks CLK_TCK
-
-#else
-#define qh_CPUclock ((unsigned long)clock()) /* return CPU clock */
-#define qh_SECticks 1E6
-#endif
-
-#elif (qh_CLOCKtype == 2)
-#define qh_CPUclock qh_clock() /* return CPU clock */
-#define qh_SECticks 100
-
-#else /* qh_CLOCKtype == ? */
-#error unknown clock option
-#endif
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="RANDOM">-</a>
-
- qh_RANDOMtype, qh_RANDOMmax, qh_RANDOMseed
- define random number generator
-
- qh_RANDOMint generates a random integer between 0 and qh_RANDOMmax.
- qh_RANDOMseed sets the random number seed for qh_RANDOMint
-
- Set qh_RANDOMtype (default 5) to:
- 1 for random() with 31 bits (UCB)
- 2 for rand() with RAND_MAX or 15 bits (system 5)
- 3 for rand() with 31 bits (Sun)
- 4 for lrand48() with 31 bits (Solaris)
- 5 for qh_rand() with 31 bits (included with Qhull)
-
- notes:
- Random numbers are used by rbox to generate point sets. Random
- numbers are used by Qhull to rotate the input ('QRn' option),
- simulate a randomized algorithm ('Qr' option), and to simulate
- roundoff errors ('Rn' option).
-
- Random number generators differ between systems. Most systems provide
- rand() but the period varies. The period of rand() is not critical
- since qhull does not normally use random numbers.
-
- The default generator is Park & Miller's minimal standard random
- number generator [CACM 31:1195 '88]. It is included with Qhull.
-
- If qh_RANDOMmax is wrong, qhull will report a warning and Geomview
- output will likely be invisible.
-*/
-#define qh_RANDOMtype 5 /* *** change to the desired number *** */
-
-#if (qh_RANDOMtype == 1)
-#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, random()/MAX */
-#define qh_RANDOMint random()
-#define qh_RANDOMseed_(seed) srandom(seed);
-
-#elif (qh_RANDOMtype == 2)
-#ifdef RAND_MAX
-#define qh_RANDOMmax ((realT)RAND_MAX)
-#else
-#define qh_RANDOMmax ((realT)32767) /* 15 bits (System 5) */
-#endif
-#define qh_RANDOMint rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 3)
-#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, Sun */
-#define qh_RANDOMint rand()
-#define qh_RANDOMseed_(seed) srand((unsigned)seed);
-
-#elif (qh_RANDOMtype == 4)
-#define qh_RANDOMmax ((realT)0x7fffffffUL) /* 31 bits, lrand38()/MAX */
-#define qh_RANDOMint lrand48()
-#define qh_RANDOMseed_(seed) srand48(seed);
-
-#elif (qh_RANDOMtype == 5)
-#define qh_RANDOMmax ((realT)2147483646UL) /* 31 bits, qh_rand/MAX */
-#define qh_RANDOMint qh_rand()
-#define qh_RANDOMseed_(seed) qh_srand(seed);
-/* unlike rand(), never returns 0 */
-
-#else
-#error: unknown random option
-#endif
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="ORIENTclock">-</a>
-
- qh_ORIENTclock
- 0 for inward pointing normals by Geomview convention
-*/
-#define qh_ORIENTclock 0
-
-
-/*============================================================*/
-/*============= joggle constants =============================*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEdefault">-</a>
-
-qh_JOGGLEdefault
-default qh.JOGGLEmax is qh.DISTround * qh_JOGGLEdefault
-
-notes:
-rbox s r 100 | qhull QJ1e-15 QR0 generates 90% faults at distround 7e-16
-rbox s r 100 | qhull QJ1e-14 QR0 generates 70% faults
-rbox s r 100 | qhull QJ1e-13 QR0 generates 35% faults
-rbox s r 100 | qhull QJ1e-12 QR0 generates 8% faults
-rbox s r 100 | qhull QJ1e-11 QR0 generates 1% faults
-rbox s r 100 | qhull QJ1e-10 QR0 generates 0% faults
-rbox 1000 W0 | qhull QJ1e-12 QR0 generates 86% faults
-rbox 1000 W0 | qhull QJ1e-11 QR0 generates 20% faults
-rbox 1000 W0 | qhull QJ1e-10 QR0 generates 2% faults
-the later have about 20 points per facet, each of which may interfere
-
-pick a value large enough to avoid retries on most inputs
-*/
-#define qh_JOGGLEdefault 30000.0
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEincrease">-</a>
-
-qh_JOGGLEincrease
-factor to increase qh.JOGGLEmax on qh_JOGGLEretry or qh_JOGGLEagain
-*/
-#define qh_JOGGLEincrease 10.0
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEretry">-</a>
-
-qh_JOGGLEretry
-if ZZretry = qh_JOGGLEretry, increase qh.JOGGLEmax
-
-notes:
-try twice at the original value in case of bad luck the first time
-*/
-#define qh_JOGGLEretry 2
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEagain">-</a>
-
-qh_JOGGLEagain
-every following qh_JOGGLEagain, increase qh.JOGGLEmax
-
-notes:
-1 is OK since it's already failed qh_JOGGLEretry times
-*/
-#define qh_JOGGLEagain 1
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEmaxincrease">-</a>
-
-qh_JOGGLEmaxincrease
-maximum qh.JOGGLEmax due to qh_JOGGLEincrease
-relative to qh.MAXwidth
-
-notes:
-qh.joggleinput will retry at this value until qh_JOGGLEmaxretry
-*/
-#define qh_JOGGLEmaxincrease 1e-2
-
-/*-<a href="qh-user.htm#TOC"
->--------------------------------</a><a name="JOGGLEmaxretry">-</a>
-
-qh_JOGGLEmaxretry
-stop after qh_JOGGLEmaxretry attempts
-*/
-#define qh_JOGGLEmaxretry 100
-
-/*============================================================*/
-/*============= performance related constants ================*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="HASHfactor">-</a>
-
- qh_HASHfactor
- total hash slots / used hash slots. Must be at least 1.1.
-
- notes:
- =2 for at worst 50% occupancy for qh hash_table and normally 25% occupancy
-*/
-#define qh_HASHfactor 2
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="VERIFYdirect">-</a>
-
- qh_VERIFYdirect
- with 'Tv' verify all points against all facets if op count is smaller
-
- notes:
- if greater, calls qh_check_bestdist() instead
-*/
-#define qh_VERIFYdirect 1000000
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="INITIALsearch">-</a>
-
- qh_INITIALsearch
- if qh_INITIALmax, search points up to this dimension
-*/
-#define qh_INITIALsearch 6
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="INITIALmax">-</a>
-
- qh_INITIALmax
- if dim >= qh_INITIALmax, use min/max coordinate points for initial simplex
-
- notes:
- from points with non-zero determinants
- use option 'Qs' to override (much slower)
-*/
-#define qh_INITIALmax 8
-
-/*============================================================*/
-/*============= memory constants =============================*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MEMalign">-</a>
-
- qh_MEMalign
- memory alignment for qh_meminitbuffers() in global.c
-
- notes:
- to avoid bus errors, memory allocation must consider alignment requirements.
- malloc() automatically takes care of alignment. Since mem.c manages
- its own memory, we need to explicitly specify alignment in
- qh_meminitbuffers().
-
- A safe choice is sizeof(double). sizeof(float) may be used if doubles
- do not occur in data structures and pointers are the same size. Be careful
- of machines (e.g., DEC Alpha) with large pointers.
-
- If using gcc, best alignment is
- #define qh_MEMalign fmax_(__alignof__(realT),__alignof__(void *))
-*/
-#define qh_MEMalign ((int)(fmax_(sizeof(realT), sizeof(void *))))
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MEMbufsize">-</a>
-
- qh_MEMbufsize
- size of additional memory buffers
-
- notes:
- used for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMbufsize 0x10000 /* allocate 64K memory buffers */
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MEMinitbuf">-</a>
-
- qh_MEMinitbuf
- size of initial memory buffer
-
- notes:
- use for qh_meminitbuffers() in global.c
-*/
-#define qh_MEMinitbuf 0x20000 /* initially allocate 128K buffer */
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="INFINITE">-</a>
-
- qh_INFINITE
- on output, indicates Voronoi center at infinity
-*/
-#define qh_INFINITE -10.101
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="DEFAULTbox">-</a>
-
- qh_DEFAULTbox
- default box size (Geomview expects 0.5)
-
- qh_DEFAULTbox
- default box size for integer coorindate (rbox only)
-*/
-#define qh_DEFAULTbox 0.5
-#define qh_DEFAULTzbox 1e6
-
-/*============================================================*/
-/*============= conditional compilation ======================*/
-/*============================================================*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="compiler">-</a>
-
- __cplusplus
- defined by C++ compilers
-
- __MSC_VER
- defined by Microsoft Visual C++
-
- __MWERKS__ && __POWERPC__
- defined by Metrowerks when compiling for the Power Macintosh
-
- __STDC__
- defined for strict ANSI C
-*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="COMPUTEfurthest">-</a>
-
- qh_COMPUTEfurthest
- compute furthest distance to an outside point instead of storing it with the facet
- =1 to compute furthest
-
- notes:
- computing furthest saves memory but costs time
- about 40% more distance tests for partitioning
- removes facet->furthestdist
-*/
-#define qh_COMPUTEfurthest 0
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="KEEPstatistics">-</a>
-
- qh_KEEPstatistics
- =0 removes most of statistic gathering and reporting
-
- notes:
- if 0, code size is reduced by about 4%.
-*/
-#define qh_KEEPstatistics 1
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MAXoutside">-</a>
-
- qh_MAXoutside
- record outer plane for each facet
- =1 to record facet->maxoutside
-
- notes:
- this takes a realT per facet and slightly slows down qhull
- it produces better outer planes for geomview output
-*/
-#define qh_MAXoutside 1
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="NOmerge">-</a>
-
- qh_NOmerge
- disables facet merging if defined
-
- notes:
- This saves about 10% space.
-
- Unless 'Q0'
- qh_NOmerge sets 'QJ' to avoid precision errors
-
- #define qh_NOmerge
-
- see:
- <a href="mem.h#NOmem">qh_NOmem</a> in mem.c
-
- see user.c/user_eg.c for removing io.o
-*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="NOtrace">-</a>
-
- qh_NOtrace
- no tracing if defined
-
- notes:
- This saves about 5% space.
-
- #define qh_NOtrace
-*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="QHpointer">-</a>
-
- qh_QHpointer
- access global data with pointer or static structure
-
- qh_QHpointer = 1 access globals via a pointer to allocated memory
- enables qh_saveqhull() and qh_restoreqhull()
- [2010, gcc] costs about 4% in time and 4% in space
- [2003, msvc] costs about 8% in time and 2% in space
-
- = 0 qh_qh and qh_qhstat are static data structures
- only one instance of qhull() can be active at a time
- default value
-
- qh_QHpointer_dllimport and qh_dllimport define qh_qh as __declspec(dllimport) [libqhull.h]
- It is required for msvc-2005. It is not needed for gcc.
-
- notes:
- all global variables for qhull are in qh, qhmem, and qhstat
- qh is defined in libqhull.h
- qhmem is defined in mem.h
- qhstat is defined in stat.h
- C++ build defines qh_QHpointer [libqhullp.pro, libqhullcpp.pro]
-
- see:
- user_eg.c for an example
-*/
-#ifdef qh_QHpointer
-#if qh_dllimport
-#error QH6207 Qhull error: Use qh_QHpointer_dllimport instead of qh_dllimport with qh_QHpointer
-#endif
-#else
-#define qh_QHpointer 0
-#if qh_QHpointer_dllimport
-#error QH6234 Qhull error: Use qh_dllimport instead of qh_QHpointer_dllimport when qh_QHpointer is not defined
-#endif
-#endif
-#if 0 /* sample code */
- qhT *oldqhA, *oldqhB;
-
- exitcode= qh_new_qhull(dim, numpoints, points, ismalloc,
- flags, outfile, errfile);
- /* use results from first call to qh_new_qhull */
- oldqhA= qh_save_qhull();
- exitcode= qh_new_qhull(dimB, numpointsB, pointsB, ismalloc,
- flags, outfile, errfile);
- /* use results from second call to qh_new_qhull */
- oldqhB= qh_save_qhull();
- qh_restore_qhull(&oldqhA);
- /* use results from first call to qh_new_qhull */
- qh_freeqhull(qh_ALL); /* frees all memory used by first call */
- qh_restore_qhull(&oldqhB);
- /* use results from second call to qh_new_qhull */
- qh_freeqhull(!qh_ALL); /* frees long memory used by second call */
- qh_memfreeshort(&curlong, &totlong); /* frees short memory and memory allocator */
-#endif
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="QUICKhelp">-</a>
-
- qh_QUICKhelp
- =1 to use abbreviated help messages, e.g., for degenerate inputs
-*/
-#define qh_QUICKhelp 0
-
-/*============================================================*/
-/*============= -merge constants- ============================*/
-/*============================================================*/
-/*
- These constants effect facet merging. You probably will not need
- to modify them. They effect the performance of facet merging.
-*/
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="DIMmergeVertex">-</a>
-
- qh_DIMmergeVertex
- max dimension for vertex merging (it is not effective in high-d)
-*/
-#define qh_DIMmergeVertex 6
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="DIMreduceBuild">-</a>
-
- qh_DIMreduceBuild
- max dimension for vertex reduction during build (slow in high-d)
-*/
-#define qh_DIMreduceBuild 5
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="BESTcentrum">-</a>
-
- qh_BESTcentrum
- if > 2*dim+n vertices, qh_findbestneighbor() tests centrums (faster)
- else, qh_findbestneighbor() tests all vertices (much better merges)
-
- qh_BESTcentrum2
- if qh_BESTcentrum2 * DIM3 + BESTcentrum < #vertices tests centrums
-*/
-#define qh_BESTcentrum 20
-#define qh_BESTcentrum2 2
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="BESTnonconvex">-</a>
-
- qh_BESTnonconvex
- if > dim+n neighbors, qh_findbestneighbor() tests nonconvex ridges.
-
- notes:
- It is needed because qh_findbestneighbor is slow for large facets
-*/
-#define qh_BESTnonconvex 15
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MAXnewmerges">-</a>
-
- qh_MAXnewmerges
- if >n newmerges, qh_merge_nonconvex() calls qh_reducevertices_centrums.
-
- notes:
- It is needed because postmerge can merge many facets at once
-*/
-#define qh_MAXnewmerges 2
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MAXnewcentrum">-</a>
-
- qh_MAXnewcentrum
- if <= dim+n vertices (n approximates the number of merges),
- reset the centrum in qh_updatetested() and qh_mergecycle_facets()
-
- notes:
- needed to reduce cost and because centrums may move too much if
- many vertices in high-d
-*/
-#define qh_MAXnewcentrum 5
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="COPLANARratio">-</a>
-
- qh_COPLANARratio
- for 3-d+ merging, qh.MINvisible is n*premerge_centrum
-
- notes:
- for non-merging, it's DISTround
-*/
-#define qh_COPLANARratio 3
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="DISToutside">-</a>
-
- qh_DISToutside
- When is a point clearly outside of a facet?
- Stops search in qh_findbestnew or qh_partitionall
- qh_findbest uses qh.MINoutside since since it is only called if no merges.
-
- notes:
- 'Qf' always searches for best facet
- if !qh.MERGING, same as qh.MINoutside.
- if qh_USEfindbestnew, increase value since neighboring facets may be ill-behaved
- [Note: Zdelvertextot occurs normally with interior points]
- RBOX 1000 s Z1 G1e-13 t1001188774 | QHULL Tv
- When there is a sharp edge, need to move points to a
- clearly good facet; otherwise may be lost in another partitioning.
- if too big then O(n^2) behavior for partitioning in cone
- if very small then important points not processed
- Needed in qh_partitionall for
- RBOX 1000 s Z1 G1e-13 t1001032651 | QHULL Tv
- Needed in qh_findbestnew for many instances of
- RBOX 1000 s Z1 G1e-13 t | QHULL Tv
-
- See:
- qh_DISToutside -- when is a point clearly outside of a facet
- qh_SEARCHdist -- when is facet coplanar with the best facet?
- qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_DISToutside ((qh_USEfindbestnew ? 2 : 1) * \
- fmax_((qh MERGING ? 2 : 1)*qh MINoutside, qh max_outside))
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="RATIOnearinside">-</a>
-
- qh_RATIOnearinside
- ratio of qh.NEARinside to qh.ONEmerge for retaining inside points for
- qh_check_maxout().
-
- notes:
- This is overkill since do not know the correct value.
- It effects whether 'Qc' reports all coplanar points
- Not used for 'd' since non-extreme points are coplanar
-*/
-#define qh_RATIOnearinside 5
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="SEARCHdist">-</a>
-
- qh_SEARCHdist
- When is a facet coplanar with the best facet?
- qh_findbesthorizon: all coplanar facets of the best facet need to be searched.
-
- See:
- qh_DISToutside -- when is a point clearly outside of a facet
- qh_SEARCHdist -- when is facet coplanar with the best facet?
- qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_SEARCHdist ((qh_USEfindbestnew ? 2 : 1) * \
- (qh max_outside + 2 * qh DISTround + fmax_( qh MINvisible, qh MAXcoplanar)));
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="USEfindbestnew">-</a>
-
- qh_USEfindbestnew
- Always use qh_findbestnew for qh_partitionpoint, otherwise use
- qh_findbestnew if merged new facet or sharpnewfacets.
-
- See:
- qh_DISToutside -- when is a point clearly outside of a facet
- qh_SEARCHdist -- when is facet coplanar with the best facet?
- qh_USEfindbestnew -- when to use qh_findbestnew for qh_partitionpoint()
-*/
-#define qh_USEfindbestnew (zzval_(Ztotmerge) > 50)
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="WIDEcoplanar">-</a>
-
- qh_WIDEcoplanar
- n*MAXcoplanar or n*MINvisible for a WIDEfacet
-
- if vertex is further than qh.WIDEfacet from the hyperplane
- then its ridges are not counted in computing the area, and
- the facet's centrum is frozen.
-
- notes:
- qh.WIDEfacet= max(qh.MAXoutside,qh_WIDEcoplanar*qh.MAXcoplanar,
- qh_WIDEcoplanar * qh.MINvisible);
-*/
-#define qh_WIDEcoplanar 6
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="MAXnarrow">-</a>
-
- qh_MAXnarrow
- max. cosine in initial hull that sets qh.NARROWhull
-
- notes:
- If qh.NARROWhull, the initial partition does not make
- coplanar points. If narrow, a coplanar point can be
- coplanar to two facets of opposite orientations and
- distant from the exact convex hull.
-
- Conservative estimate. Don't actually see problems until it is -1.0
-*/
-#define qh_MAXnarrow -0.99999999
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="WARNnarrow">-</a>
-
- qh_WARNnarrow
- max. cosine in initial hull to warn about qh.NARROWhull
-
- notes:
- this is a conservative estimate.
- Don't actually see problems until it is -1.0. See qh-impre.htm
-*/
-#define qh_WARNnarrow -0.999999999999999
-
-/*-<a href="qh-user.htm#TOC"
- >--------------------------------</a><a name="ZEROdelaunay">-</a>
-
- qh_ZEROdelaunay
- a zero Delaunay facet occurs for input sites coplanar with their convex hull
- the last normal coefficient of a zero Delaunay facet is within
- qh_ZEROdelaunay * qh.ANGLEround of 0
-
- notes:
- qh_ZEROdelaunay does not allow for joggled input ('QJ').
-
- You can avoid zero Delaunay facets by surrounding the input with a box.
-
- Use option 'PDk:-n' to explicitly define zero Delaunay facets
- k= dimension of input sites (e.g., 3 for 3-d Delaunay triangulation)
- n= the cutoff for zero Delaunay facets (e.g., 'PD3:-1e-12')
-*/
-#define qh_ZEROdelaunay 2
-
-#endif /* qh_DEFuser */
-
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/usermem.c b/PyMca/Object3D/Object3DQhull/src/usermem.c
deleted file mode 100644
index 8cb6ba4..0000000
--- a/PyMca/Object3D/Object3DQhull/src/usermem.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*<html><pre> -<a href="qh-user.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- usermem.c
- qh_exit(), qh_free(), and qh_malloc()
-
- See README.txt.
-
- If you redefine one of these functions you must redefine all of them.
- If you recompile and load this file, then usermem.o will not be loaded
- from qhull.a or qhull.lib
-
- See libqhull.h for data structures, macros, and user-callable functions.
- See user.c for qhull-related, redefinable functions
- see user.h for user-definable constants
- See userprintf.c for qh_fprintf and userprintf_rbox,c for qh_fprintf_rbox
-
- Please report any errors that you fix to qhull@qhull.org
-*/
-
-#include "libqhull.h"
-
-#include <stdlib.h>
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="qh_exit">-</a>
-
- qh_exit( exitcode )
- exit program
-
- notes:
- same as exit()
-*/
-void qh_exit(int exitcode) {
- exit(exitcode);
-} /* exit */
-
-/*-<a href="qh-user.htm#TOC"
->-------------------------------</a><a name="qh_free">-</a>
-
-qh_free( mem )
-free memory
-
-notes:
-same as free()
-*/
-void qh_free(void *mem) {
- free(mem);
-} /* free */
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="qh_malloc">-</a>
-
- qh_malloc( mem )
- allocate memory
-
- notes:
- same as malloc()
-*/
-void *qh_malloc(size_t size) {
- return malloc(size);
-} /* malloc */
-
-
diff --git a/PyMca/Object3D/Object3DQhull/src/userprintf.c b/PyMca/Object3D/Object3DQhull/src/userprintf.c
deleted file mode 100644
index 88ead2f..0000000
--- a/PyMca/Object3D/Object3DQhull/src/userprintf.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*<html><pre> -<a href="qh-user.htm"
- >-------------------------------</a><a name="TOP">-</a>
-
- userprintf.c
- qh_fprintf()
-
- see README.txt see COPYING.txt for copyright information.
-
- If you recompile and load this file, then userprintf.o will not be loaded
- from qhull.a or qhull.lib
-
- See libqhull.h for data structures, macros, and user-callable functions.
- See user.c for qhull-related, redefinable functions
- see user.h for user-definable constants
- See usermem.c for qh_exit(), qh_free(), and qh_malloc()
- see Qhull.cpp and RboxPoints.cpp for examples.
-
- Please report any errors that you fix to qhull@qhull.org
-*/
-
-#include "libqhull.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-/*-<a href="qh-user.htm#TOC"
- >-------------------------------</a><a name="qh_fprintf">-</a>
-
- qh_fprintf(fp, msgcode, format, list of args )
- print arguments to *fp according to format
- Use qh_fprintf_rbox() for rboxlib.c
-
- notes:
- same as fprintf()
- fgets() is not trapped like fprintf()
- exit qh_fprintf via qh_errexit()
-*/
-
-void qh_fprintf(FILE *fp, int msgcode, const char *fmt, ... ) {
- va_list args;
-
- if (!fp) {
- fprintf(stderr, "QH6232 Qhull internal error (userprintf.c): fp is 0. Wrong qh_fprintf called.\n");
- qh_errexit(6232, NULL, NULL);
- }
- va_start(args, fmt);
-#if qh_QHpointer
- if (qh_qh && qh ANNOTATEoutput) {
-#else
- if (qh ANNOTATEoutput) {
-#endif
- fprintf(fp, "[QH%.4d]", msgcode);
- }else if (msgcode >= MSG_ERROR && msgcode < MSG_STDERR ) {
- fprintf(fp, "QH%.4d ", msgcode);
- }
- vfprintf(fp, fmt, args);
- va_end(args);
-
- /* Place debugging traps here. Use with option 'Tn' */
-
-} /* qh_fprintf */
-
diff --git a/PyMca/OmnicMap.py b/PyMca/OmnicMap.py
index 97cc71d..67e958e 100644
--- a/PyMca/OmnicMap.py
+++ b/PyMca/OmnicMap.py
@@ -33,7 +33,7 @@ class OmnicMap(DataObject.DataObject):
It reads the spectra into a DataObject instance.
This class info member contains all the parsed information.
- This calss data member contains the map itself as a 3D array.
+ This class data member contains the map itself as a 3D array.
'''
def __init__(self, filename):
'''
diff --git a/PyMca/PhysicalMemory.py b/PyMca/PhysicalMemory.py
index 57b12d8..b4dc3da 100644
--- a/PyMca/PhysicalMemory.py
+++ b/PyMca/PhysicalMemory.py
@@ -1,82 +1,107 @@
-import sys
-import os
-import ctypes
-import traceback
-
-def loadCLibrary(name="libc.so"):
- try:
- libc = ctypes.CDLL(name)
- except OSError:
- text = traceback.format_exc()
- if "invalid ELF header" in text:
- library = text.split(": ")
- if len(library) > 1:
- libraryFile = library[1]
- if os.path.exists(libraryFile):
- # to read some line
- f = open(libraryFile, 'r')
- for i in range(10):
- line = f.readline()
- if name in line:
- f.close()
- lineSplit = line.split(name)
- libraryFile = lineSplit[0].split()[-1] +\
- name+\
- lineSplit[1].split()[0]
- break
- libraryFile = line[line.index(libraryFile):].split()[0]
- libc = ctypes.CDLL(libraryFile)
- else:
- raise
- return libc
-
-if sys.platform == 'win32':
- class MEMORYSTATUSEX(ctypes.Structure):
- _fields_ = [
- ("dwLength", ctypes.c_ulong),
- ("dwMemoryLoad", ctypes.c_ulong),
- ("ullTotalPhys", ctypes.c_ulonglong),
- ("ullAvailPhys", ctypes.c_ulonglong),
- ("ullTotalPageFile", ctypes.c_ulonglong),
- ("ullAvailPageFile", ctypes.c_ulonglong),
- ("ullTotalVirtual", ctypes.c_ulonglong),
- ("ullAvailVirtual", ctypes.c_ulonglong),
- ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
- ]
-
- def __init__(self):
- # have to initialize this to the size of MEMORYSTATUSEX
- self.dwLength = ctypes.sizeof(self)
- super(MEMORYSTATUSEX, self).__init__()
-
- #print("MemoryLoad: %d%%" % (stat.dwMemoryLoad))
- #print("Physical memory = %d" % stat.ullTotalPhys)
- #print(stat.ullAvailPhys)
- def getPhysicalMemory():
- stat = MEMORYSTATUSEX()
- ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
- return stat.ullTotalPhys
-
-elif sys.platform.startswith('linux'):
- def getPhysicalMemory():
- return os.sysconf('SC_PAGESIZE') * os.sysconf('SC_PHYS_PAGES')
-
-elif sys.platform == 'darwin':
- def getPhysicalMemory():
- libc = loadCLibrary("libc.dylib")
- memsize = ctypes.c_uint64(0)
- length = ctypes.c_size_t(ctypes.sizeof(memsize))
- libc.sysctlbyname("hw.memsize", ctypes.byref(memsize), ctypes.byref(length), None, 0)
- return memsize.value
-else:
- def getPhysicalMemory():
- return None
-
-def getPhysicalMemoryOrNone():
- try:
- return getPhysicalMemory()
- except:
- return None
-
-if __name__ == "__main__":
- print("Physical memory = %d" % getPhysicalMemory())
+#
+# Copyright (C) 2012 V. Armando Sole - ESRF
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+__license__ = "MIT"
+import sys
+import os
+import ctypes
+import traceback
+
+def loadCLibrary(name="libc.so"):
+ try:
+ libc = ctypes.CDLL(name)
+ except OSError:
+ text = traceback.format_exc()
+ if "invalid ELF header" in text:
+ library = text.split(": ")
+ if len(library) > 1:
+ libraryFile = library[1]
+ if os.path.exists(libraryFile):
+ # to read some line
+ f = open(libraryFile, 'r')
+ for i in range(10):
+ line = f.readline()
+ if name in line:
+ f.close()
+ lineSplit = line.split(name)
+ libraryFile = lineSplit[0].split()[-1] +\
+ name+\
+ lineSplit[1].split()[0]
+ break
+ libraryFile = line[line.index(libraryFile):].split()[0]
+ libc = ctypes.CDLL(libraryFile)
+ else:
+ raise
+ return libc
+
+if sys.platform == 'win32':
+ class MEMORYSTATUSEX(ctypes.Structure):
+ _fields_ = [
+ ("dwLength", ctypes.c_ulong),
+ ("dwMemoryLoad", ctypes.c_ulong),
+ ("ullTotalPhys", ctypes.c_ulonglong),
+ ("ullAvailPhys", ctypes.c_ulonglong),
+ ("ullTotalPageFile", ctypes.c_ulonglong),
+ ("ullAvailPageFile", ctypes.c_ulonglong),
+ ("ullTotalVirtual", ctypes.c_ulonglong),
+ ("ullAvailVirtual", ctypes.c_ulonglong),
+ ("sullAvailExtendedVirtual", ctypes.c_ulonglong),
+ ]
+
+ def __init__(self):
+ # have to initialize this to the size of MEMORYSTATUSEX
+ self.dwLength = ctypes.sizeof(self)
+ super(MEMORYSTATUSEX, self).__init__()
+
+ #print("MemoryLoad: %d%%" % (stat.dwMemoryLoad))
+ #print("Physical memory = %d" % stat.ullTotalPhys)
+ #print(stat.ullAvailPhys)
+ def getPhysicalMemory():
+ stat = MEMORYSTATUSEX()
+ ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat))
+ return stat.ullTotalPhys
+
+elif sys.platform.startswith('linux'):
+ def getPhysicalMemory():
+ return os.sysconf('SC_PAGESIZE') * os.sysconf('SC_PHYS_PAGES')
+
+elif sys.platform == 'darwin':
+ def getPhysicalMemory():
+ libc = loadCLibrary("libc.dylib")
+ memsize = ctypes.c_uint64(0)
+ length = ctypes.c_size_t(ctypes.sizeof(memsize))
+ libc.sysctlbyname("hw.memsize", ctypes.byref(memsize), ctypes.byref(length), None, 0)
+ return memsize.value
+else:
+ def getPhysicalMemory():
+ return None
+
+def getPhysicalMemoryOrNone():
+ try:
+ return getPhysicalMemory()
+ except:
+ return None
+
+if __name__ == "__main__":
+ print("Physical memory = %d" % getPhysicalMemory())
diff --git a/PyMca/Plot1D.py b/PyMca/Plot1D.py
index 1371a1d..60e5ec2 100644
--- a/PyMca/Plot1D.py
+++ b/PyMca/Plot1D.py
@@ -20,7 +20,7 @@ __author__ = "V.A. Sole - ESRF Data Analysis"
This module can be used for plugin testing purposes as well as for doing
the bookkeeping of actual plot windows.
-It implements the Plot1D interface:
+It implements the Plot1DBase interface:
addCurve(self, x, y, legend=None, info=None, replace=False, replot=True)
getActiveCurve(self, just_legend=False)
@@ -44,6 +44,18 @@ class Plot1D(Plot1DBase.Plot1DBase):
replot=True):
"""
Add the 1D curve given by x an y to the graph.
+ :param x: The data corresponding to the x axis
+ :type x: list or numpy.ndarray
+ :param y: The data corresponding to the y axis
+ :type y: list or numpy.ndarray
+ :param legend: The legend to be associated to the curve
+ :type legend: string or None
+ :param info: Dictionary of information associated to the curve
+ :type info: dict or None
+ :param replace: Flag to indicate if already existing curves are to be deleted
+ :type replace: boolean default False
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default True
"""
if legend is None:
key = "Unnamed curve 1.1"
@@ -74,6 +86,10 @@ class Plot1D(Plot1DBase.Plot1DBase):
"""
Remove the curve associated to the supplied legend from the graph.
The graph will be updated if replot is true.
+ :param legend: The legend associated to the curve to be deleted
+ :type legend: string or None
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default True
"""
if legend is None:
return
@@ -86,7 +102,11 @@ class Plot1D(Plot1DBase.Plot1DBase):
def getActiveCurve(self, just_legend=False):
"""
- Function to access the currently active curve.
+ :param just_legend: Flag to specify the type of output required
+ :type just_legend: boolean
+ :return: legend of the active curve or list [x, y, legend, info]
+ :rtype: string or list
+ Function to access the graph currently active curve.
It returns None in case of not having an active curve.
Default output has the form:
@@ -109,6 +129,12 @@ class Plot1D(Plot1DBase.Plot1DBase):
def getAllCurves(self, just_legend=False):
"""
+ :param just_legend: Flag to specify the type of output required
+ :type just_legend: boolean
+ :return: legend of the curves or list [[x, y, legend, info], ...]
+ :rtype: list of strings or list of curves
+
+ It returns an empty list in case of not having any curve.
If just_legend is False:
It returns a list of the form:
[[xvalues0, yvalues0, legend0, dict0],
@@ -125,10 +151,13 @@ class Plot1D(Plot1DBase.Plot1DBase):
keys = self.curveDict.keys()
for key in self.curveList:
if key in keys:
- output.append(self.curveDict[key])
+ if just_legend:
+ output.append(key)
+ else:
+ output.append(self.curveDict[key])
return output
- def __getAllLimits(self):
+ def _getAllLimits(self):
keys = self.curveDict.keys()
if not len(keys):
return 0.0, 0.0, 100., 100.
@@ -159,23 +188,36 @@ class Plot1D(Plot1DBase.Plot1DBase):
def getGraphXLimits(self):
"""
- Get the graph X limits.
+ Set the graph X limits.
+ :param xmin: minimum value of the axis
+ :type xmin: float
+ :param xmax: minimum value of the axis
+ :type xmax: float
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default False
"""
- xmin, ymin, xmax, ymax = self.__getAllLimits()
+ xmin, ymin, xmax, ymax = self._getAllLimits()
return xmin, xmax
def getGraphYLimits(self):
"""
- Get the graph Y (left) limits.
+ Set the graph Y (left) limits.
+ :param ymin: minimum value of the axis
+ :type ymin: float
+ :param ymax: minimum value of the axis
+ :type ymax: float
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default False
"""
- xmin, ymin, xmax, ymax = self.__getAllLimits()
+ xmin, ymin, xmax, ymax = self._getAllLimits()
return ymin, ymax
def setActiveCurve(self, legend):
"""
- Funtion to request the plot window to set the curve with the specified
- legend as the active curve.
- It returns the active curve legend.
+ Funtion to request the plot window to set the curve with the specified legend
+ as the active curve.
+ :param legend: The legend associated to the curve
+ :type legend: string
"""
key = str(legend)
if key in self.curveDict.keys():
@@ -185,7 +227,6 @@ class Plot1D(Plot1DBase.Plot1DBase):
def main():
import numpy
-
x = numpy.arange(100.)
y = x * x
plot = Plot1D()
diff --git a/PyMca/Plot1DBase.py b/PyMca/Plot1DBase.py
index c7a001a..79885aa 100644
--- a/PyMca/Plot1DBase.py
+++ b/PyMca/Plot1DBase.py
@@ -16,7 +16,8 @@
#
#############################################################################*/
__author__ = "V.A. Sole - ESRF Software Group"
-"""
+__license__ = "LGPL"
+__doc__ = """
Any window willing to accept 1D plugins should implement the methods defined
in this class.
@@ -26,8 +27,11 @@ The plugins will be compatible with any 1D-plot window that provides the methods
removeCurve
getActiveCurve
getAllCurves
+ setGraphTitle
getGraphXLimits
getGraphYLimits
+ setGraphXLimits
+ setGraphYLimits
setActiveCurve
On instantiation, this clase imports all the plugins found in the PyMcaPlugins
@@ -63,6 +67,10 @@ class Plot1DBase(object):
self.getPlugins()
def setPluginDirectoryList(self, dirlist):
+ """
+ :param dirlist: Set directories to search for Plot1D plugins
+ :type dirlist: list
+ """
for directory in dirlist:
if not os.path.exists(directory):
raise IOError("Directory:\n%s\ndoes not exist." % directory)
@@ -70,12 +78,15 @@ class Plot1DBase(object):
self.__pluginDirList = dirlist
def getPluginDirectoryList(self):
+ """
+ :return dirlist: List of directories to search for Plot1D plugins
+ """
return self.__pluginDirList
def getPlugins(self):
"""
Import or reloads all the available plugins.
- It returns the number of plugins loaded.
+ :return: The number of plugins loaded.
"""
if self.__pluginDirList == []:
self.__pluginDirList = [PLUGINS_DIR]
@@ -137,6 +148,18 @@ class Plot1DBase(object):
def addCurve(self, x, y, legend=None, info=None, replace=False, replot=True):
"""
Add the 1D curve given by x an y to the graph.
+ :param x: The data corresponding to the x axis
+ :type x: list or numpy.ndarray
+ :param y: The data corresponding to the y axis
+ :type y: list or numpy.ndarray
+ :param legend: The legend to be associated to the curve
+ :type legend: string or None
+ :param info: Dictionary of information associated to the curve
+ :type info: dict or None
+ :param replace: Flag to indicate if already existing curves are to be deleted
+ :type replace: boolean default False
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default True
"""
print("addCurve not implemented")
return None
@@ -145,13 +168,21 @@ class Plot1DBase(object):
"""
Remove the curve associated to the supplied legend from the graph.
The graph will be updated if replot is true.
+ :param legend: The legend associated to the curve to be deleted
+ :type legend: string or None
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default True
"""
print("removeCurve not implemented")
return None
def getActiveCurve(self, just_legend=False):
"""
- Function to access the currently active curve.
+ :param just_legend: Flag to specify the type of output required
+ :type just_legend: boolean
+ :return: legend of the active curve or list [x, y, legend, info]
+ :rtype: string or list
+ Function to access the graph currently active curve.
It returns None in case of not having an active curve.
Default output has the form:
@@ -168,6 +199,12 @@ class Plot1DBase(object):
def getAllCurves(self, just_legend=False):
"""
+ :param just_legend: Flag to specify the type of output required
+ :type just_legend: boolean
+ :return: legend of the curves or list [[x, y, legend, info], ...]
+ :rtype: list of strings or list of curves
+
+ It returns an empty list in case of not having any curve.
If just_legend is False:
It returns a list of the form:
[[xvalues0, yvalues0, legend0, dict0],
@@ -185,7 +222,8 @@ class Plot1DBase(object):
def getGraphXLimits(self):
"""
- Get the graph X limits.
+ :return: Two floats with the X axis limits
+ Get the graph X limits.
"""
print("getGraphXLimits not implemented")
return 0.0, 100.0
@@ -193,35 +231,88 @@ class Plot1DBase(object):
def getGraphYLimits(self):
"""
Get the graph Y (left) limits.
+ :return: Two floats with the Y (left) axis limits
"""
print("getGraphYLimits not implemented")
return 0.0, 100.0
+ def setGraphXLimits(self, xmin, xmax, replot=False):
+ """
+ Set the graph X limits.
+ :param xmin: minimum value of the axis
+ :type xmin: float
+ :param xmax: minimum value of the axis
+ :type xmax: float
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default False
+ """
+ print("setGraphXLimits not implemented")
+ return
+
+ def getGraphYLimits(self, ymin, ymax, replot=False):
+ """
+ Set the graph Y (left) limits.
+ :param ymin: minimum value of the axis
+ :type ymin: float
+ :param ymax: minimum value of the axis
+ :type ymax: float
+ :param replot: Flag to indicate plot is to be immediately updated
+ :type replot: boolean default False
+ """
+ print("setGraphYLimits not implemented")
+ return
+
def setActiveCurve(self, legend):
"""
Funtion to request the plot window to set the curve with the specified legend
as the active curve.
+ :param legend: The legend associated to the curve
+ :type legend: string
"""
print("setActiveCurve not implemented")
return None
def setGraphTitle(self, title):
+ """
+ :param title: The title to be set
+ :type title: string
+ """
print("setGraphTitle not implemented")
def setGraphXTitle(self, title):
+ """
+ :param title: The title to be associated to the X axis
+ :type title: string
+ """
print("setGraphXTitle not implemented")
def setGraphYTitle(self, title):
+ """
+ :param title: The title to be associated to the X axis
+ :type title: string
+ """
print("setGraphYTitle not implemented")
+
def getGraphTitle(self):
+ """
+ :return: The graph title
+ :rtype: string
+ """
print("getGraphTitle not implemented")
return "Title"
def getGraphXTitle(self):
+ """
+ :return: The graph X axis label
+ :rtype: string
+ """
print("getGraphXTitle not implemented")
return "X"
def getGraphYTitle(self):
- print("getGraphYTitle not implemented")
+ """
+ :return: The graph Y axis label
+ :rtype: string
+ """
return "Y"
diff --git a/PyMca/PyMcaData/HTML/AdvancedAlignmentScanPlugin.html b/PyMca/PyMcaData/HTML/AdvancedAlignmentScanPlugin.html
new file mode 100644
index 0000000..40c4d44
--- /dev/null
+++ b/PyMca/PyMcaData/HTML/AdvancedAlignmentScanPlugin.html
@@ -0,0 +1,246 @@
+<html>
+<head>
+ <style type="text/css">
+ body {
+ background-color:white;
+ width:400px
+ }
+ th, tr, td {
+ text-align:left;
+ vertical-align:bottom;
+ border: 2px solid #CCCCCC;
+ border-style:solid;
+ }
+ table {
+ font-family:"Monospace";
+ font-size:75%;
+ border: 2px solid grey;
+ border-collapse:collapse;
+ width:390px;
+ margin-left:0px;
+ margin-right:0px;
+ margin-top:10px;
+ margin-bottom:10px;
+ }
+ div.indent {
+ color:#333333;
+ text-align:justify;
+ margin-left:20px;
+ margin-right:20px;
+ margin-top:20px;
+ margin-bottom:20px;
+ }
+ div.main {
+ text-align:justify;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:5px;
+ margin-bottom:20px;
+ }
+ div.elem {
+ text-align:left;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:5px;
+ margin-bottom:5px;
+ }
+ div.code {
+ color:#333333;
+ background:#EEEEEE;
+ text-align:left;
+ margin-left:20px;
+ margin-right:20px;
+ margin-top:20px;
+ margin-bottom:20px;
+ }
+ div.highlight {
+ background: #f8f8f8;
+ font-size:80%;
+ }
+ div.highlight .hll { background-color: #ffffcc }
+ div.highlight .c { color: #408080; font-style: italic } /* Comment */
+ div.highlight .err { border: 1px solid #FF0000 } /* Error */
+ div.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+ div.highlight .o { color: #666666 } /* Operator */
+ div.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+ div.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
+ div.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
+ div.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
+ div.highlight .gd { color: #A00000 } /* Generic.Deleted */
+ div.highlight .ge { font-style: italic } /* Generic.Emph */
+ div.highlight .gr { color: #FF0000 } /* Generic.Error */
+ div.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+ div.highlight .gi { color: #00A000 } /* Generic.Inserted */
+ div.highlight .go { color: #808080 } /* Generic.Output */
+ div.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+ div.highlight .gs { font-weight: bold } /* Generic.Strong */
+ div.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+ div.highlight .gt { color: #0040D0 } /* Generic.Traceback */
+ div.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+ div.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+ div.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+ div.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+ div.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+ div.highlight .kt { color: #B00040 } /* Keyword.Type */
+ div.highlight .m { color: #666666 } /* Literal.Number */
+ div.highlight .s { color: #BA2121 } /* Literal.String */
+ div.highlight .na { color: #7D9029 } /* Name.Attribute */
+ div.highlight .nb { color: #008000 } /* Name.Builtin */
+ div.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+ div.highlight .no { color: #880000 } /* Name.Constant */
+ div.highlight .nd { color: #AA22FF } /* Name.Decorator */
+ div.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+ div.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+ div.highlight .nf { color: #0000FF } /* Name.Function */
+ div.highlight .nl { color: #A0A000 } /* Name.Label */
+ div.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+ div.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+ div.highlight .nv { color: #19177C } /* Name.Variable */
+ div.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+ div.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+ div.highlight .mf { color: #666666 } /* Literal.Number.Float */
+ div.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+ div.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+ div.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+ div.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+ div.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+ div.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+ div.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+ div.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+ div.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+ div.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+ div.highlight .sx { color: #008000 } /* Literal.String.Other */
+ div.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+ div.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+ div.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+ div.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+ div.highlight .vc { color: #19177C } /* Name.Variable.Class */
+ div.highlight .vg { color: #19177C } /* Name.Variable.Global */
+ div.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+ div.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
+ </style>
+</head>
+
+<body TEXT=#000000 BGCOLOR=#FFFFFF ALINK=#ff6600 LINK=#0000cc VLINK=#0000cc
+marginwidth=10 marginheight=10 topmargin=10 leftmargin=10>
+
+<a NAME=Up></a>
+<H3>Alignment plug-in Documentation</H3>
+
+<H4>
+Contents
+</H4>
+<br>
+<a href=#Description>1. Usage and Description</a><br>
+<a href=#Methods>2. Methods used by the plug-in</a><br>
+<br>
+
+<H4>
+Synopsis
+</H4>
+
+Due to uncertainties in the experimental set-up, recorded data might be shifted unrelated
+to physical effects probed in the experiment. The present plug-in calculates this shift and
+corrects the data using a variety of different methods.
+
+<H3><a NAME=Description>
+1. Usage and Description
+</a></H3>
+
+<div class='main'>
+Data that is subject to a shift must be loaded into the plot window of the main application.
+The plug-in offers two ways to treat the data: a shortcut options called 'Perform FFT Shift'
+calculates the shift and directly corrects the data and the 'Show Alignment Window' option
+showing a window that allows for specification of the shift and alignment methods as well as
+offering the possibility to safe calculated shifts respectively load previously calculated
+shifts from a file. It is also possible to enter shift values by hand.</br>
+</br>
+Once the Alignment Window is opened, the alignment method and the shift method must be specified.
+The alignment method specifies how the shift is calculated while the shift method determines
+how the shift is applied to the data.</br>
+</br>
+The table shows three columns: The first one shows the plot legend of the data that will be
+corrected by the shift method. The second column shows the plot legend from which the shift
+is calculated. The third column shows the shift values calculated by the alignment method in
+units of the plot windows x-axis. While columns one and two can not be edited, shift values
+can be entered by hand. Another way of setting the shift values is to load them from a existing
+*.shift file using the Load button.</br>
+</br>
+Once the shift values are set, they can either be directly applied to the data present in the
+plot window using the Apply button or the data can be stored in memory. The latter options allow
+to use a reference signal recorded during the experiment to determine the shift and then apply
+the shift values to a different set of data.</br>
+</br>
+Notice: In order to match different sets of data to another, as necessary in the case of a
+reference signal, the order in which the data is added to the plot window is crucial. If one
+switches between two sets of data where one set aligns the other one it is highly encouraged
+to consult the table in the Alignment window to check if every element in the two different
+sets of data is assigned to its correct counterpart before applying the shift.</br>
+</br>
+If the data in the plot window is zoomed in to a distinct feature, only of the data is used to
+calculate the shift.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H3><a NAME=Methods>
+1. Usage and Description
+</a></H3>
+
+<div class='main'>
+Alignment methods are used to calculate the shift. Present methods include FFT, MAX, FIT and
+FIT DRV.
+</div>
+
+<div class=elem><i>FFT</i></div>
+ <div class='indent'>
+ Uses the Fourier Transform of the curves to calculated their cross-correlation. The maximum
+ of the correlation is determined and yields the shift value. This method is the default option,
+ since it is not affected by the peak shape, fast and numerically robust. Notice: the shifts
+ are given in real space values.
+ </div>
+
+<div class=elem><i>MAX</i></div>
+ <div class='indent'>
+ Determines the maximum of each curve, the shift is given by its the differences in the x-position
+ of the maxima. Notice that this method is highly vulnerable to noise in the data and spikes.
+ </div>
+
+<div class=elem><i>FIT</i></div>
+ <div class='indent'>
+ Method subtracts a background from the data using the SNIP algorithm (c.f. plug-in section,
+ Background subtraction tools) and searches for peaks in the data. For every curve, the single
+ most pronounced feature is selected. The peak is fitted by a Gaussian model, the shifts are then
+ given by differences in the x-offsets of the fitted Gaussians.
+ </div>
+
+<div class=elem><i>FIT</i></div>
+ <div class='indent'>
+ Uses the same procedure as the FIT method, however the fit is applied to the first derivative of
+ the data. This method only recommended for X-ray absorption data.
+ </div>
+
+<div class='main'>
+Shift methods are used to apply the calculated shift to the data. Present methods include 'Shift x-range'
+and 'Inverse FFT shift'.
+</div>
+
+<div class=elem><i>Shift x-range</i></div>
+ <div class='indent'>
+ This method takes the x-range of the respective curve and adds the calculated shift value to every
+ point.
+ </div>
+
+<div class=elem><i>Inverse FFT shift</i></div>
+ <div class='indent'>
+ Takes the Fourier Transform of a curve and multiplies the shift as a phase factor. The multiplication
+ of a phase factor in Fourier space translates to a shift in the x-range in real space. The shifted data
+ is given by the inverse Fourier transform.
+
+ Notice: In the process, the data needs to have a equidistant x-range. If this is not the case, the data
+ will be interpolated on a equidistant x-range. Due to the cyclic nature of the Fourier transform, this
+ method is recommended for data that has linear background.
+ </div>
+
+<br><a href=#Up>up</a>
+</body>
diff --git a/PyMca/PyMcaData/HTML/XMCDInfotext.html b/PyMca/PyMcaData/HTML/XMCDInfotext.html
new file mode 100644
index 0000000..7602cfc
--- /dev/null
+++ b/PyMca/PyMcaData/HTML/XMCDInfotext.html
@@ -0,0 +1,702 @@
+<html>
+<head>
+ <style type="text/css">
+ body {
+ background-color:white;
+ width:400px
+ }
+ th, tr, td {
+ text-align:left;
+ vertical-align:bottom;
+ border: 2px solid #CCCCCC;
+ border-style:solid;
+ }
+ table {
+ font-family:"Monospace";
+ font-size:75%;
+ border: 2px solid grey;
+ border-collapse:collapse;
+ width:390px;
+ margin-left:0px;
+ margin-right:0px;
+ margin-top:10px;
+ margin-bottom:10px;
+ }
+ div.indent {
+ color:#333333;
+ text-align:justify;
+ margin-left:20px;
+ margin-right:20px;
+ margin-top:20px;
+ margin-bottom:20px;
+ }
+ div.main {
+ text-align:justify;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:5px;
+ margin-bottom:20px;
+ }
+ div.elem {
+ text-align:left;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:5px;
+ margin-bottom:5px;
+ }
+ div.code {
+ color:#333333;
+ background:#EEEEEE;
+ text-align:left;
+ margin-left:20px;
+ margin-right:20px;
+ margin-top:20px;
+ margin-bottom:20px;
+ }
+ div.highlight {
+ background: #f8f8f8;
+ font-size:80%;
+ }
+ div.highlight .hll { background-color: #ffffcc }
+ div.highlight .c { color: #408080; font-style: italic } /* Comment */
+ div.highlight .err { border: 1px solid #FF0000 } /* Error */
+ div.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+ div.highlight .o { color: #666666 } /* Operator */
+ div.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+ div.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
+ div.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
+ div.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
+ div.highlight .gd { color: #A00000 } /* Generic.Deleted */
+ div.highlight .ge { font-style: italic } /* Generic.Emph */
+ div.highlight .gr { color: #FF0000 } /* Generic.Error */
+ div.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+ div.highlight .gi { color: #00A000 } /* Generic.Inserted */
+ div.highlight .go { color: #808080 } /* Generic.Output */
+ div.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+ div.highlight .gs { font-weight: bold } /* Generic.Strong */
+ div.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+ div.highlight .gt { color: #0040D0 } /* Generic.Traceback */
+ div.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+ div.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+ div.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+ div.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+ div.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+ div.highlight .kt { color: #B00040 } /* Keyword.Type */
+ div.highlight .m { color: #666666 } /* Literal.Number */
+ div.highlight .s { color: #BA2121 } /* Literal.String */
+ div.highlight .na { color: #7D9029 } /* Name.Attribute */
+ div.highlight .nb { color: #008000 } /* Name.Builtin */
+ div.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+ div.highlight .no { color: #880000 } /* Name.Constant */
+ div.highlight .nd { color: #AA22FF } /* Name.Decorator */
+ div.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+ div.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+ div.highlight .nf { color: #0000FF } /* Name.Function */
+ div.highlight .nl { color: #A0A000 } /* Name.Label */
+ div.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+ div.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+ div.highlight .nv { color: #19177C } /* Name.Variable */
+ div.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+ div.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+ div.highlight .mf { color: #666666 } /* Literal.Number.Float */
+ div.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+ div.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+ div.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+ div.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+ div.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+ div.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+ div.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+ div.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+ div.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+ div.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+ div.highlight .sx { color: #008000 } /* Literal.String.Other */
+ div.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+ div.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+ div.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+ div.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+ div.highlight .vc { color: #19177C } /* Name.Variable.Class */
+ div.highlight .vg { color: #19177C } /* Name.Variable.Global */
+ div.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+ div.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
+ </style>
+</head>
+
+<body TEXT=#000000 BGCOLOR=#FFFFFF ALINK=#ff6600 LINK=#0000cc VLINK=#0000cc
+marginwidth=10 marginheight=10 topmargin=10 leftmargin=10>
+
+<a NAME=Up></a>
+<H3>XLD/XMCD Analysis HOWTO</H3>
+
+<H4>
+Contents
+</H4>
+<br>
+<a href=#Usage>1. Usage</a><br>
+<a href=#Description>2. Description</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#Toprow>2.1 Top row</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#OptionsWindow>2.2 Options window</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=#OptionsWindowNorm>2.2.1 Normalization</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=#OptionsWindowInterp>2.2.2 Interpolation</a><br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=#OptionsWindowMotors>2.2.3 Motor selection</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#Table>2.3 Table</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#AnalysisWindow>2.4 Analysis window</a><br>
+<a href=#EditAutoAssign>3. Extend the automatic assignment</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#EditExpDict>3.1 Edit the experiments dictionary</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#EditComboBox>3.2 Edit the drop down menu</a><br>
+&nbsp;&nbsp;&nbsp;<a href=#EditSelectExp>3.3 Edit the selectExperiment function</a><br>
+<br>
+
+<H4>
+Synopsis
+</H4>
+
+<div class='main'>
+Xray linear dichorism (XLD) and Xray magnetic circular dichorism (XMCD)
+measurements as performed at Beamlines ID08 and ID12 of the ESRF
+probe the sample with x-rays of two different polarizations. From two spectra
+with different polarizations, one calculates the difference spectrum (the
+XLD/XMCD spectrum) as well as the average spectrum (XAS spectrum). The present
+plug-in aims to ease the evaluation process.<br>
+<br>
+To assign the recorded spectra into two groups (labeled 'A' and 'B') depending
+on their polarization, the plug-in displays meta data obtained from the spec file
+and provides methods to automate the assignment process. A separate plot
+window allows a preview on calculated XLD/XMCD spectra. Several options relevant
+to the treatment of the data can be specified and saved. The results of an analysis
+can be exported into spec-files.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H3><a NAME=Usage>
+1. Usage
+</a></H3>
+
+<div class='main'>
+From the open spec-File, select the relevant scans in the scan selection window
+on the left side of your PyMca session. Assign the relevant counters to the
+respective axes and load the scans in the plot window on the right. Load the plug-in
+from the plug-in menu (gearbox item in the top row of the plot window).
+Notice that if one selects a section of the data by zooming in before starting the
+plug-in, only the data within that energy range is used for the analysis.<br>
+<br>
+The selected spectra now appears in the table of the plug-in.
+Per default, the spectra remain unassigned as indicated by the drop down menu showing
+the entry 'Generic dichorism'. Either one selects an existing experiment from the
+drop down menu (which also provides automatic division of spectra into groups) or does all
+settings by hand using the options menu. The options menu also allows to determine
+if and when a normalization is applied to the spectra and the specifics of the interpolation
+carried out during the calculation.<br>
+If all necessary information is displayed in the table, the assignment of spectra to
+either group 'A' or 'B' can be done by right-clicking on the table. A context menu appears
+offering several ways to assign a selected spectrum a group.<br>
+<br>
+Once a selection is made, the result of calculations is displayed immediately in the analysis window.
+An average is calculated on the spectra that belong to groups 'A' and 'B' (curves labeled
+avg_A resp. avg_B). The difference spectrum (curve labeled XMCD) is calculated as Avg(B)- Avg(A).
+The XAS spectrum is calculated as the average of both groups: (Avg(A) + Avg(B))/2<br>
+The finished analysis can be saved in a spec file using the Save Button in the top button row
+of the analysis window.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H3><a NAME=Description>
+2. Description
+</a></H3>
+
+<div class='main'>
+The plug-in consists of four elements: the top row of buttons, the table
+listing the spectra and the analysis window. Another important element is the options
+window.
+</div>
+
+<H4><a NAME=Toprow>
+2.1 Top row
+</a></H4>
+
+<div class='main'>
+The top row contains the following buttons in order from left to right: the Update
+Button, the Options Button and the Experiment Selection.
+</div>
+
+<div class=elem><i>Update Button</i></div>
+ <div class='indent'>
+ Loads plots from the main window of the PyMca session into the plug-in. Notice:
+ If the plot window of the main application is zoomed in or out, only the data
+ within the zoomed in energy range is considered for analysis. After zooming in
+ or out in the main application, the spectra in the plug-in should be updated.
+ </div>
+
+<div class=elem><i>Options Button</i></div>
+ <div class='indent'>
+ Allows to specify the plug-in behavior during the analysis. For information in
+ can be found in <a href=#OptionsWindow>section 2.2</a>.
+ </div>
+
+<div class='elem'><i>Experiment Selection:</i></div>
+ <div class='indent'>
+ The options for the experiments carried out at beamlines ID08 and ID12 are
+ embedded in the plug-in. Selecting one of the experiments sets these options
+ and divides the spectra automatically into groups 'A' and 'B'.
+ A new experimental configuration can be added using the 'Add new configuration'
+ option. A window will open and ask the user to name the configuration.
+ Once accepted, an option window is opened and can be used to define the experimental
+ configuration. This can be done by either loading an existing configuration
+ or by specifying it by hand.
+ The new experimental configuration can now be selected in the drop down menu and
+ remains there until the end of the PyMca session. It sets all options as specified,
+ however the spectra assignment into groups has still to be done by hand.
+ </div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=OptionsWindow>
+2.2 Options Window
+</a></H4>
+
+<div class='main'>
+With the Options Window, the user can control the details of the analysis and
+determine the information shown in the table. A configuration made in the Options
+Window can be saved and an existing configuration can be loaded. Notice that once
+the 'OK' button is clicked, the analysis is immediately recalculated.<br>
+<br>
+The saved options are stored in a config file. If the result of a XLD/XMCD
+analysis is saved a spec file, the current configuration is automatically
+saved in a separate file.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=OptionsWindowNorm>
+2.2.1 Normalization
+</a></H4>
+
+<div class='main'>
+One can select if and when a normalization is applied, the normalization method can
+be specified. Either no normalization is applied at all or it is applied before
+performing the averages over groups 'A' and 'B'. The third option is to perform
+the normalization after averaging over both groups.<br>
+<br>
+The following table explains the various normalization methods in detail.
+</div>
+
+<table border="1">
+ <colgroup>
+ <col span="1" style="width: 45%;">
+ <col span="1" style="width: 55%;">
+ </colgroup>
+ <tr>
+ <th text-align='left'>Option</th>
+ <th>Explanation</th>
+ </tr>
+ <tr>
+ <td>(y-min(y))<br>/trapz(max(y)-min(y),x)</td>
+ <td>
+ Default selection. Subtracts the minimum value as offset from the spectrum
+ and normalizes it to its integral
+ </td>
+ </tr>
+ <tr>
+ <td>y/max(y)</td>
+ <td>
+ Normalizes the curve to its maximum value
+ </td>
+ </tr>
+ <tr>
+ <td>(y-min(y))<br>/(max(y)-min(y))</td>
+ <td>
+ Subtracts the minimum value as offset from the spectrum and normalizes to the
+ resulting maximum, effectively putting all spectral values between zero and one
+ </td>
+ </tr>
+ <tr>
+ <td>(y-min(y))<br>/sum(max(y)-min(y))</td>
+ <td>
+ Similar to the default options, but uses the summation over all spectral values
+ instead of the integral
+ </td>
+ </tr>
+</table>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=OptionsWindowInterp>
+2.2.2 Interpolation
+</a></H4>
+
+<div class='main'>
+The plug-in performs an interpolation of the spectra selected to be used in the analysis
+before calculation averages and differences. In the "Interpolation x-range" section the
+user can select, which energy range is used for interpolation. To guarantee numerical
+stability of the interpolation, the spectra are cleaned up before being copied from
+the main application to the plug-in.
+The clean up process consists of sorting the data with respect to the energy (i.e. x)
+range as well as removing energies that have been measured twice.<br>
+<br>
+One can chose between selecting one of the energy ranges that actually have been measured or
+let the plug-in determine a equidistant energy range, which might be beneficial for further
+analysis such as Savitzky-Golay smoothing. Options that conserve at least one measured
+energy range are 'First curve in sequence' or 'Active curve' (i.e. taking the active curve in
+the plot window of the main application).
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=OptionsWindowMotors>
+2.2.3 Motor Selection
+</a></H4>
+
+<div class='main'>
+The drop down menus allow to select the motors positions to be shown in the plug-in
+table. Notice that all motors in the drop down menu are not hard coded in the plug-in
+but are obtained dynamically from meta data in the spec file. Motor names are treated
+case sensitive by the plug-in.
+</div>
+
+
+<div class='elem'><i>Motors for ID08 are:</i></div>
+<div class='indent'>
+phaseD, PhaseD, oxPS, magnet
+</div>
+
+<div class='elem'><i>Motors for ID12 are:</i></div>
+<div class='indent'>
+Phase, PhaseA, BRUKER, CRYO, OXFORD
+</div>
+
+<div class='main'>
+Notice that ID12 also uses different counters to differ between polarizations.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=Table>
+2.3 Table
+</a></H4>
+
+<div class='main'>
+The table, positioned beneath the top row, shows the spectra that are included
+in the XLD/XMCD analysis. The table shows the group to which a curve is assigned,
+the curves' legend, the scan number and the counter of a spectrum. The
+remaining columns display settings of various physical or virtual motors that were
+recorded during the course of the measurement and stored in the meta data of the
+spec file.
+Every column of the table can be used to sort it with respect to the values in this
+column by double clicking the right top corner of the respective header section.<br>
+<br>
+Right click on the table provides the user with a context menu with the following
+options:
+</div>
+
+<div class='elem'><i>Perform Analysis</i></div>
+ <div class='indent'>
+ Although most calculation is triggered automatically upon selection of a set
+ of scans, selecting this option forces the plug-in to recalculate the XLD/XMCD spectrum.
+ </div>
+
+<div class='elem'><i>Set as A</i> resp. <i>Set as B</i></div>
+ <div class='indent'>
+ Assigns a scan selected in the table to the respective group and triggers a
+ recalculation of the XLD/XMCD Analysis.
+ </div>
+
+<div class='elem'><i>Enter sequence</i></div>
+ <div class='indent'>
+ Opens a window and allows to enter a sequence of letters ('A', 'B', 'D'). The
+ spectra in the table are sorted after their scan number and assigned into
+ groups 'A' and 'B' based on the sequence, 'D' leaves a spectrum unselected.
+ If no scan number is present, the spectra remain unsorted.
+ The length of the sequence does not need to match the number of spectra. If the
+ length of the sequence is smaller than the number of spectra, the plug-in assumes
+ the entered sequence as a pattern and repeats it.
+ </div>
+
+<div class='elem'><i>Remove selection</i></div>
+ <div class='indent'>
+ Removes a scan from the selection, effectively setting its group to 'D'
+ </div>
+
+<div class='elem'><i>Invert selection</i></div>
+ <div class='indent'>
+ Selects scans in the table that are not selected yet and deselects the selected
+ scans.
+ </div>
+
+<div class='elem'><i>Remove curves</i></div>
+ <div class='indent'>
+ Removes curves from the table and the plot window in the main application.
+ </div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=AnalysisWindow>
+2.4 Analysis Window
+</a></H4>
+
+<div class='main'>
+The analysis window beneath the table shows the result of the XLD/XMCD analysis. Four
+curves are displayed: the arithmetic averages over groups A and B, the XAS spectrum
+(an arithmetic average over the averages of groups A and B) and the difference spectrum
+(group B - group A) called the XMCD spectrum.<br>
+<br>
+Notice that the XMCD spectrum usually is not in the same order of magnitude as the average
+spectra and the XAS spectrum. Thus, the XMCD spectrum is plotted to the secondary y axis
+on the right. In order to hide individual spectra, one can right-click on the legend and
+select 'Hide curve'.<br>
+<br>
+In the analysis window behaves exactly like the plot window of the main application. The
+plot can be zoomed and the spectra can be manipulated using the usual tools of PyMca. Only
+the save routine has been modified to the specific demands of XLD/XMCD analysis.
+</div>
+
+<div class='elem'><i>Save routine</i></div>
+ <div class='indent'>
+ The save icon in the analysis window allows the users to save all results of the XLD/XMCD
+ analysis at once in a single spec file. The data is divided into multiple columns. The
+ first column contains the energy range over which the analysis is carried out, followed
+ by the averages over groups 'A' and 'B'. The last two columns are occupied by the XLD/XMCD
+ spectra.<br>
+ The save dialog also allows to enter a comment that will be written in the spec file.
+ If multiple datasets are analyzed consecutively, the results can be still saved in a single
+ spec file by selecting the 'Append to existing file' option. Every individual scan is saved
+ in a separate file, too. Therefore, the original file name is extended by an underscore and
+ the number of scans already present in the file to which the analysis is appended to.<br>
+ Along with the data, the configuration from the options menu is also saved under the same
+ file name, but with the extension 'cfg'.
+ </div>
+
+<div class='elem'>Buttons <i>Add, Add all, Replace </i>and<i> Replace All</i></div>
+ <div class='indent'>
+ Allow to push the resulting spectra from the plug-in window to the plot window of the main
+ application. While 'Add' and 'Replace' only affect the active curve in the plug-in plot
+ window, 'Add all' and 'Replace all' copy all curves from the analysis to the main application.
+ Notice: If one plans to compare two or more analyzed spectra by consecutively pushing them
+ to the main window, the spectra should be renamed beforehand. The name for each analyzed
+ spectrum remains the same (avg_A, avg_B, XMCD, XAS) and moving spectra of the same name
+ to the plot window in the main application just replaces them there.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=EditAutoAssign>
+3. Extend the automatic assignment
+</a></H4>
+
+<div class='main'>
+The scope of this paragraph is to explain the additions to the source code necessary to make to
+define a new experiment. The paragraph assumes entry level knowledge of the Python programming
+language.<br>
+<br>
+Data measured on beamline ID08 or ID12 of the ESRF can automatically be assigned to one of groups 'A'
+or 'B', as long as it is saved in spec files. By selecting one of the experiments from the drop down
+menu in the top row, the XLD/XMCD plug-in sets the motors resp. counters controlling the polarization
+in the options menu. This displays the respective values in the plug-ins table. To achieve the
+automatic assignment, the plug-in reads the displayed values and guesses the affiliation of a
+spectrum based on a set of rules.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=EditExpDict>
+3.1 Edit the experiments dictionary
+</a></H4>
+
+<div class='main'>
+The experiments dictionary contains the settings specific to an experiments. The options concern
+the normalization settings and method, the interpolation settings and most importantly the motors
+on which the assignment depends.<br>
+<br>
+The following code fragment shows the exemplary entry 'Generic Dichorism' in the experiments
+dictionary.
+</div>
+
+<div class="highlight"><pre><span class="bp">self</span><span class="o">.</span><span class="n">experimentsDict</span> <span class="o">=</span> <span class="p">{</span>
+ <span class="s">&#39;Generic Dichorism&#39;</span><span class="p">:</span> <span class="p">{</span>
+ <span class="s">&#39;xrange&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
+ <span class="s">&#39;normalization&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
+ <span class="s">&#39;normalizationMethod&#39;</span><span class="p">:</span> <span class="s">&#39;offsetAndArea&#39;</span><span class="p">,</span>
+ <span class="s">&#39;motor0&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span><span class="p">,</span>
+ <span class="s">&#39;motor1&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span><span class="p">,</span>
+ <span class="s">&#39;motor2&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span><span class="p">,</span>
+ <span class="s">&#39;motor3&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span><span class="p">,</span>
+ <span class="s">&#39;motor4&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</span>
+ <span class="p">},</span>
+ <span class="p">...</span>
+<span class="p">}</span>
+</div>
+
+<div class='main'>
+Notice that every experiment is represented by a dictionary itself, with the different options
+as keys and the respective settings as values. Valid values for each option, as well as the
+necessary types are shown in the following table.
+
+<table border="1">
+ <colgroup>
+ <col span="1" style="width: 15%;">
+ <col span="1" style="width: 15%;">
+ <col span="1">
+ </colgroup>
+ <tr>
+ <th text-align='left'>Option</th>
+ <th>Type</th>
+ <th>Values: Explanation</th>
+ </tr>
+ <tr>
+ <td>xrange</td>
+ <td>Int</td>
+ <td>
+ <b>0</b>: First curve in sequence<br>
+ <b>1</b>: Active curve<br>
+ <b>2</b>: Equidistant x-range</td>
+ </tr>
+ <tr>
+ <td>normalization</td>
+ <td>Int</td>
+ <td>
+ <b>0</b>: No normalization<br>
+ <b>1</b>: Normalize after average<br>
+ <b>2</b>: Normalize before average</td>
+ </tr>
+ <tr>
+ <td>normalizationMethod</td>
+ <td>String</td>
+ <td>
+ <b>OffsetAndArea</b>: Subtracts minimum and normalizes to the integral,
+ <b>OffsetAndCounts</b>: Subtracts minimum and normalizes to the sum,
+ <b>OffsetAndMaximum</b>: Subtracts minimum and normalizes to the maximum
+ <b>NormToMaximum</b>: Normalizes to the maximum
+ </td>
+ </tr>
+ </tr>
+ <tr>
+ <td>motor0,<br>motor1,<br>motor2,<br>motor3,<br>motor4</td>
+ <td>String</td>
+ <td>
+ Assumes knowledge of the motor settings in the experimental apparatus.
+ If unsure, consult the Motor Info plug-in or a Beamline Scientist.
+ </td>
+ </tr>
+</table>
+
+Notice that up to five motors can be specified, however no motor must be specified. If a
+motor is not needed, just set the variable to an empty string.
+</div>
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=EditComboBox>
+3.2 Edit the drop down menu
+</a></H4>
+
+<div class='main'>
+Now that a new experiment is present in the experiments dictionary, it can be added into
+the selection of the drop down menu. The drop down menu itself is a QComboBox whose items are
+added using the addItem member function. The explicit code to do so (at least in the initial
+version of this program) looks as follows:
+
+<div class="highlight"><pre><span class="bp">self</span><span class="o">.</span><span class="n">expCBox</span><span class="o">.</span><span class="n">addItems</span><span class="p">(</span>
+ <span class="p">[</span><span class="s">&#39;Generic Dichorism&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID08: XLD 9 Tesla Magnet&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID08: XLD 5 Tesla Magnet&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID08: XMCD 9 Tesla Magnet&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID08: XMCD 5 Tesla Magnet&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID12: XLD (quater wave plate)&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID12: XMCD (Flipper)&#39;</span><span class="p">,</span>
+ <span class="s">&#39;ID12: XMCD&#39;</span><span class="p">,</span>
+ <span class="s">&#39;Add new configuration&#39;</span><span class="p">])</span>
+</pre></div>
+
+It is important, that the registered string is the exact key of the experiment in the experiments
+dictionary. New experiments should be added above the 'Add new configuration' option.
+
+<br><a href=#Up>up</a>
+
+<H4><a NAME=EditSelectExp>
+3.3 Edit the selectExperiment function
+</a></H4>
+
+<div class='main'>
+The selectExperiment function is called every time a item from the drop down menu is selected. In the process,
+the selected option is passed on to the function as a string. Based on this string, the function then sets
+the options as defined in the experiments dictionary. This triggers the table of the plug-in to display the
+information, especially if motors are present in the options.<br>
+<br>
+In a second step, the function reads all values shown in the tables motor columns (that is columns 4 to 8). If
+needed (as in case of two of the ID12 experiments), the counter column (no. 3) might as well be read out.
+The code fragment below shows the updating of the table and the readout.
+</div>
+
+<div class="highlight"><pre><span class="bp">self</span><span class="o">.</span><span class="n">updateTree</span><span class="p">()</span>
+<span class="n">values0</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">getColumn</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">convertType</span><span class="o">=</span><span class="nb">float</span><span class="p">))</span>
+<span class="n">values1</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">getColumn</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">convertType</span><span class="o">=</span><span class="nb">float</span><span class="p">))</span>
+<span class="n">values2</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">getColumn</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="n">convertType</span><span class="o">=</span><span class="nb">float</span><span class="p">))</span>
+<span class="n">values3</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">getColumn</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="n">convertType</span><span class="o">=</span><span class="nb">float</span><span class="p">))</span>
+<span class="n">values4</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">getColumn</span><span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="n">convertType</span><span class="o">=</span><span class="nb">float</span><span class="p">))</span>
+</pre></div>
+
+<div class='main'>
+The table function getColumn returns the entries of a table column as a list while conserving the current order
+of the table rows. The type of the list elements can be specified using the convertType option. The numpy
+Arrays values0 to values4 now contain different motor positions, each values array has the length of the
+number of scans in question<br>
+<br>
+The next section consists of a succession of if/else statements to determine the specific experiment. Within
+such a statement, the values from the table are reduced to a single vector named 'values' that determines
+the affiliation of a spectrum to groups 'A' or 'B'. This array contains numerical values for every spectrum.
+The second step here is to set a pivot element (or threshold value), so that if the value for a spectrum is
+above this value, the spectrum belongs to group 'A' and below to group 'B'. New assignment routines must be
+implemented here as a new elif block.<br>
+<br>
+In case of the XLD experiment of ID08, the decision process is shown in the code fragment below.
+</div>
+
+<div class="highlight"><pre><span class="k">if</span> <span class="n">exp</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;ID08: XLD&#39;</span><span class="p">):</span>
+ <span class="n">values</span> <span class="o">=</span> <span class="n">values0</span>
+ <span class="n">mask</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="n">numpy</span><span class="o">.</span><span class="n">isfinite</span><span class="p">(</span><span class="n">values</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
+ <span class="n">minmax</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">take</span><span class="p">(</span><span class="n">mask</span><span class="p">)</span>
+ <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">minmax</span><span class="p">):</span>
+ <span class="n">vmin</span> <span class="o">=</span> <span class="n">minmax</span><span class="o">.</span><span class="n">min</span><span class="p">()</span>
+ <span class="n">vmax</span> <span class="o">=</span> <span class="n">minmax</span><span class="o">.</span><span class="n">max</span><span class="p">()</span>
+ <span class="n">vpivot</span> <span class="o">=</span> <span class="o">.</span><span class="mi">5</span> <span class="o">*</span> <span class="p">(</span><span class="n">vmax</span> <span class="o">+</span> <span class="n">vmin</span><span class="p">)</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="n">values</span> <span class="o">=</span> <span class="n">numpy</span><span class="o">.</span><span class="n">array</span><span class="p">(</span>
+ <span class="p">[</span><span class="nb">float</span><span class="p">(</span><span class="s">&#39;NaN&#39;</span><span class="p">)]</span><span class="o">*</span><span class="n">numOfSpectra</span><span class="p">)</span>
+</pre></div>
+
+<div class='main'>
+In this case, the motor 'PhaseD' (or 'phaseD', depending on the magnet) determines the polarization on the sample
+and is thus set in the options dictionary. All motor positions are then contained in numpy array 'values0'. Since no
+further calculations are needed, we can directly assign 'values0' to 'values'. The pivot element in this case is
+calculated as the average between maximal and minimal values in 'values'.<br>
+<br>
+The last step of the assignment processes is to loop though the 'values' array and check if the element is
+above or below threshold, as shown in the next code fragement.
+</div>
+
+<div class="highlight"><pre><span class="n">seq</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
+<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
+ <span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">==</span> <span class="s">&#39;nan&#39;</span><span class="p">:</span>
+ <span class="n">seq</span> <span class="o">+=</span> <span class="s">&#39;D&#39;</span>
+ <span class="k">elif</span> <span class="n">x</span><span class="o">&gt;</span><span class="n">vpivot</span><span class="p">:</span>
+ <span class="n">seq</span> <span class="o">+=</span> <span class="s">&#39;A&#39;</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="n">seq</span> <span class="o">+=</span> <span class="s">&#39;B&#39;</span>
+<span class="bp">self</span><span class="o">.</span><span class="n">list</span><span class="o">.</span><span class="n">setSelectionToSequence</span><span class="p">(</span><span class="n">seq</span><span class="p">)</span>
+</pre></div>
+
+<div class='main'>
+Notice that not-a-number float values in the 'values' array are set to the dummy identifier 'D' and thus are ignored in
+the selection. The resulting sequence of this procedure is then passed on to the table function setToSequence, which
+assigns the selection. Once a selection is made, a recalculation is triggered automatically.
+</div>
+
+<br><a href=#Up>up</a>
+
+</body>
+</html>
diff --git a/PyMca/PyMcaIOHelper/PyMcaIOHelper.c b/PyMca/PyMcaIOHelper/PyMcaIOHelper.c
index ad1d772..32681d7 100644
--- a/PyMca/PyMcaIOHelper/PyMcaIOHelper.c
+++ b/PyMca/PyMcaIOHelper/PyMcaIOHelper.c
@@ -1,4 +1,8 @@
#include "Python.h"
+/* adding next line may raise errors ...
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
+
#include <./numpy/arrayobject.h>
#include <stdio.h>
@@ -35,7 +39,7 @@ PyMcaIOHelper_fillSupaVisio(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O|d", &input, &nChannels))
return NULL;
inputArray = (PyArrayObject *)
- PyArray_ContiguousFromObject(input, PyArray_USHORT, 2,2);
+ PyArray_ContiguousFromObject(input, NPY_USHORT, 2,2);
if (inputArray == NULL)
{
struct module_state *st = GETSTATE(self);
@@ -43,17 +47,17 @@ PyMcaIOHelper_fillSupaVisio(PyObject *self, PyObject *args)
return NULL;
}
- dataPointer = (unsigned short *) inputArray->data;
+ dataPointer = (unsigned short *) PyArray_DATA(inputArray);
dataPointer++;
dimensions[1] = *dataPointer++;
dimensions[0] = *dataPointer++;
dimensions[2] = nChannels;
- outputArray = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, PyArray_UINT);
+ outputArray = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, NPY_UINT);
PyArray_FILLWBYTE(outputArray, 0);
/* Do the job */
maxy=maxch=0;
- outputPointer = (unsigned int *) outputArray->data;
- for (i=3; i<inputArray->dimensions[0]; i++)
+ outputPointer = (unsigned int *) PyArray_DATA(outputArray);
+ for (i = 3; i < PyArray_DIMS(inputArray)[0]; i++)
{
y = *dataPointer++;
x = *dataPointer++;
@@ -114,11 +118,11 @@ PyMcaIOHelper_readAifira(PyObject *self, PyObject *args)
dimensions[1] = 128;
dimensions[2] = nChannels;
- outputArray = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, PyArray_UINT);
+ outputArray = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, NPY_UINT);
PyArray_FILLWBYTE(outputArray, 0);
/* Do the job */
- outputPointer = (unsigned int *) outputArray->data;
+ outputPointer = (unsigned int *) PyArray_DATA(outputArray);
while(fscanf(fd, "%2c%c%c", (char *)&channel, &x, &y) == 3)
{
if (channel >= nChannels)
diff --git a/PyMca/PyMcaIOHelper/setup.py b/PyMca/PyMcaIOHelper/setup.py
deleted file mode 100644
index be0db11..0000000
--- a/PyMca/PyMcaIOHelper/setup.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-
-"""Setup script for the PyMcaIOHelper module distribution."""
-
-import os, sys, glob
-try:
- import numpy
-except ImportError:
- text = "You must have numpy installed.\n"
- text += "See http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103\n"
- raise ImportError(text)
-
-from distutils.core import setup
-from distutils.extension import Extension
-
-sources = glob.glob('*.c')
-define_macros = []
-setup (
- name = "PyMcaIOHelper",
- version = "1.0",
- description = "PyMca Input Output helper module",
- author = "V.A. Sole - BLISS Group",
- author_email = "sole@esrf.fr",
- url = "http://www.esrf.fr/computing/bliss/",
-
- # Description of the modules and packages in the distribution
- ext_modules = [
- Extension(
- name = 'PyMcaIOHelper',
- sources = sources,
- define_macros = define_macros,
- libraries = [],
- include_dirs = [numpy.get_include()]
- ),
- ],
-)
diff --git a/PyMca/PyMcaMain.py b/PyMca/PyMcaMain.py
index 5df2c22..5f119d7 100644
--- a/PyMca/PyMcaMain.py
+++ b/PyMca/PyMcaMain.py
@@ -93,7 +93,7 @@ from PyMca.PyMca_Icons import IconDict
from PyMca.PyMca_help import HelpDict
from PyMca import PyMcaDataDir
import os
-__version__ = "4.7.0"
+__version__ = "4.7.1"
if (QTVERSION < '4.0.0') and (sys.platform == 'darwin'):
class SplashScreen(qt.QWidget):
def __init__(self,parent=None,name="SplashScreen",
diff --git a/PyMca/PyMcaPlugins/AdvancedAlignmentScanPlugin.py b/PyMca/PyMcaPlugins/AdvancedAlignmentScanPlugin.py
new file mode 100644
index 0000000..9c05b2b
--- /dev/null
+++ b/PyMca/PyMcaPlugins/AdvancedAlignmentScanPlugin.py
@@ -0,0 +1,1075 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+__author__ = "Tonn Rueter & V.A. Sole - ESRF Data Analysis"
+import numpy
+import sys
+import traceback
+from PyMca import PyMcaQt as qt
+from PyMca import PyMcaDataDir, PyMcaDirs, PyMcaFileDialogs
+from PyMca import ConfigDict
+from PyMca import specfilewrapper as SFW
+from PyMca import SpecfitFunctions as SF
+from PyMca import SNIPModule as snip
+from PyMca.Gefit import LeastSquaresFit as LSF
+from PyMca.SpecfitFuns import gauss
+from PyMca import SpecfitFuns
+from os.path import join as pathjoin
+
+try:
+ from PyMca import Plugin1DBase
+except ImportError:
+ print("WARNING:AlignmentScanPlugin import from somewhere else")
+ from . import Plugin1DBase
+
+DEBUG = 0
+class AlignmentWidget(qt.QDialog):
+
+ _storeCode = 2
+ _colLegend = 0 # Column number of current legends from plot window
+ _colShiftLegend = 1 # Column number of curve from which the shift was calculated
+ _colShift = 2 # Shift
+
+ def __init__(self, parent, ddict, llist, plugin):
+ qt.QDialog.__init__(self, parent)
+ self.setWindowTitle('Alignment Window')
+
+ nCols = 2
+ nRows = len(ddict)
+ self.plugin = plugin
+
+ # Buttons
+ buttonSave = qt.QPushButton('Save')
+ buttonSave.setToolTip('Save shifts to file')
+ buttonLoad = qt.QPushButton('Load')
+ buttonLoad.setToolTip('Load shifts from file')
+ buttonStore = qt.QPushButton('Store')
+ buttonStore.setToolTip('Store shifts in memory.\n')
+ buttonApply = qt.QPushButton('Apply')
+ buttonApply.setToolTip('Apply shift to curves present'
+ +' in the plot window')
+ buttonCancel = qt.QPushButton('Cancel')
+ buttonCalc = qt.QPushButton('Calculate')
+
+ # Table
+ self.shiftTab = qt.QTableWidget(nRows, nCols)
+ self.shiftTab.verticalHeader().hide()
+ self.shiftTab.horizontalHeader().setStretchLastSection(True)
+ self.shiftTab.setHorizontalHeaderLabels(['Legend','Shift'])
+
+ # Shift Method selector
+ self.shiftMethodComboBox = qt.QComboBox()
+ self.shiftMethodComboBox.addItems(
+ ['Shift x-range',
+ 'Inverse FFT shift'])
+ shiftMethodToolTip =\
+ ('Select the method that shifts the spectra\n\n'
+ +'Shift x-range:\n'
+ +' Directly applies the shift to the data\'s\n'
+ +' x-range\n'
+ +'Inverse FFT shift:\n'
+ +' Shifts the spectra by multiplying a\n'
+ +' phase factor to their Fourier transform. The result is\n'
+ +' transformed back to real space. Recommended for data with\n'
+ +' resp. regions with constant background.')
+ self.shiftMethodComboBox.setToolTip(shiftMethodToolTip)
+
+ # Alignment Method selector
+ self.alignmentMethodComboBox = qt.QComboBox()
+ self.alignmentMethodComboBox.addItems(
+ ['FFT',
+ 'MAX',
+ 'FIT',
+ 'FIT DRV'])
+ alignmentMethodToolTip =\
+ ('Select the method used to calculate the shift is calculated.\n\n'
+ +'FFT:\n'
+ +' Calculates the correlation between two curves using its\n'
+ +' Fourier transform. The shift is proportional to the distance of\n'
+ +' the correlation function\'s maxima.\n'
+ +'MAX:\n'
+ +' Determines the shift as the distance between the maxima of\n'
+ +' two peaks\n'
+ +'FIT:\n'
+ +' Guesses the most prominent feature in a spectrum and tries\n'
+ +' to fit it with a Gaussian peak. Before the fit is perform, the\n'
+ +' background is substracted. The shift is given by the difference\n'
+ +' of the center of mass between two peaks.\n'
+ +'FIT DRV:\n'
+ +' Like FIT, but the fit is performed on the derivate of the\n'
+ +' spectrum. Recommended procedure for XAFS data.')
+ self.alignmentMethodComboBox.setToolTip(alignmentMethodToolTip)
+
+ # Fill table with data
+ self.setDict(llist, ddict)
+ self.shiftTab.resizeColumnToContents(self._colLegend)
+ self.shiftTab.resizeColumnToContents(self._colShiftLegend)
+
+ #Layouts
+ topLayout = qt.QHBoxLayout()
+ topLayout.addWidget(buttonCalc)
+ topLayout.addWidget(qt.HorizontalSpacer())
+ topLayout.addWidget(qt.QLabel('Alignment method:'))
+ topLayout.addWidget(self.alignmentMethodComboBox)
+ topLayout.addWidget(qt.QLabel('Shift method:'))
+ topLayout.addWidget(self.shiftMethodComboBox)
+
+ buttonLayout = qt.QHBoxLayout()
+ buttonLayout.addWidget(buttonSave)
+ buttonLayout.addWidget(buttonLoad)
+ buttonLayout.addWidget(qt.HorizontalSpacer())
+ buttonLayout.addWidget(buttonApply)
+ buttonLayout.addWidget(buttonStore)
+ buttonLayout.addWidget(buttonCancel)
+
+ mainLayout = qt.QVBoxLayout()
+ mainLayout.addLayout(topLayout)
+ mainLayout.addWidget(self.shiftTab)
+ mainLayout.addLayout(buttonLayout)
+ mainLayout.setContentsMargins(1,1,1,1)
+ self.setLayout(mainLayout)
+
+ # Connects
+ self.shiftTab.cellChanged.connect(self.validateInput)
+ buttonApply.clicked.connect(self.accept)
+ buttonCancel.clicked.connect(self.reject)
+ buttonStore.clicked.connect(self.store)
+ buttonSave.clicked.connect(self.saveDict)
+ buttonLoad.clicked.connect(self.loadDict)
+
+ # ..to Plugin instance
+ buttonCalc.clicked[()].connect(self.triggerCalculateShift)
+ self.alignmentMethodComboBox.activated['QString'].\
+ connect(self.triggerCalculateShift)
+
+ def triggerCalculateShift(self, methodName=None):
+ # Need to call the plugin instance to perform calculations
+ try:
+ if methodName != None:
+ self.plugin.setAlignmentMethod(methodName)
+ llist, ddict = self.plugin.calculateShifts()
+ self.setDict(llist, ddict)
+ except:
+ msg = qt.QMessageBox(self)
+ msg.setIcon(qt.QMessageBox.Critical)
+ msg.setWindowTitle("Plugin error")
+ msg.setText("An error has occured while executing the plugin:")
+ msg.setInformativeText(str(sys.exc_info()[1]))
+ msg.setDetailedText(traceback.format_exc())
+ msg.exec_()
+
+ def store(self):
+ self.done(self._storeCode)
+
+ def loadDict(self):
+ openDir = PyMcaDirs.outputDir
+ filter = 'PyMca (*.shift)'
+ filename = qt.QFileDialog.\
+ getOpenFileName(self,
+ 'Load Shifts obtained from FFTAlignment',
+ openDir,
+ filter)
+ if len(filename) == 0:
+ return
+ inDict = ConfigDict.ConfigDict()
+ try:
+ inDict.read(filename)
+ except IOError:
+ msg = qt.QMessageBox()
+ msg.setTitle('FFTAlignment Load Error')
+ msg.setText('Unable to read shifts form file \'%s\''%filename)
+ msg.exec_()
+ return
+ if 'Shifts' not in inDict.keys():
+ # Only if the shift file consists exclusively of ShiftList
+ orderedLegends = [legend for legend in self.plugin.getOrder()]
+ try:
+ shiftList = inDict['ShiftList']['ShiftList']
+ except KeyError:
+ msg = qt.QMessageBox()
+ msg.setWindowTitle('FFTAlignment Load Error')
+ msg.setText('No shift information found in file \'%s\''%filename)
+ msg.exec_()
+ ddict = dict(zip(orderedLegends, shiftList))
+ llist = self.plugin.getOrder()
+ else:
+ llist = inDict['Order']['Order']
+ ddict = inDict['Shifts']
+ self.setDict(llist, ddict)
+
+ def saveDict(self):
+ saveDir = PyMcaDirs.outputDir
+ filter = ['PyMca (*.shift)']
+ try:
+ filename = PyMcaFileDialogs.\
+ getFileList(parent=self,
+ filetypelist=filter,
+ message='Safe FFT Alignment shifts',
+ mode='SAVE',
+ single=True)[0]
+ except IndexError:
+ # Returned list is empty
+ return False
+ if len(filename) == 0:
+ return False
+ if not str(filename).endswith('.shift'):
+ filename += '.shift'
+ if DEBUG:
+ print('saveOptions -- Filename: "%s"' % filename)
+ currentOrder = self.plugin.getOrder()
+ outDict = ConfigDict.ConfigDict()
+ llist, ddict = self.getDict()
+ outDict['Order'] = {'Order': currentOrder}
+ outDict['Shifts'] = ddict
+ outDict['ShiftList'] = {
+ 'ShiftList':[ddict[legend] for legend in currentOrder]}
+ try:
+ outDict.write(filename)
+ except IOError:
+ msg = qt.QMessageBox()
+ msg.setWindowTitle('FFTAlignment Save Error')
+ msg.setText('Unable to write configuration to \'%s\''%filename)
+ msg.exec_()
+ return True
+
+ def getAlignmentMethodName(self):
+ return self.alignmentMethodComboBox.currentText()
+
+ def getShiftMethodName(self):
+ return self.shiftMethodComboBox.currentText()
+
+ def getDict(self):
+ llist, ddict = [], {}
+ for idx in range(self.shiftTab.rowCount()):
+ # Loop through rows
+ legend = self.shiftTab.item(idx, self._colLegend)
+ shiftLegend = self.shiftTab.item(idx, self._colShiftLegend)
+ value = self.shiftTab.item(idx, self._colShift)
+ try:
+ floatValue = float(value.text())
+ except:
+ floatValue = float('NaN')
+ ddict[str(legend.text())] = floatValue
+ llist.append(str(shiftLegend.text()))
+ return llist, ddict
+
+ def setDict(self, llist, ddict):
+ # Order in which shift are shown is not
+ # necessarily the order in which they were
+ # added to plot window
+
+ curr = self.plugin.getOrder()
+ keys = llist
+ vals = [ddict[k] for k in keys]
+ # ..or just leave them in random ddict order
+ #dkeys = ddict.keys()
+ #dvals = ddict.values()
+
+ self.shiftTab.clear()
+ self.shiftTab.setColumnCount(3)
+ self.shiftTab.setHorizontalHeaderLabels(
+ ['Legend','Shift calculated from','Shift'])
+ self.shiftTab.setRowCount(len(keys))
+ if len(ddict) == 0:
+ return
+
+ for j, dlist in enumerate([curr, keys, vals]):
+ # j denotes the column of the table
+ # j = 0: Legend, set cells inactive (greyed out)
+ # j = 1: Legend from which the shift was calculated (greyed out)
+ # j = 2: Shift values, set cells active
+ for i in range(len(dlist)):
+ # i loops through the contents of each list
+ # setting every row of the table
+ if (j == 0) or (j == 1):
+ elem = qt.QTableWidgetItem(dlist[i])
+ elem.setFlags(qt.Qt.ItemIsSelectable)
+ #elem.setFlags(qt.Qt.ItemIsEnabled)
+ elif j == 2:
+ elem = qt.QTableWidgetItem(str(dlist[i]))
+ elem.setTextAlignment(qt.Qt.AlignRight)
+ elem.setTextAlignment(qt.Qt.AlignRight + qt.Qt.AlignVCenter)
+ elem.setFlags(qt.Qt.ItemIsEditable | qt.Qt.ItemIsEnabled)
+ else:
+ elem = qt.QTableWidgetItem('')
+ self.shiftTab.setItem(i,j, elem)
+ self.shiftTab.resizeColumnToContents(self._colLegend)
+ self.shiftTab.resizeColumnToContents(self._colShiftLegend)
+ self.shiftTab.resizeRowsToContents()
+
+ def validateInput(self, row, col):
+ if (col == 0) or (col == 1):
+ return
+ elif col == 2:
+ item = self.shiftTab.item(row, 2)
+ try:
+ floatValue = float(item.text())
+ item.setText('%.6g'%floatValue)
+ except:
+ floatValue = float('NaN')
+ item.setText(str(floatValue))
+
+class AdvancedAlignmentScanPlugin(Plugin1DBase.Plugin1DBase):
+ def __init__(self, plotWindow, **kw):
+ Plugin1DBase.Plugin1DBase.__init__(self, plotWindow, **kw)
+ self.__randomization = True
+ self.__methodKeys = []
+ self.methodDict = {}
+
+ function = self.calculateAndApplyShifts
+ method = "Perform FFT Alignment"
+ text = "Performs FFT based alignment and\n"
+ text += "inverse FFT based shift"
+ info = text
+ icon = None
+ self.methodDict[method] = [function,
+ info,
+ icon]
+ self.__methodKeys.append(method)
+
+ function = self.showShifts
+ method = "Show Alignment Window"
+ text = "Displays the calculated shifts and\n"
+ text += "allows to fine tune the plugin"
+ info = text
+ icon = None
+ self.methodDict[method] = [function,
+ info,
+ icon]
+ self.__methodKeys.append(method)
+
+ function = self.showDocs
+ method = "Show documentation"
+ text = "Shows the plug-ins documentation\n"
+ text += "in a browser window"
+ info = text
+ icon = None
+ self.methodDict[method] = [function,
+ info,
+ icon]
+ self.__methodKeys.append(method)
+
+ self.alignmentMethod = self.calculateShiftsFFT
+ self.shiftMethod = self.fftShift
+ self.shiftDict = {}
+ self.shiftList = []
+
+ #Methods to be implemented by the plugin
+ def getMethods(self, plottype=None):
+ """
+ A list with the NAMES associated to the callable methods
+ that are applicable to the specified plot.
+
+ Plot type can be "SCAN", "MCA", None, ...
+ """
+# if self.__randomization:
+# return self.__methodKeys[0:1] + self.__methodKeys[2:]
+# else:
+# return self.__methodKeys[1:]
+ return self.__methodKeys
+
+ def getMethodToolTip(self, name):
+ """
+ Returns the help associated to the particular method name or None.
+ """
+ return self.methodDict[name][1]
+
+ def getMethodPixmap(self, name):
+ """
+ Returns the pixmap associated to the particular method name or None.
+ """
+ return None
+
+ def applyMethod(self, name):
+ """
+ The plugin is asked to apply the method associated to name.
+ """
+ return self.methodDict[name][0]()
+
+
+ def calculateAndApplyShifts(self):
+ # Assure that FFT alignment & shift methods are set
+ self.alignmentMethod = self.calculateShiftsFFT
+ self.shiftMethod = self.fftShift
+ self.calculateShifts()
+ self.applyShifts()
+ # Reset shift Dictionary and legend List
+ self.shiftDict = {}
+ self.shiftList = []
+
+ def calculateShifts(self):
+ '''
+ Generic alignment method, executes the method
+ that is set under self.alignmentMethod.
+
+ Choices are:
+ - calculateShiftsFit
+ - calculateShiftsFFT
+ - calculateShiftsMax
+
+ Sets self.shiftList and self.shiftDict
+ '''
+ self.shiftList, self.shiftDict = self.alignmentMethod()
+ return self.shiftList, self.shiftDict
+
+ def getOrder(self):
+ '''
+ Returns the legends of the curves in the plot winow
+ in the order they were added.
+ '''
+ ret = [legend for (x,y,legend,info) in self._plotWindow.getAllCurves()]
+ return ret
+
+ # BEGIN Alignment Methods
+ def calculateShiftsFitDerivative(self):
+ return self.calculateShiftsFit(derivative=True)
+
+ def calculateShiftsFit(self, derivative=False, thr=30):
+ retDict = {}
+ retList = []
+
+ curves = self.getAllCurves()
+ nCurves = len(curves)
+ if nCurves < 2:
+ raise ValueError("At least 2 curves needed")
+ return
+
+ # Check if scan window is zoomed in
+ xmin, xmax = self.getGraphXLimits()
+ # Determine largest overlap between curves
+ xmin0, xmax0 = self.getXLimits(x for (x,y,leg,info) in curves)
+ if xmin0 > xmin:
+ xmin = xmin0
+ if xmax0 < xmax:
+ xmax = xmax0
+ if DEBUG:
+ print('calculateShiftsFit -- xmin = %.3f, xmax = %.3f'%(xmin, xmax))
+
+ # Get active curve
+ activeCurve = self.getActiveCurve()
+ if activeCurve is None:
+ # If active curve is not set, continue with first curve
+ activeCurve = curves[0]
+ else:
+ activeLegend = activeCurve[2]
+ idx = list.index([curve[2] for curve in curves],
+ activeLegend)
+ activeCurve = curves[idx]
+
+ x0, y0 = activeCurve[0], activeCurve[1]
+ idx = numpy.nonzero((xmin <= x0) & (x0 <= xmax))[0]
+ x0 = numpy.take(x0, idx)
+ y0 = numpy.take(y0, idx)
+
+ if derivative:
+ # Take first derivative
+ y0 = numpy.diff(y0)/numpy.diff(x0)
+ x0 = .5 * (x0[1:] + x0[:-1])
+
+ peak0 = self.findPeaks(x0, y0, .80, derivative)
+ if peak0:
+ xp0, yp0, fwhm0, fitrange0 = peak0
+ else:
+ raise ValueError("No peak identified in '%s'"%activeCurve[2])
+ fitp0, chisq0, sigma0 = LSF(gauss,
+ numpy.asarray([yp0, xp0, fwhm0]),
+ xdata=x0[fitrange0],
+ ydata=y0[fitrange0])
+ if DEBUG:
+ if derivative:
+ print('calculateShiftsFit -- Results (Leg, PeakPos, Shift):')
+ else:
+ print('calculateShiftsFitDerivative -- Results (Leg, PeakPos, Shift):')
+ for x,y,legend,info in curves:
+ idx = numpy.nonzero((xmin <= x) & (x <= xmax))[0]
+ x = numpy.take(x, idx)
+ y = numpy.take(y, idx)
+
+ if derivative:
+ # Take first derivative
+ y = numpy.diff(y)/numpy.diff(x)
+ x = .5 * (x[1:] + x[:-1])
+
+ peak = self.findPeaks(x, y, .80, derivative)
+ if peak:
+ xp, yp, fwhm, fitrange = peak
+ else:
+ raise ValueError("No peak identified in '%s'"%activeCurve[2])
+ try:
+ fitp, chisq, sigma = LSF(gauss,
+ numpy.asarray([yp, xp, fwhm]),
+ xdata=x[fitrange],
+ ydata=y[fitrange])
+ # Shift is difference in peak's x position
+ shift = fitp0[1] - fitp[1]
+ except numpy.linalg.linalg.LinAlgError:
+ msg = qt.QMessageBox(None)
+ msg.setWindowTitle('Alignment Error')
+ msg.setText('Singular matrix encountered during least squares fit.')
+ msg.setStandardButtons(qt.QMessageBox.Ok)
+ msg.exec_()
+ shift = float('NaN')
+ key = legend
+ retList.append(key)
+ retDict[key] = shift
+ if DEBUG:
+ print( '\t%s\t%.3f\t%.3f'%(legend, fitp[1], shift))
+ return retList, retDict
+
+ def calculateShiftsMax(self):
+ retDict = {}
+ retList = []
+
+ curves = self.getAllCurves()
+ nCurves = len(curves)
+
+ if nCurves < 2:
+ raise ValueError("At least 2 curves needed")
+ return
+
+ # Check if plotwindow is zoomed in
+ xmin, xmax = self.getGraphXLimits()
+ # Determine largest overlap between curves
+ xmin0, xmax0 = self.getXLimits(x for (x,y,leg,info) in curves)
+ if xmin0 > xmin:
+ xmin = xmin0
+ if xmax0 < xmax:
+ xmax = xmax0
+
+ # Get active curve
+ activeCurve = self.getActiveCurve()
+ if activeCurve is None:
+ # If active curve is not set, continue with first curve
+ activeCurve = curves[0]
+ else:
+ activeLegend = activeCurve[2]
+ idx = list.index([curve[2] for curve in curves],
+ activeLegend)
+ activeCurve = curves[idx]
+
+ x0, y0 = activeCurve[0], activeCurve[1]
+ idx = numpy.nonzero((xmin <= x0) & (x0 <= xmax))[0]
+ x0 = numpy.take(x0, idx)
+ y0 = numpy.take(y0, idx)
+
+ # Determine the index of maximum in active curve
+ shift0 = numpy.argmax(y0)
+ if DEBUG:
+ print('calculateShiftsMax -- Results:')
+ print('\targmax(y) shift')
+ for x,y,legend,info in curves:
+ idx = numpy.nonzero((xmin <= x) & (x <= xmax))[0]
+ x = numpy.take(x, idx)
+ y = numpy.take(y, idx)
+
+ shifty = numpy.argmax(y)
+ shift = x0[shift0] - x[shifty]
+ key = legend
+ retList.append(key)
+ retDict[key] = shift
+ if DEBUG:
+ print('\t%d %.3f'%(x[shifty],shift))
+ return retList, retDict
+
+ def calculateShiftsFFT(self, portion=.95):
+ retDict = {}
+ retList = []
+
+ curves = self.interpolate()
+ nCurves = len(curves)
+ if nCurves < 2:
+ raise ValueError("At least 2 curves needed")
+ return
+
+ # Check if scan window is zoomed in
+ xmin, xmax = self.getGraphXLimits()
+ # Determine largest overlap between curves
+ xmin0, xmax0 = self.getXLimits(x for (x,y,leg,info) in curves)
+ if xmin0 > xmin:
+ xmin = xmin0
+ if xmax0 < xmax:
+ xmax = xmax0
+ if DEBUG:
+ print('calculateShiftsFFT -- xmin = %.3f, xmax = %.3f'%(xmin, xmax))
+
+ # Get active curve
+ activeCurve = self.getActiveCurve()
+ if activeCurve is None:
+ # If active curve is not set, continue with first curve
+ activeCurve = curves[0]
+ else:
+ activeLegend = activeCurve[2]
+ idx = list.index([curve[2] for curve in curves],
+ activeLegend)
+ activeCurve = curves[idx]
+
+ x0, y0 = activeCurve[0], activeCurve[1]
+ idx = numpy.nonzero((xmin <= x0) & (x0 <= xmax))[0]
+ x0 = numpy.take(x0, idx)
+ y0 = self.normalize(y0)
+ y0 = numpy.take(y0, idx)
+
+ fft0 = numpy.fft.fft(y0)
+ if DEBUG:
+ print('calculateShiftsFFT -- results (Legend len(idx) shift):')
+ for x,y,legend,info in curves:
+ idx = numpy.nonzero((x >= xmin) & (x <= xmax))[0]
+ x = numpy.take(x, idx)
+ y = numpy.take(y, idx)
+ ffty = numpy.fft.fft(y)
+ shiftTmp = numpy.fft.ifft(fft0 * ffty.conjugate()).real
+ shiftPhase = numpy.zeros(shiftTmp.shape, dtype=shiftTmp.dtype)
+ m = shiftTmp.size//2
+ shiftPhase[m:] = shiftTmp[:-m]
+ shiftPhase[:m] = shiftTmp[-m:]
+ # Normalize shiftPhase to standardize thresholding
+ shiftPhase = self.normalize(shiftPhase)
+
+ # Thresholding
+ xShiftMax = shiftPhase.argmax()
+ left, right = xShiftMax, xShiftMax
+ threshold = portion * shiftPhase.max()
+ while (shiftPhase[left] > threshold)&\
+ (shiftPhase[right] > threshold):
+ left -= 1
+ right += 1
+ idx = numpy.arange(left, right+1, 1, dtype=int)
+ # The shift is determined by center-of-mass around shiftMax
+ shiftTmp = (shiftPhase[idx] * idx/shiftPhase[idx].sum()).sum()
+ shift = (shiftTmp - m) * (x[1] - x[0])
+
+ key = legend
+ retList.append(key)
+ retDict[key] = shift
+ if DEBUG:
+ print('\t%s\t%d\t%f'%(legend,len(idx),shift))
+ return retList, retDict
+ # END Alignment Methods
+
+ def applyShifts(self):
+ '''
+ Generic shift method. The method shifts curves
+ according to the shift stored in self.shiftDict
+ and executes the method stored in self.shiftMethod.
+
+ Curves are sorted with respect to their legend,
+ the values of self.shiftDict are sorted with
+ respect to their key.
+ '''
+ if len(self.shiftDict) == 0:
+ msg = qt.QMessageBox(None)
+ msg.setWindowTitle('Alignment Error')
+ msg.setText('No shift data present.')
+ msg.setStandardButtons(qt.QMessageBox.Ok)
+ msg.exec_()
+ return False
+
+ # Check if interpolation is needed
+ if self.shiftMethod == self.fftShift:
+ curves = self.interpolate()
+ else:
+ curves = self.getAllCurves()
+
+ if len(self.shiftList) != len(curves):
+ msg = qt.QMessageBox(None)
+ msg.setWindowTitle('Alignment Error')
+ msg.setText(
+ '''Number of shifts does not match the number of curves.
+ Do you want to continue anyway?''')
+ msg.setStandardButtons(qt.QMessageBox.Ok)
+ msg.setStandardButtons(qt.QMessageBox.Ok | qt.QMessageBox.Cancel)
+ msg.setDefaultButton(qt.QMessageBox.Ok)
+
+ if msg.exec_() != qt.QMessageBox.Ok:
+ return False
+
+ if DEBUG:
+ print('applyShifts -- Shifting ...')
+ for idx, (x,y,legend,info) in enumerate(curves):
+ shift = self.shiftDict[legend]
+
+ if shift is None:
+ if DEBUG:
+ print('\tCurve \'%s\' not found in shiftDict\n%s'\
+ %(legend,str(self.shiftDict)))
+ continue
+ if shift == float('NaN'):
+ if DEBUG:
+ print('\tCurve \'%s\' has NaN shift'%legend)
+ continue
+
+ # Limit shift to zoomed in area
+ xmin, xmax = self.getGraphXLimits()
+ mask = numpy.nonzero((xmin<=x) & (x<=xmax))[0]
+ # Execute method stored in self.shiftMethod
+ xShifted, yShifted = self.shiftMethod(shift, x[mask], y[mask])
+
+ if idx == 0:
+ replace, replot = True, False
+ elif idx == (len(curves)-1):
+ replace, replot = False, True
+ else:
+ replace, replot = False, False
+ # Check if scan number is adopted by new curve
+ if DEBUG:
+ print('\'%s\' -- shifts -> \'%s\' by %f'%(self.shiftList[idx], legend, shift))
+ selectionlegend = info.get('selectionlegend',legend)
+ self.addCurve(xShifted, yShifted,
+ (selectionlegend + ' SHIFT'),
+ info,
+ replace, replot)
+ return True
+
+
+ # BEGIN Shift Methods
+ def fftShift(self, shift, x, y):
+ yShifted = numpy.fft.ifft(
+ numpy.exp(-2.0*numpy.pi*numpy.sqrt(numpy.complex(-1))*\
+ numpy.fft.fftfreq(len(x), d=x[1]-x[0])*shift)*numpy.fft.fft(y))
+ return x, yShifted.real
+
+ def xShift(self, shift, x, y):
+ return x+shift, y
+ # END Shift Methods
+
+ def showShifts(self):
+ '''
+ Creates an instance of Alignment Widget that
+ allows to
+
+ - Calculate, display & save/store shifts
+ - Load existing shift data
+ - Select different alignment and shift methods
+ '''
+ # Empty shift table in the beginning
+ widget = AlignmentWidget(None, self.shiftDict, self.shiftList, self)
+ ret = widget.exec_()
+ if ret == 1:
+ # Result code Apply
+ self.shiftList, self.shiftDict = widget.getDict()
+ # self.shiftList = self.getOrder()
+ self.setShiftMethod(widget.getShiftMethodName())
+ self.applyShifts()
+ self.shiftDict = {}
+ self.shiftList = []
+ elif ret == 2:
+ # Result code Store
+ self.shiftList, self.shiftDict = widget.getDict()
+ self.shiftList = self.getOrder() # Remember order of scans
+ self.setShiftMethod(widget.getShiftMethodName())
+ else:
+ # Dialog is canceled
+ self.shiftDict = {}
+ self.shiftList = []
+ widget.destroy() # Widget should be destroyed after finishing method
+ return
+
+ # BEGIN Helper Methods
+ def setShiftMethod(self, methodName):
+ '''
+ Method receives methodName from AlignmentWidget
+ instance and assigns the according shift method.
+ '''
+ if DEBUG:
+ print('setShiftMethod -- %s'%methodName)
+ methodName = str(methodName)
+ if methodName == 'Inverse FFT shift':
+ self.shiftMethod = self.fftShift
+ elif methodName == 'Shift x-range':
+ self.shiftMethod = self.xShift
+ else:
+ # Unknown method name, use fftShift as default
+ self.shiftMethod = self.fftShift
+
+ def setAlignmentMethod(self, methodName):
+ '''
+ Method receives methodName from AlignmentWidget
+ instance and assigns the according alignment method.
+ '''
+ if DEBUG:
+ print('setAlignmentMethod -- %s'%methodName)
+ methodName = str(methodName)
+ if methodName == 'FFT':
+ self.alignmentMethod = self.calculateShiftsFFT
+ elif methodName == 'MAX':
+ self.alignmentMethod = self.calculateShiftsMax
+ elif methodName == 'FIT':
+ self.alignmentMethod = self.calculateShiftsFit
+ elif methodName == 'FIT DRV':
+ self.alignmentMethod = self.calculateShiftsFitDerivative
+ else:
+ # Unknown method name, use fftShift as default
+ self.alignmentMethod = self.calculateShiftsFFT
+
+ def getAllCurves(self, just_legend=False):
+ '''
+ Ensures that the x-range of the curves
+ is strictly monotonically increasing.
+ Conserves curves legend and info dictionary.
+ '''
+ curves = Plugin1DBase.Plugin1DBase.getAllCurves(self)
+ if just_legend:
+ return curves
+
+ processedCurves = []
+ for curve in curves:
+ x, y, legend, info = curve[0:4]
+ xproc = x[:]
+ yproc = y[:]
+ # Sort
+ idx = numpy.argsort(xproc, kind='mergesort')
+ xproc = numpy.take(xproc, idx)
+ yproc = numpy.take(yproc, idx)
+ # Ravel, Increasing
+ xproc = xproc.ravel()
+ idx = numpy.nonzero((xproc[1:] > xproc[:-1]))[0]
+ xproc = numpy.take(xproc, idx)
+ yproc = numpy.take(yproc, idx)
+ processedCurves += [(xproc, yproc, legend, info)]
+ return processedCurves
+
+ def interpolate(self, factor=1.):
+ '''
+ Input
+ -----
+ factor : float
+ factor used to oversample existing data, use
+ with caution.
+
+ Interpolates all existing curves to an equidistant
+ x-range using the either the active or the first
+ curve do determine the number of data points.
+ Use this method instead of self.getAllCurves() when
+ performin FFT related tasks.
+
+ Returns
+ -------
+ interpCurves : ndarray
+ Array containing the interpolated curves shown
+ in the plot window.
+ Format: [(x0, y0, legend0, info0), ...]
+ '''
+ curves = self.getAllCurves()
+ if len(curves) < 1:
+ raise ValueError("At least 1 curve needed")
+ if DEBUG:
+ print('interpolate -- no curves present')
+ return
+
+ activeCurve = self.getActiveCurve()
+ if not activeCurve:
+ activeCurve = curves[0]
+ else:
+ activeLegend = activeCurve[2]
+ idx = list.index([curve[2] for curve in curves],
+ activeLegend)
+ activeCurve = curves[idx]
+ activeX, activeY, activeLegend, activeInfo = activeCurve[0:4]
+
+ # Determine average spaceing between Datapoints
+ step = numpy.average(numpy.diff(activeX))
+ xmin, xmax = self.getXLimits([x for (x,y,leg,info) in curves],
+ overlap=False)
+ num = factor * numpy.ceil((xmax-xmin)/step)
+
+ # Create equidistant x-range, exclude first and last point
+ xeq = numpy.linspace(xmin, xmax, num, endpoint=False)[:-1]
+
+ # Interpolate on sections of xeq
+ interpCurves = []
+ for (x,y,legend,info) in curves:
+ idx = numpy.nonzero((x.min()<xeq) & (xeq<x.max()))[0]
+ xi = numpy.take(xeq, idx)
+ yi = SpecfitFuns.interpol([x], y, xi.reshape(-1,1), y.min())
+ yi.shape = -1
+ interpCurves += [(xi, yi, legend, info)]
+ return interpCurves
+
+ def getXLimits(self, values, overlap=True):
+ '''
+ Input
+ -----
+ overlap : bool
+ True -> returns minimal and maximal x-values
+ that are that are still lie within the
+ x-ranges of all curves in plot window
+ False -> returns minimal and maximal x-values of
+ all curves in plot window
+
+ Returns
+ -------
+ xmin0, xmax0 : float
+ '''
+ if overlap:
+ xmin0, xmax0 = -numpy.inf, numpy.inf
+ else:
+ xmin0, xmax0 = numpy.inf, -numpy.inf
+ for x in values:
+ xmin = x.min()
+ xmax = x.max()
+ if overlap:
+ if xmin > xmin0:
+ xmin0 = xmin
+ if xmax < xmax0:
+ xmax0 = xmax
+ else:
+ if xmin < xmin0:
+ xmin0 = xmin
+ if xmax > xmax0:
+ xmax0 = xmax
+ if DEBUG:
+ print('getXLimits -- overlap = %s, xmin = %.3f, xmax =%.3f'\
+ %(overlap,xmin0,xmax0))
+ return xmin0, xmax0
+
+ def normalize(self, y):
+ '''
+ Normalizes spectrum to values between zero and one.
+ '''
+ ymax, ymin = y.max(), y.min()
+ return (y-ymin)/(ymax-ymin)
+
+ def findPeaks(self, x, y, thr, derivative):
+ '''
+ Input
+ -----
+ x,y : ndarrays
+ Arrays contain curve intformation
+ thr : float
+ Threshold in percent of normalized maximum
+ derivative : bool
+ The derivative of a curve is being fitted
+
+ Finds most prominent feature contained in y
+ and tries to estimate starting parameters for a
+ Gaussian least squares fit (LSF). Recommends values
+ used to fit the Gaussian.
+
+ Return
+ ------
+ xpeak, ypeak, fwhm : float
+ Estimated values for x-position, amplitude
+ and width of the Gaussian
+ fwhmIdx : ndarray
+ Indices determine the range on which the LSF
+ is performed
+ '''
+ # Use SNIP algorithm for background substraction &
+ # seek method for peak detection
+ sffuns = SF.SpecfitFunctions()
+ if derivative:
+ # Avoid BG substraction & normalization if
+ # fitting the derivate of a curve
+ ybg = y
+ ynorm = y/(abs(y.max())+abs(y.min()))
+ else:
+ ybg = y-snip.getSnip1DBackground(y, len(y)//thr) # USER INPUT!!!
+ # Normalize background substracted data to
+ # standardize the yscaling of seek method
+ #ynorm = (ybg - ybg.min())/(ybg.max()-ybg.min())
+ ynorm = self.normalize(ybg)
+
+ # Replace by max()?
+ try:
+ # Calculate array woth all peak indices
+ peakIdx = numpy.asarray(sffuns.seek(ybg, yscaling=1000.), dtype=int)
+ # Extract highest peak
+ sortIdx = y[peakIdx].argsort()[-1]
+ except IndexError:
+ if DEBUG:
+ print('No peaks found..')
+ return None
+ except SystemError:
+ if DEBUG:
+ print('Peak search failed. Continue with y maximum')
+ peakIdx = [ybg.argmax()]
+ sortIdx = 0
+ xpeak = float(x[peakIdx][sortIdx])
+ ypeak = float(y[peakIdx][sortIdx])
+ ypeak_norm = float(ynorm[peakIdx][sortIdx])
+ ypeak_bg = float(ybg[peakIdx][sortIdx])
+
+ # Estimate FWHM
+ fwhmIdx = numpy.nonzero(ynorm >= thr*ypeak_norm)[0]
+ #fwhmIdx = numpy.nonzero(ybg >= thr*ypeak_bg)[0]
+ # Underestimates FWHM
+ x0, x1 = x[fwhmIdx].min(), x[fwhmIdx].max()
+ fwhm = x1 - x0
+
+ return xpeak, ypeak, fwhm, fwhmIdx
+ # END Helper Methods
+
+ def showDocs(self):
+ '''
+ Displays QTextBrowser showing the documentation
+ '''
+ helpFileName = pathjoin(PyMcaDataDir.PYMCA_DOC_DIR,
+ "HTML",
+ "AdvancedAlignmentScanPlugin.html")
+ self.helpFileBrowser = qt.QTextBrowser()
+ self.helpFileBrowser.setWindowTitle('Alignment Scan Plug-in Documentation')
+ self.helpFileBrowser.setLineWrapMode(qt.QTextEdit.FixedPixelWidth)
+ self.helpFileBrowser.setLineWrapColumnOrWidth(500)
+ self.helpFileBrowser.resize(520,300)
+ try:
+ helpFileHandle = open(helpFileName)
+ helpFileHTML = helpFileHandle.read()
+ helpFileHandle.close()
+ self.helpFileBrowser.setHtml(helpFileHTML)
+ except IOError:
+ msg = qt.QMessageBox()
+ msg.setWindowTitle('Alignment Scan Error')
+ msg.setText('No help file found.')
+ msg.exec_()
+ if DEBUG:
+ print('XMCDWindow -- init: Unable to read help file')
+ self.helpFileBrowser = None
+ if self.helpFileBrowser is not None:
+ self.helpFileBrowser.show()
+ self.helpFileBrowser.raise_()
+
+MENU_TEXT = "Advanced Alignment Plugin"
+def getPlugin1DInstance(plotWindow, **kw):
+ ob = AdvancedAlignmentScanPlugin(plotWindow)
+ return ob
+
+if __name__ == "__main__":
+ from PyMca import PyMcaQt as qt
+ app = qt.QApplication([])
+ from PyMca.Plot1DQwt import Plot1DQwt as Plot1D
+
+ x = numpy.arange(250, 750, 2, dtype=float)
+ y1 = 1.0 + 50.0 * numpy.exp(-0.001*(x-500)**2) + 2.*numpy.random.random(250.)
+ y2 = 1.0 + 20.5 * numpy.exp(-0.005*(x-600)**2) + 2.*numpy.random.random(250.)
+
+ plot = Plot1D()
+ plot.addCurve(x, y1, "y1", {'selectionlegend': 'y1'})
+ plot.addCurve(x, y2, "y2", {'selectionlegend': 'y2'})
+
+ plugin = getPlugin1DInstance(plot)
+ for method in plugin.getMethods():
+ print(method, ":", plugin.getMethodToolTip(method))
+ plugin.applyMethod(plugin.getMethods()[0])
diff --git a/PyMca/PyMcaPlugins/FastXRFLinearFitStackPlugin.py b/PyMca/PyMcaPlugins/FastXRFLinearFitStackPlugin.py
new file mode 100644
index 0000000..81f4e5d
--- /dev/null
+++ b/PyMca/PyMcaPlugins/FastXRFLinearFitStackPlugin.py
@@ -0,0 +1,263 @@
+#/*##########################################################################
+# Copyright (C) 2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+__author__ = "V.A. Sole - ESRF Data Analysis"
+"""
+
+A Stack plugin is a module that will be automatically added to the PyMca stack windows
+in order to perform user defined operations on the data stack.
+
+These plugins will be compatible with any stack window that provides the functions:
+ #data related
+ getStackDataObject
+ getStackData
+ getStackInfo
+ setStack
+
+ #images related
+ addImage
+ removeImage
+ replaceImage
+
+ #mask related
+ setSelectionMask
+ getSelectionMask
+
+ #displayed curves
+ getActiveCurve
+ getGraphXLimits
+ getGraphYLimits
+
+ #information method
+ stackUpdated
+ selectionMaskUpdated
+"""
+import os
+import numpy
+import time
+from PyMca import StackPluginBase
+from PyMca import FastXRFLinearFit
+from PyMca import FastXRFLinearFitWindow
+from PyMca import CalculationThread
+from PyMca import StackPluginResultsWindow
+import PyMca.PyMca_Icons as PyMca_Icons
+from PyMca import PyMcaQt as qt
+from PyMca import ArraySave
+
+DEBUG = 0
+
+class FastXRFLinearFitStackPlugin(StackPluginBase.StackPluginBase):
+ def __init__(self, stackWindow, **kw):
+ StackPluginBase.DEBUG = DEBUG
+ StackPluginBase.StackPluginBase.__init__(self, stackWindow, **kw)
+ self.methodDict = {}
+ function = self.calculate
+ info = "Fit stack with current fit configuration"
+ icon = PyMca_Icons.fit
+ self.methodDict["Fit Stack"] =[function,
+ info,
+ icon]
+ function = self._showWidget
+ info = "Show last results"
+ icon = PyMca_Icons.brushselect
+ self.methodDict["Show"] =[function,
+ info,
+ icon]
+ self.__methodKeys = ["Fit Stack", "Show"]
+ self.configurationWidget = \
+ FastXRFLinearFitWindow.FastXRFLinearFitDialog()
+ self.fitInstance = None
+ self._widget = None
+ self.thread = None
+
+ def stackUpdated(self):
+ if DEBUG:
+ print("FastXRFLinearFitStackPlugin.stackUpdated() called")
+ self._widget = None
+
+ def selectionMaskUpdated(self):
+ if self._widget is None:
+ return
+ if self._widget.isHidden():
+ return
+ mask = self.getStackSelectionMask()
+ self._widget.setSelectionMask(mask)
+
+ def mySlot(self, ddict):
+ if DEBUG:
+ print("mySlot ", ddict['event'], ddict.keys())
+ if ddict['event'] == "selectionMaskChanged":
+ self.setStackSelectionMask(ddict['current'])
+ elif ddict['event'] == "addImageClicked":
+ self.addImage(ddict['image'], ddict['title'])
+ elif ddict['event'] == "removeImageClicked":
+ self.removeImage(ddict['title'])
+ elif ddict['event'] == "replaceImageClicked":
+ self.replaceImage(ddict['image'], ddict['title'])
+ elif ddict['event'] == "resetSelection":
+ self.setStackSelectionMask(None)
+
+ #Methods implemented by the plugin
+ def getMethods(self):
+ if self._widget is None:
+ return [self.__methodKeys[0]]
+ else:
+ return self.__methodKeys
+
+ def getMethodToolTip(self, name):
+ return self.methodDict[name][1]
+
+ def getMethodPixmap(self, name):
+ return self.methodDict[name][2]
+
+ def applyMethod(self, name):
+ return self.methodDict[name][0]()
+
+ # The specific part
+ def calculate(self):
+ ret = self.configurationWidget.exec_()
+ if ret:
+ self._executeFunctionAndParameters()
+
+ def _executeFunctionAndParameters(self):
+ self._parameters = self.configurationWidget.getParameters()
+ self._widget = None
+ if self.fitInstance is None:
+ self.fitInstance = FastXRFLinearFit.FastXRFLinearFit()
+ #self._fitConfigurationFile="E:\DATA\COTTE\CH1777\G4-4720eV-NOWEIGHT-Constant-batch.cfg"
+
+ if DEBUG:
+ self.thread = CalculationThread.CalculationThread(\
+ calculation_method=self.actualCalculation)
+ self.thread.result = self.actualCalculation()
+ self.threadFinished()
+ else:
+ self.thread = CalculationThread.CalculationThread(\
+ calculation_method=self.actualCalculation)
+ #qt.QObject.connect(self.thread,
+ # qt.SIGNAL('finished()'),
+ # self.threadFinished)
+ self.thread.start()
+ message = "Please wait. Calculation going on."
+ CalculationThread.waitingMessageDialog(self.thread,
+ parent=self.configurationWidget,
+ message=message)
+ while self.thread.isRunning():
+ time.sleep(2)
+ self.threadFinished()
+
+ def actualCalculation(self):
+ activeCurve = self.getActiveCurve()
+ if activeCurve is not None:
+ x, spectrum, legend, info = activeCurve
+ else:
+ x = None
+ spectrum = None
+ if not self.isStackFinite():
+ # one has to check for NaNs in the used region(s)
+ # for the time being only in the global image
+ # spatial_mask = numpy.isfinite(image_data)
+ spatial_mask = numpy.isfinite(self.getStackOriginalImage())
+ stack = self.getStackDataObject()
+ fitConfigurationFile = self._parameters['configuration']
+ concentrations = self._parameters['concentrations']
+ self.fitInstance.setFitConfigurationFile(fitConfigurationFile)
+ result = self.fitInstance.fitMultipleSpectra(x=None,
+ y=stack,
+ concentrations=concentrations,
+ ysum=spectrum)
+ return result
+
+ def threadFinished(self):
+ result = self.thread.result
+ self.thread = None
+ if type(result) == type((1,)):
+ #if we receive a tuple there was an error
+ if len(result):
+ if result[0] == "Exception":
+ # somehow this exception is not caught
+ raise Exception(result[1], result[2])
+ return
+ if 'concentrations' in result:
+ imageNames = result['names']
+ images = numpy.concatenate((result['parameters'],
+ result['concentrations']), axis=0)
+ else:
+ images = result['parameters']
+ imageNames = result['names']
+ nImages = images.shape[0]
+ self._widget = StackPluginResultsWindow.StackPluginResultsWindow(\
+ usetab=False)
+ self._widget.buildAndConnectImageButtonBox()
+ qt = StackPluginResultsWindow.qt
+ qt.QObject.connect(self._widget,
+ qt.SIGNAL('MaskImageWidgetSignal'),
+ self.mySlot)
+
+ self._widget.setStackPluginResults(images,
+ image_names=imageNames)
+ self._showWidget()
+
+ # save to output directory
+ parameters = self.configurationWidget.getParameters()
+ outputDir = parameters["output_dir"]
+ if outputDir in [None, ""]:
+ if DEBUG:
+ print("Nothing to be saved")
+ return
+ if parameters["file_root"] is None:
+ fileRoot = ""
+ else:
+ fileRoot = parameters["file_root"].replace(" ","")
+ if fileRoot in [None, ""]:
+ fileRoot = "images"
+ if not os.path.exists(outputDir):
+ os.mkdir(outputDir)
+ imagesDir = os.path.join(outputDir, "IMAGES")
+ if not os.path.exists(imagesDir):
+ os.mkdir(imagesDir)
+ imageList = [None] * nImages
+ for i in range(nImages):
+ imageList[i] = images[i]
+ fileName = os.path.join(imagesDir, fileRoot+".edf")
+ ArraySave.save2DArrayListAsEDF(imageList, fileName, labels=imageNames)
+ fileName = os.path.join(imagesDir, fileRoot+".csv")
+ ArraySave.save2DArrayListAsASCII(imageList, fileName, csv=True, labels=imageNames)
+
+ def _showWidget(self):
+ if self._widget is None:
+ return
+ #Show
+ self._widget.show()
+ self._widget.raise_()
+
+ #update
+ self.selectionMaskUpdated()
+
+MENU_TEXT = "Fast XRF Stack Fitting"
+def getStackPluginInstance(stackWindow, **kw):
+ ob = FastXRFLinearFitStackPlugin(stackWindow)
+ return ob
diff --git a/PyMca/PyMcaPlugins/ImageAlignmentStackPlugin.py b/PyMca/PyMcaPlugins/ImageAlignmentStackPlugin.py
index a4290d7..2f311f0 100644
--- a/PyMca/PyMcaPlugins/ImageAlignmentStackPlugin.py
+++ b/PyMca/PyMcaPlugins/ImageAlignmentStackPlugin.py
@@ -58,24 +58,17 @@ These plugins will be compatible with any stack window that provides the functio
import sys
import os
import numpy
-try:
- from PyMca import StackPluginBase
- from PyMca import PyMcaQt as qt
- from PyMca import FFTAlignmentWindow
- from PyMca import ImageRegistration
- from PyMca import SpecfitFuns
- from PyMca import CalculationThread
- from PyMca import ArraySave
-
-except ImportError:
- print("ExternalImagesWindow importing from somewhere else")
- import StackPluginBase
- import PyMcaQt as qt
- import ImageRegistration
- import FFTAlignmentWindow
- import SpecfitFuns
- import CalculationThread
- import ArraySave
+from PyMca import StackPluginBase
+from PyMca import PyMcaQt as qt
+from PyMca import FFTAlignmentWindow
+from PyMca import ImageRegistration
+from PyMca import SpecfitFuns
+from PyMca import CalculationThread
+from PyMca import ArraySave
+from PyMca import PyMcaFileDialogs
+from PyMca import specfilewrapper
+from PyMca import HDF5Widget
+
try:
from PyMca import SIFTAlignmentWindow
sift = SIFTAlignmentWindow.sift
@@ -104,6 +97,11 @@ class ImageAlignmentStackPlugin(StackPluginBase.StackPluginBase):
"Align using SIFT Algorithm",
None]
self.__methodKeys.append(key)
+ key = 'From File Alignment'
+ self.methodDict[key] = [self._shiftFromFile,
+ "Align using shifts from file",
+ None]
+ self.__methodKeys.append(key)
self.widget = None
def stackUpdated(self):
@@ -508,6 +506,149 @@ class ImageAlignmentStackPlugin(StackPluginBase.StackPluginBase):
raise IndexError("Only stacks of images or spectra supported. 1D index should be 0 or 2")
return shifts
+ def _shiftFromFile(self):
+ stack = self.getStackDataObject()
+ if stack is None:
+ return
+ data = stack.data
+ mcaIndex = stack.info.get('McaIndex')
+ if not (mcaIndex in [0, -1, 2]):
+ raise IndexError("1D index must be 0, 2, or -1")
+ filefilter = ['HDF5 Files (*.h5 *.nxs *.hdf)', 'CSV 2-column (*.csv)', 'ASCII 2-column (*)']
+ filename, ffilter = PyMcaFileDialogs.\
+ getFileList(parent=None,
+ filetypelist=filefilter,
+ message='Load',
+ mode='OPEN',
+ single=True,
+ getfilter=True,
+ currentfilter=filefilter[0])
+ if len(filename):
+ if DEBUG:
+ print("file name = %s file filter = %s" % (filename, ffilter))
+ else:
+ if DEBUG:
+ print("nothing selected")
+ return
+ filename = filename[0]
+ if ffilter.startswith('HDF5'):
+ # browse
+ self.__hdf5Dialog = qt.QDialog()
+ self.__hdf5Dialog.setWindowTitle('Select your data set by a double click')
+ self.__hdf5Dialog.mainLayout = qt.QVBoxLayout(self.__hdf5Dialog)
+ self.__hdf5Dialog.mainLayout.setMargin(0)
+ self.__hdf5Dialog.mainLayout.setSpacing(0)
+ fileModel = HDF5Widget.FileModel()
+ fileView = HDF5Widget.HDF5Widget(fileModel)
+ hdf5File = fileModel.openFile(filename)
+ shiftsDataset = None
+ qt.QObject.connect(fileView, qt.SIGNAL("HDF5WidgetSignal"), self._hdf5WidgetSlot)
+ self.__hdf5Dialog.mainLayout.addWidget(fileView)
+ self.__hdf5Dialog.resize(400, 200)
+ ret = self.__hdf5Dialog.exec_()
+ if not ret:
+ return
+ shifts = hdf5File[self.__shitfsDataset].value
+ else:
+ sf = specfilewrapper.Specfile(filename)
+ nScans = len(sf)
+ targetScan = None
+ for scan in sf:
+ if scan.lines() == data.shape[stack.info['McaIndex']]:
+ targetScan = scan
+ break
+ if targetScan is None:
+ scan = None
+ sf = None
+ raise IOError("Number of read lines does not match stack shape")
+ shifts = targetScan.data()
+ targetScan = None
+ scan = None
+ sf = None
+ if shifts.shape[0] == 3 and\
+ shifts.shape[1] == data.shape[stack.info['McaIndex']]:
+ # one column was added (point number)
+ shifts = shifts[1:].T
+
+ filename = None
+ if not isinstance(data, numpy.ndarray):
+ filefilter = ['HDF5 Files (*.h5)']
+ filename = PyMcaFileDialogs.\
+ getFileList(parent=None,
+ filetypelist=filefilter,
+ message='Select output file',
+ mode='SAVE',
+ single=True,
+ getfilter=False,
+ currentfilter=filefilter[0])
+ if len(filename):
+ filename = filename[0]
+ if DEBUG:
+ print("file name = %s" % filename)
+ else:
+ raise IOError("No output file selected")
+ if filename is not None:
+ self.__hdf5 = self.initializeHDF5File(filename)
+ crop = False
+ if DEBUG:
+ result = self.shiftStack(stack,
+ shifts,
+ crop=crop,
+ filename=filename)
+ else:
+ result = self.__shiftStack(stack,
+ shifts,
+ crop=crop,
+ filename=filename)
+ if result is not None:
+ # exception occurred
+ raise Exception(result[1], result[2], result[3])
+
+ if filename is not None:
+ hdf = self.__hdf5
+ alignmentGroup = hdf['/entry_000/Alignment']
+ outputShifts = self.getHDF5BufferIntoGroup(alignmentGroup,
+ shape=(stack.data.shape[mcaIndex], 2),
+ name="shifts",
+ dtype=numpy.float32)
+ outputShifts[:,:] = shifts
+ attributes={'interpretation':'image'}
+ # fill the axes information
+ dataGroup = hdf['/entry_000/Data']
+ if mcaIndex == 0:
+ reference_shape = data[0].shape
+ else:
+ reference_shape = data.shape[0], data.shape[1]
+ try:
+ activeCurve = self.getActiveCurve()
+ if activeCurve is None:
+ activeCurve = self.getAllCurves()[0]
+ x, y, legend, info = activeCurve
+ dataGroup[info['xlabel']] = numpy.array(x, dtype=numpy.float32)
+ dataGroup[info['xlabel']].attrs['axis'] = numpy.int32(1)
+ axesAttribute = '%s:dim_1:dim_2' % info['xlabel']
+ except:
+ if DEBUG:
+ raise
+ dataGroup['dim_0'] = numpy.arange(stack.data.shape[mcaIndex]).astype(numpy.float32)
+ dataGroup['dim_0'].attrs['axis'] = numpy.int32(1)
+ axesAttribute = 'dim_0:dim_1:dim_2'
+ dataGroup['dim_1'] = numpy.arange(reference_shape[0]).astype(numpy.float32)
+ dataGroup['dim_1'].attrs['axis'] = numpy.int32(2)
+ dataGroup['dim_2'] = numpy.arange(reference_shape[1]).astype(numpy.float32)
+ dataGroup['dim_2'].attrs['axis'] = numpy.int32(3)
+ dim2 = numpy.arange(reference_shape[1]).astype(numpy.float32)
+ dataGroup['data'].attrs['axes'] = axesAttribute
+ self.finishHDF5File(hdf)
+ else:
+ self.setStack(stack)
+
+ def _hdf5WidgetSlot(self, ddict):
+ if ddict['event'] == "itemDoubleClicked":
+ if ddict['type'].lower() in ['dataset']:
+ self.__shitfsDataset = ddict['name']
+ self.__hdf5Dialog.accept()
+
def shiftStack(self, stack, shifts, crop=False, filename=None):
"""
"""
diff --git a/PyMca/PyMcaPlugins/MotorInfoPlugin.py b/PyMca/PyMcaPlugins/MotorInfoPlugin.py
index f7058e9..3e05965 100644
--- a/PyMca/PyMcaPlugins/MotorInfoPlugin.py
+++ b/PyMca/PyMcaPlugins/MotorInfoPlugin.py
@@ -1,3 +1,29 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
__author__ = 'Tonn Rueter'
try:
from PyMca import Plugin1DBase
diff --git a/PyMca/PyMcaPlugins/MotorInfoWindow.py b/PyMca/PyMcaPlugins/MotorInfoWindow.py
index cf41546..29814a8 100644
--- a/PyMca/PyMcaPlugins/MotorInfoWindow.py
+++ b/PyMca/PyMcaPlugins/MotorInfoWindow.py
@@ -1,3 +1,29 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
__author__ = 'Tonn Rueter'
from PyMca import PyMcaQt as qt
from PyMca.PyMca_Icons import IconDict
diff --git a/PyMca/PyMcaPlugins/StackAxesPlugin.py b/PyMca/PyMcaPlugins/StackAxesPlugin.py
index 1a2bf11..04fd401 100644
--- a/PyMca/PyMcaPlugins/StackAxesPlugin.py
+++ b/PyMca/PyMcaPlugins/StackAxesPlugin.py
@@ -57,19 +57,12 @@ functions:
selectionMaskUpdated
"""
import numpy
-if 1:#try:
- from PyMca import StackPluginBase
- from PyMca import PyMcaFileDialogs
- import PyMca.PyMca_Icons as PyMca_Icons
-else:#except ImportError:
- print("Plugin importing from somewhere else")
- import StackPluginBase
- import PyMcaFileDialogs
- import PyMca_Icons
+from PyMca import StackPluginBase
+from PyMca import PyMcaFileDialogs
+import PyMca.PyMca_Icons as PyMca_Icons
DEBUG = 0
-
class StackAxesPlugin(StackPluginBase.StackPluginBase):
def __init__(self, stackWindow, **kw):
StackPluginBase.DEBUG = DEBUG
@@ -79,8 +72,22 @@ class StackAxesPlugin(StackPluginBase.StackPluginBase):
function = self.replace1DAxisWithASCII
info = text
icon = None
- self.methodDict["1D axis from file"] = [function, info, icon]
- self.__methodKeys = ["1D axis from file"]
+ self.methodDict["1D axis from ASCII file"] = [function, info, icon]
+ self.__methodKeys = ["1D axis from ASCII file"]
+
+ function = self.replace1DAxisWithActiveCurveXValues
+ text = "Replace current 1D axis by X values in current MCA curve"
+ info = text
+ icon = None
+ self.methodDict["1D axis from MCA curve X values"] = [function, info, icon]
+ self.__methodKeys.append("1D axis from MCA curve X values")
+
+ function = self.replace1DAxisWithActiveCurveYValues
+ text = "Replace current 1D axis by Y values in current MCA curve"
+ info = text
+ icon = None
+ self.methodDict["1D axis from MCA curve Y values"] = [function, info, icon]
+ self.__methodKeys.append("1D axis from MCA curve Y values")
#Methods implemented by the plugin
def getMethods(self):
@@ -107,6 +114,7 @@ class StackAxesPlugin(StackPluginBase.StackPluginBase):
single=True)
if not len(fileList):
return
+
filename = fileList[0]
data = numpy.loadtxt(filename)
data.shape = -1
@@ -116,6 +124,32 @@ class StackAxesPlugin(StackPluginBase.StackPluginBase):
stack.x = [data]
self.setStack(stack, mcaindex=mcaIndex)
+ def replace1DAxisWithActiveCurveYValues(self):
+ stack = self.getStackDataObject()
+ mcaIndex = stack.info.get('McaIndex', -1)
+ nPoints = stack.data.shape[mcaIndex]
+ curve = self.getActiveCurve()
+ data = curve[1]
+ data.shape = -1
+ if data.size != nPoints:
+ raise ValueError("Number of read values not equal to %d" % nPoints)
+ else:
+ stack.x = [data]
+ self.setStack(stack, mcaindex=mcaIndex)
+
+ def replace1DAxisWithActiveCurveXValues(self):
+ stack = self.getStackDataObject()
+ mcaIndex = stack.info.get('McaIndex', -1)
+ nPoints = stack.data.shape[mcaIndex]
+ curve = self.getActiveCurve()
+ data = curve[0]
+ data.shape = -1
+ if data.size != nPoints:
+ raise ValueError("Number of read values not equal to %d" % nPoints)
+ else:
+ stack.x = [data]
+ self.setStack(stack, mcaindex=mcaIndex)
+
MENU_TEXT = "Stack Axes Options"
def getStackPluginInstance(stackWindow, **kw):
ob = StackAxesPlugin(stackWindow)
diff --git a/PyMca/PyMcaPlugins/StackScanWindowPlugin.py b/PyMca/PyMcaPlugins/StackScanWindowPlugin.py
index 4ea1e97..566fe89 100644
--- a/PyMca/PyMcaPlugins/StackScanWindowPlugin.py
+++ b/PyMca/PyMcaPlugins/StackScanWindowPlugin.py
@@ -1,3 +1,29 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
"""
A Stack plugin is a module that will be automatically added to the PyMca stack windows
diff --git a/PyMca/PyMcaPlugins/XMCDPlugin.py b/PyMca/PyMcaPlugins/XMCDPlugin.py
index dc1ae6c..bd426c9 100644
--- a/PyMca/PyMcaPlugins/XMCDPlugin.py
+++ b/PyMca/PyMcaPlugins/XMCDPlugin.py
@@ -1,3 +1,29 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
import PyMca.PyMca_Icons as PyMca_Icons
from PyMca import Plugin1DBase
from PyMca import XMCDWindow
@@ -52,7 +78,7 @@ class XMCDAnalysis(Plugin1DBase.Plugin1DBase):
self.widget = XMCDWindow.XMCDWidget(parent,
self._plotWindow,
beamline,
- nSelectors = 2)
+ nSelectors = 5)
MENU_TEXT = "XLD/XMCD Analysis"
diff --git a/PyMca/PyMcaSciPy/signal/mediantools.c b/PyMca/PyMcaSciPy/signal/mediantools.c
index 2396574..a4628da 100644
--- a/PyMca/PyMcaSciPy/signal/mediantools.c
+++ b/PyMca/PyMcaSciPy/signal/mediantools.c
@@ -6,6 +6,9 @@ is granted under the SciPy License.
*/
#include "Python.h"
+/* adding next line may raise errors ...
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include "numpy/noprefix.h"
#include <setjmp.h>
@@ -45,16 +48,6 @@ static struct module_state _state;
{struct module_state *st = GETSTATE(self);\
PyErr_SetString(st->error, message);goto fail;}
-#define DATA(arr) ((arr)->data)
-#define DIMS(arr) ((arr)->dimensions)
-#define STRIDES(arr) ((arr)->strides)
-#define ELSIZE(arr) ((arr)->descr->elsize)
-#define OBJECTTYPE(arr) ((arr)->descr->type_num)
-#define BASEOBJ(arr) ((PyArrayObject *)((arr)->base))
-#define RANK(arr) ((arr)->nd)
-#define ISCONTIGUOUS(m) ((m)->flags & CONTIGUOUS)
-
-
jmp_buf MALLOC_FAIL;
char *check_malloc (int);
@@ -103,18 +96,18 @@ static PyObject *mediantools_median2d(PyObject *self, PyObject *args)
if (a_image == NULL) goto fail;
if (size != NULL) {
- a_size = (PyArrayObject *)PyArray_ContiguousFromObject(size, PyArray_LONG, 1, 1);
+ a_size = (PyArrayObject *)PyArray_ContiguousFromObject(size, NPY_LONG, 1, 1);
if (a_size == NULL) goto fail;
- if ((RANK(a_size) != 1) || (DIMS(a_size)[0] < 2))
+ if ((PyArray_NDIM(a_size) != 1) || (PyArray_DIMS(a_size)[0] < 2))
PYERR("Size must be a length two sequence");
- lhelp = (long *) DATA(a_size);
+ lhelp = (long *) PyArray_DATA(a_size);
Nwin[0] = (int) (*lhelp);
Nwin[1] = (int) (*(lhelp++));
- Idims[0] = (int) (a_image->dimensions[0]);
- Idims[1] = (int) (a_image->dimensions[1]);
+ Idims[0] = (int) (PyArray_DIMS(a_image)[0]);
+ Idims[1] = (int) (PyArray_DIMS(a_image)[1]);
}
- a_out = (PyArrayObject *)PyArray_SimpleNew(2,DIMS(a_image),typenum);
+ a_out = (PyArrayObject *)PyArray_SimpleNew(2,PyArray_DIMS(a_image),typenum);
if (a_out == NULL) goto fail;
if (setjmp(MALLOC_FAIL)) {
@@ -122,41 +115,41 @@ static PyObject *mediantools_median2d(PyObject *self, PyObject *args)
}
else {
switch (typenum) {
- case PyArray_UBYTE:
- b_medfilt2((unsigned char *)DATA(a_image), (unsigned char *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_UBYTE:
+ b_medfilt2((unsigned char *)PyArray_DATA(a_image), (unsigned char *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_FLOAT:
- f_medfilt2((float *)DATA(a_image), (float *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_FLOAT:
+ f_medfilt2((float *)PyArray_DATA(a_image), (float *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_DOUBLE:
- d_medfilt2((double *)DATA(a_image), (double *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_DOUBLE:
+ d_medfilt2((double *)PyArray_DATA(a_image), (double *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_SHORT:
- short_medfilt2((short *)DATA(a_image), (short *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_SHORT:
+ short_medfilt2((short *)PyArray_DATA(a_image), (short *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_USHORT:
- ushort_medfilt2((unsigned short *)DATA(a_image), (unsigned short *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_USHORT:
+ ushort_medfilt2((unsigned short *)PyArray_DATA(a_image), (unsigned short *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_INT:
- int_medfilt2((int *)DATA(a_image), (int *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_INT:
+ int_medfilt2((int *)PyArray_DATA(a_image), (int *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_UINT:
- uint_medfilt2((unsigned int *)DATA(a_image), (unsigned int *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_UINT:
+ uint_medfilt2((unsigned int *)PyArray_DATA(a_image), (unsigned int *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_LONG:
- long_medfilt2((long *)DATA(a_image), (long *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_LONG:
+ long_medfilt2((long *)PyArray_DATA(a_image), (long *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
- case PyArray_ULONG:
- ulong_medfilt2((unsigned long *)DATA(a_image), (unsigned long *)DATA(a_out),\
- Nwin, Idims, conditional_flag);
+ case NPY_ULONG:
+ ulong_medfilt2((unsigned long *)PyArray_DATA(a_image), (unsigned long *)PyArray_DATA(a_out),\
+ Nwin, Idims, conditional_flag);
break;
default:
PYERR("Median filter unsupported data type.");
diff --git a/PyMca/PyMcaSciPy/signal/setup.py b/PyMca/PyMcaSciPy/signal/setup.py
deleted file mode 100644
index 05aaf80..0000000
--- a/PyMca/PyMcaSciPy/signal/setup.py
+++ /dev/null
@@ -1,19 +0,0 @@
-try:
- import numpy
-except ImportError:
- text = "You must have numpy installed.\n"
- text += "See http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103\n"
- raise ImportError(text)
-
-from distutils.core import setup
-from distutils.extension import Extension
-
-data_files = ('signal',['__init__.py', 'median.py'])
-setup( name = 'signal',
- ext_modules = [Extension(
- name = 'signal.mediantools',
- sources = ['mediantools.c', 'medianfilter.c'],
- define_macros = [],
- include_dirs = [numpy.get_include()]
- ),],
- data_files=data_files)
diff --git a/PyMca/QHDF5StackWizard.py b/PyMca/QHDF5StackWizard.py
index 18f09a9..e63bfb2 100644
--- a/PyMca/QHDF5StackWizard.py
+++ b/PyMca/QHDF5StackWizard.py
@@ -257,6 +257,14 @@ class DatasetSelectionPage(qt.QWizardPage):
ddict['counters'].append(path)
ddict['aliases'].append(posixpath.basename(axis))
+ if sys.platform == "darwin" and\
+ len(ddict['counters']) > 3 and\
+ qt.qVersion().startswith('4.8'):
+ # workaround a strange bug on Mac:
+ # when the counter list has to be scrolled
+ # the selected button also changes!!!!
+ return
+
self.nexusWidget.setWidgetConfiguration(ddict)
if len(signalList):
if len(axesList) == 0:
diff --git a/PyMca/QStackWidget.py b/PyMca/QStackWidget.py
index d9a37c9..d4032ea 100644
--- a/PyMca/QStackWidget.py
+++ b/PyMca/QStackWidget.py
@@ -598,7 +598,7 @@ class QStackWidget(StackBase.StackBase,
idx = 0
else:
actionList = []
- methods.sort()
+ #methods.sort()
menu = qt.QMenu(self)
for method in methods:
text = QString(method)
@@ -621,7 +621,7 @@ class QStackWidget(StackBase.StackBase,
if a.text() == action[0]:
idx = actionList.index(action)
try:
- self.pluginInstanceDict[key].applyMethod(methods[idx])
+ self.pluginInstanceDict[key].applyMethod(methods[idx])
except:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
diff --git a/PyMca/SGModule.py b/PyMca/SGModule.py
index 773b60a..364d62d 100644
--- a/PyMca/SGModule.py
+++ b/PyMca/SGModule.py
@@ -7,8 +7,30 @@
# and are very grateful to Uwe for making his code available to the
# community.
#
+# Copyright (C) 2008 Uwe Schmitt
#
-
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+__license__ = "MIT"
import numpy
from numpy.linalg import solve
diff --git a/PyMca/ScanWindow.py b/PyMca/ScanWindow.py
index e829cda..676b85f 100644
--- a/PyMca/ScanWindow.py
+++ b/PyMca/ScanWindow.py
@@ -1,5 +1,5 @@
#/*##########################################################################
-# Copyright (C) 2004-2012 European Synchrotron Radiation Facility
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
@@ -1721,6 +1721,12 @@ class ScanWindow(qt.QWidget, Plot1DBase.Plot1DBase):
else:
return self.graph.getY2AxisLimits()
+ def setGraphXLimits(self, xmin, xmax, replot=False):
+ return self.graph.setX1AxisLimits(xmin, xmax, replot=replot)
+
+ def setGraphYLimits(self, ymin, ymax, replot=False):
+ return self.graph.setY1AxisLimits(ymin, ymax, replot=replot)
+
def setActiveCurve(self, legend):
self.graph.setActiveCurve(legend)
ddict = {}
diff --git a/PyMca/SixCircle.py b/PyMca/SixCircle.py
index ac7a4d2..10d8554 100644
--- a/PyMca/SixCircle.py
+++ b/PyMca/SixCircle.py
@@ -1,172 +1,250 @@
#/*##########################################################################
-# Copyright (C) 2004-2012 European Synchrotron Radiation Facility
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
#
-# This toolkit 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
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
-# PyMca is distributed in the hope that it will be useful, but WITHOUT ANY
+# This file 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
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
-# You should have received a copy of the GNU General Public License along with
-# PyMca; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
-# used as a free plugin for a non-free program.
-#
# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
# is a problem for you.
#############################################################################*/
__author__ = "V.A. Sole - ESRF Data Analysis"
+__license__ = "LGPL"
+__doc__ = """
+Methods to convert single point or complete images to reciprocal space.
+It is fully vectorized and therefore very fast for converting complete
+images.
+"""
import numpy
+
cos = numpy.cos
sin = numpy.sin
+
class SixCircle(object):
def __init__(self):
self._energy = None
self._lambda = None
- self._K = 1.0
+ self._K = 1.0
+ self._ub = None
self.setLambda(1.0)
self.setUB([1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0])
def setUB(self, ublist):
+ """
+ :param ublist: the ub matrix element values
+ :type ublist: list(float)
+ """
self._ub = numpy.array(ublist).astype(numpy.float)
self._ub.shape = 3, 3
def getUB(self):
+ """
+ :return: the ub matrix element values
+ :rtype: list(float)
+ """
a = self._ub * 1
a.shape = -1
return a.tolist()
def setEnergy(self, energy):
"""
- setEnergy(self, energy)
- The energy has to be given in keV
+ :param energy: the energy to set in KeV
+ :type energy: float
"""
self._lambda = 12.39842 / energy
self._energy = energy
self.update()
def getEnergy(self):
+ """
+ :return: the energy in KeV
+ :rtype: float
+ """
return self._energy
def setLambda(self, value):
"""
- setLamabda(self, lambda)
- The wavelength has to be given in Angstroms
+ :param value: the wavelength to set in Angstroms
+ :type value: float
"""
self._lambda = value
self._energy = 12.39842 / value
self.update()
def getLambda(self):
+ """
+ :return: the wavelength in Angstroms
+ :rtype: float
+ """
return self._lambda
def update(self):
- self._K = (2*numpy.pi)/self._lambda
+ """
+ compute K from the wavelength value
+ """
+ self._K = (2 * numpy.pi) / self._lambda
def getPhiMatrix(self, phi):
- angle = phi * numpy.pi/180.
+ """
+ :param phi: the phi angle in degree
+ :type phi: float
+ :return: the rotation matrix of the phi axis for a given angle
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(phi)
cphi = cos(angle)
sphi = sin(angle)
- return numpy.array([[ cphi, sphi, 0.0],
+ return numpy.array([[cphi, sphi, 0.0],
[-sphi, cphi, 0.0],
- [ 0.0, 0.0, 1.0]],numpy.float)
+ [0.0, 0.0, 1.0]], numpy.float)
def getChiMatrix(self, chi):
- angle = chi * numpy.pi/180.
+ """
+ :param chi: the chi angle in degree
+ :type chi: float
+ :return: the rotation matrix of the chi
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(chi)
cchi = cos(angle)
schi = sin(angle)
- return numpy.array([[ cchi, 0.0, schi],
- [ 0.0, 1.0, 0.0],
+ return numpy.array([[cchi, 0.0, schi],
+ [0.0, 1.0, 0.0],
[-schi, 0.0, cchi]], numpy.float)
def getThetaMatrix(self, th):
- angle = th * numpy.pi/180.
+ """
+ :param th: the theta angle in Degree
+ :type th: float
+ :return: the rotation matrix of the theta axis
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(th)
cth = cos(angle)
sth = sin(angle)
- return numpy.array([[ cth, sth, 0],
- [-sth, cth, 0],
- [ 0, 0, 1]], numpy.float)
+ return numpy.array([[cth, sth, 0],
+ [-sth, cth, 0],
+ [0, 0, 1]], numpy.float)
def getDeltaMatrix(self, delta):
- angle = delta * numpy.pi/180.
+ """
+ :param delta: the delta angle in Degree
+ :type delta: float
+ :return: the rotation matrix of the delta axis
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(delta)
cdel = cos(angle)
sdel = sin(angle)
- return numpy.array([[ cdel, sdel, 0],
- [-sdel, cdel, 0],
- [ 0, 0, 1]], numpy.float)
+ return numpy.array([[cdel, sdel, 0],
+ [-sdel, cdel, 0],
+ [0, 0, 1]], numpy.float)
def getGammaMatrix(self, gamma):
- angle = gamma * numpy.pi/180.
+ """
+ :param gamma: the gamma angle in Degree
+ :type gamma: float
+ :return: the rotation matrix of the gamma axis
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(gamma)
cgam = cos(angle)
sgam = sin(angle)
- return numpy.array([[1.0, 0.0, 0.0],
- [0.0, cgam, -sgam],
- [0.0, sgam, cgam]], numpy.float)
+ return numpy.array([[1.0, 0.0, 0.0],
+ [0.0, cgam, -sgam],
+ [0.0, sgam, cgam]], numpy.float)
def getMuMatrix(self, mu):
- angle = mu * numpy.pi/180.
+ """
+ :param mu: the mu angle in degree
+ :type mu: float
+ :return: the rotation matrix of the mu axis
+ :rtype: numpy.ndarray
+ """
+ angle = numpy.radians(mu)
cmu = cos(angle)
smu = sin(angle)
- return numpy.array([[1.0, 0.0, 0.0],
- [0.0, cmu, -smu],
- [0.0, smu, cmu]], numpy.float)
-
+ return numpy.array([[1.0, 0.0, 0.0],
+ [0.0, cmu, -smu],
+ [0.0, smu, cmu]], numpy.float)
- def _getDeltaDotGammaMatrix(self, delta, gamma):
+ def _getDeltaDotGammaMatrix(self, delta, gamma, gamma_first=False):
"""
- Given a 1D array of delta values and a 1D array of gamma values
- returns an array of dimension (3, 3, ndelta_values * n_gamma_values)
+ :param delta: the delta angles in Degrees
+ :type delta: numpy.ndarray (1D)
+ :param gamma: the gamma values in Degrees
+ :type gamma: numpy.ndarray (1D)
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+ :return: all the rotation matrix of all the delta, gamma combinations
+ :rtype: numpy.ndarray (3x3, len(delta) * len(gamma))
"""
- delr = delta * numpy.pi/180.
- gamr = gamma * numpy.pi/180.
- if 0:
+ delr = numpy.radians(delta)
+ gamr = numpy.radians(gamma)
+ if gamma_first:
cgam, cdel = numpy.meshgrid(numpy.cos(gamr), numpy.cos(delr))
sgam, sdel = numpy.meshgrid(numpy.sin(gamr), numpy.sin(delr))
else:
#this is to give the same result as Didier and not the transpose
cdel, cgam = numpy.meshgrid(numpy.cos(delr), numpy.cos(gamr))
sdel, sgam = numpy.meshgrid(numpy.sin(delr), numpy.sin(gamr))
- deltaDotGamma = numpy.zeros((3, 3, len(delta), len(gamma)), numpy.float)
- #1st row of dot(deltamatrix, gammaMatrix)
- deltaDotGamma[0, 0, :] = cdel
- deltaDotGamma[0, 1, :] = (sdel * cgam)[:]
+ deltaDotGamma = numpy.zeros((3, 3, len(delta), len(gamma)),
+ numpy.float)
+ # 1st row of dot(deltamatrix, gammaMatrix)
+ deltaDotGamma[0, 0, :] = cdel
+ deltaDotGamma[0, 1, :] = (sdel * cgam)[:]
deltaDotGamma[0, 2, :] = -sdel * sgam
- #2nd row of dot(deltaMatrix, gammaMatrix)
+ # 2nd row of dot(deltaMatrix, gammaMatrix)
deltaDotGamma[1, 0, :] = -sdel
- deltaDotGamma[1, 1, :] = cdel * cgam
+ deltaDotGamma[1, 1, :] = cdel * cgam
deltaDotGamma[1, 2, :] = -cdel * sgam
- #3rd row of dot(deltaMatrix, gammaMatrix)
- deltaDotGamma[2, 0, :] = 0.0
- deltaDotGamma[2, 1, :] = sgam
- deltaDotGamma[2, 2, :] = cgam
- deltaDotGamma.shape = 3, 3, len(delta)*len(gamma)
+ # 3rd row of dot(deltaMatrix, gammaMatrix)
+ deltaDotGamma[2, 0, :] = 0.0
+ deltaDotGamma[2, 1, :] = sgam
+ deltaDotGamma[2, 2, :] = cgam
+ deltaDotGamma.shape = 3, 3, len(delta) * len(gamma)
+
return deltaDotGamma
- def getQMu(self, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.):
+ def getQMu(self, phi=0., chi=0., theta=0., mu=0.,
+ delta=0., gamma=0., gamma_first=False):
"""
- getQMu(self, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.)
-
- Angles given in degrees
-
+ :param phi: angle in Degrees
+ :type phi: float
+ :param chi: angle in Degrees
+ :type chi: float
+ :param theta: angle in Degrees
+ :type theta: float
+ :param mu: angle in Degrees
+ :type mu: float
+ :param delta: angle in Degrees
+ :type delta: float or numpy.ndarray
+ :param gamma: angle in Degrees
+ :type gamma: float or numpy.ndarray
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+
+ :return: Q coordinates for all the given delta, gamma values
+ :rtype: numpy.ndarray (len(delta), len(gamma), 3)
"""
PHIi = self.getPhiMatrix(phi).T
CHIi = self.getChiMatrix(chi).T
- THi = self.getThetaMatrix(theta).T
- MUi = self.getMuMatrix(mu).T
- tmpArray = numpy.dot(PHIi,numpy.dot(CHIi,numpy.dot(THi, MUi)))
- Q = self.getQLab(mu=mu, delta=delta, gamma=gamma)
+ THi = self.getThetaMatrix(theta).T
+ MUi = self.getMuMatrix(mu).T
+ tmpArray = numpy.dot(PHIi, numpy.dot(CHIi, numpy.dot(THi, MUi)))
+ Q = self.getQLab(mu=mu, delta=delta, gamma=gamma, gamma_first=gamma_first)
Q.shape = 3, -1
Q = numpy.transpose(numpy.dot(tmpArray, Q))
if type(delta) in [type(1.0), type(1)]:
@@ -180,38 +258,55 @@ class SixCircle(object):
Q.shape = lengamma, lendelta, 3
return Q
-
- def getQSurface(self, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.):
+ def getQSurface(self, phi=0., chi=0., theta=0., mu=0.,
+ delta=0., gamma=0., gamma_first=False):
"""
- getQSurface(self, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.)
-
- Angles given in degrees
+ :param phi: angle in Degrees
+ :type phi: float
+ :param chi: angle in Degrees
+ :type chi: float
+ :param theta: angle in Degrees
+ :type theta: float
+ :param mu: angle in Degrees
+ :type mu: float
+ :param delta: angle in Degrees
+ :type delta: float or numpy.ndarray
+ :param gamma: angle in Degrees
+ :type gamma: float or numpy.ndarray
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+
+ :return: Q values for all the given delta, gamma values
This is only true if the diffractometer has been properly aligned.
-
"""
PHIi = self.getPhiMatrix(phi).T
CHIi = self.getChiMatrix(chi).T
THi = self.getThetaMatrix(theta).T
MUi = self.getMuMatrix(mu).T
- tmpArray = numpy.dot(PHIi,numpy.dot(CHIi,numpy.dot(THi, MUi)))
- Q = self.getQLab(mu=mu, delta=delta, gamma=gamma)
+ tmpArray = numpy.dot(PHIi, numpy.dot(CHIi, numpy.dot(THi, MUi)))
+ Q = self.getQLab(mu=mu, delta=delta, gamma=gamma, gamma_first=gamma_first)
Q.shape = 3, -1
return (numpy.dot(tmpArray, Q))
- def getQLab(self, mu=0.0, delta=0.0, gamma=0.0):
+ def getQLab(self, mu=0.0, delta=0.0, gamma=0.0, gamma_first=False):
"""
- getQLab(self, mu=0.0, delta=0.0, gamma=0.0)
-
- Angles are given in degrees.
-
- The momentum transfer in the Lab system is
+ :param mu: angle in Degrees
+ :type mu: float
+ :param delta: angle in Degrees
+ :type delta: float or numpy.ndarray
+ :param gamma: angle in Degrees
+ :type gamma: float or numpy.ndarray
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+
+ :return: the Q coordinates in the Lab system
+ :rtype: numpy.ndarray ()
Q = Kf - Ki = (2 * pi / lambda) * (MU DELTA GAMMA - I) * (0, 1, 0)
This gives (transforming angles to radians):
-
(2*pi/lambda) * ( sin(delta) cos(gamma),
cos(mu) cos(delta) cos(gamma) - sin(mu) sin(gamma) - 1,
sin(mu) cos(delta) cos(gamma) + cos(mu) sin(gamma))
@@ -224,21 +319,23 @@ class SixCircle(object):
"""
- alpha = mu * (numpy.pi/180.)
+ alpha = numpy.radians(mu)
cmu = cos(alpha)
smu = sin(alpha)
- alpha = delta * (numpy.pi/180.)
+ alpha = numpy.radians(delta)
cdel = cos(alpha)
sdel = sin(alpha)
- alpha = gamma * (numpy.pi/180.)
+ alpha = numpy.radians(gamma)
cgam = cos(alpha)
sgam = sin(alpha)
- if isinstance(delta, numpy.ndarray) and isinstance(gamma, numpy.ndarray):
- if 0:
- cgam, cdel = numpy.meshgrid(cgam, cdelr)
- sgam, sdel = numpy.meshgrid(sgamr, sdel)
+
+ if isinstance(delta, numpy.ndarray) or \
+ isinstance(gamma, numpy.ndarray):
+ if gamma_first:
+ cgam, cdel = numpy.meshgrid(cgam, cdel)
+ sgam, sdel = numpy.meshgrid(sgam, sdel)
else:
- #this is to give the same result as Didier and not the transpose
+ # this is to give the same result as Didier and not the transpose
cdel, cgam = numpy.meshgrid(cdel, cgam)
sdel, sgam = numpy.meshgrid(sdel, sgam)
Q = numpy.zeros((3, sdel.shape[0], sdel.shape[1]), numpy.float)
@@ -246,76 +343,116 @@ class SixCircle(object):
Q[1, :, :] = cmu * cdel * cgam - smu * sgam - 1
Q[2, :, :] = smu * cdel * cgam + cmu * sgam
else:
- Q = numpy.zeros((3,1), numpy.float)
- Q[0,0] = sdel * cgam
- Q[1,0] = cmu * cdel * cgam - smu * sgam - 1
- Q[2,0] = smu * cdel * cgam + cmu * sgam
+ Q = numpy.zeros((3, 1), numpy.float)
+ Q[0, 0] = sdel * cgam
+ Q[1, 0] = cmu * cdel * cgam - smu * sgam - 1
+ Q[2, 0] = smu * cdel * cgam + cmu * sgam
return Q * self._K
- def getHKL(self, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.):
+ def getHKL(self, phi=0., chi=0., theta=0., mu=0.,
+ delta=0., gamma=0., gamma_first=False):
+ """
+ :param phi: angle in Degrees
+ :type phi: float
+ :param chi: angle in Degrees
+ :type chi: float
+ :param theta: angle in Degrees
+ :type theta: float
+ :param mu: angle in Degrees
+ :type mu: float
+ :param delta: angle in Degrees
+ :type delta: float or numpy.ndarray
+ :param gamma: angle in Degrees
+ :type gamma: float or numpy.ndarray
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+
+ :return: HKL values for all the given delta, gamma values
+ """
PHIi = self.getPhiMatrix(phi).T
CHIi = self.getChiMatrix(chi).T
- THi = self.getThetaMatrix(theta).T
- MUi = self.getMuMatrix(mu).T
+ THi = self.getThetaMatrix(theta).T
+ MUi = self.getMuMatrix(mu).T
UBi = numpy.linalg.inv(self._ub)
- tmpArray = numpy.dot(UBi,numpy.dot(PHIi,numpy.dot(CHIi,numpy.dot(THi, MUi))))
- Q = self.getQLab(mu=mu, delta=delta, gamma=gamma)
+ tmpArray = numpy.dot(UBi,
+ numpy.dot(PHIi,
+ numpy.dot(CHIi,
+ numpy.dot(THi, MUi))))
+ Q = self.getQLab(mu=mu, delta=delta, gamma=gamma, gamma_first=gamma_first)
Q.shape = 3, -1
return (numpy.dot(tmpArray, Q))
-def getHKL(wavelength, ub, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.):
+
+def getHKL(wavelength, ub, phi=0., chi=0., theta=0., mu=0.,
+ delta=0., gamma=0., gamma_first=False):
"""
- getHKL(wavelength, ub, phi=0., chi=0., theta=0., mu=0., delta=0., gamma=0.):
+ :param wavelength: the wavelength in Angstroms
+ :type wavelength: float
+ :param ub: the ub matrix element values
+ :type ub: list(float)
+ :param phi: angle in Degrees
+ :type phi: float
+ :param chi: angle in Degrees
+ :type chi: float
+ :param theta: angle in Degrees
+ :type theta: float
+ :param mu: angle in Degrees
+ :type mu: float
+ :param delta: angle in Degrees
+ :type delta: float or numpy.ndarray
+ :param gamma: angle in Degrees
+ :type gamma: float or numpy.ndarray
+ :param gamma_first: if delta and gamma are arrays, which one variates first.
+ :type gamma_first: boolean
+
+ :return: HKL values for all the given delta, gamma values
+
A convenience function that takes the whole input in one go
"""
a = SixCircle()
a.setLambda(wavelength)
a.setUB(ub)
- return a.getHKL(delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma)
+ return a.getHKL(delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma, gamma_first=gamma_first)
-if __name__ == "__main__":
+
+def main():
wavelength = 0.363504
- UB = [1.0, 0.0, 0.0,
+ UB = [1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0]
UB[0] = -4.080
- UB[1] = 0.000
- UB[2] = 0.000
- UB[3] = 0.000
- UB[4] = 4.080
- UB[5] = 0.000
- UB[6] = 0.000
- UB[7] = 0.000
- UB[8] = -4.080
+ UB[1] = 0.000
+ UB[2] = 0.000
+ UB[3] = 0.000
+ UB[4] = 4.080
+ UB[5] = 0.000
+ UB[6] = 0.000
+ UB[7] = 0.000
+ UB[8] = -4.080
d = SixCircle()
d.setLambda(wavelength)
d.setUB(UB)
print("H = 0 K = 0 L = 1")
delta, theta, chi, phi, mu, gamma = 13.5558, 6.77779, -90, 0.0, 0.0, 0.0
- print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
+ print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma))
print("H = 0 K = 1 L = 0")
delta, theta, chi, phi, mu, gamma = 13.5558, 96.77779, -90, 0.0, 0.0, 0.0
- print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
+ print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma))
print("H = 1 K = 1 L = 1")
delta, theta, chi, phi, mu, gamma = 23.5910, 47.0595, -135., 0.0, 0.0, 0.0
- print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
+ print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma))
print("H = 2 K = -1 L = 0")
delta, theta, chi, phi, mu, gamma = 30.6035, -11.2635, 180.0, 0.0, 0.0, 0.0
- print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
+ print(d.getHKL(delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma))
print("H = 2 K = -1 L = 0")
- print(getHKL(wavelength, UB, delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
-
- if 0:
- print("DIDIER Image")
- wavelength = 1.12711884437
- UB = [1.99593e-16, 2.73682e-16, -1.54, -1.08894, 1.08894, 1.6083e-16, 1.08894, 1.08894, 9.28619e-17]
- chi = 90.
- phi = -13.3
- theta = -5.53
- mu = 0.0
- gamma = 12.3
- delta = 23.23
- print(getHKL(wavelength, UB, delta=delta, theta=theta, chi=chi, phi=phi, mu=mu, gamma=gamma))
-
+ print(getHKL(wavelength, UB, delta=delta, theta=theta, chi=chi, phi=phi,
+ mu=mu, gamma=gamma))
+if __name__ == "__main__":
+ main()
diff --git a/PyMca/StackSelector.py b/PyMca/StackSelector.py
index 7fcb0f6..33f713d 100644
--- a/PyMca/StackSelector.py
+++ b/PyMca/StackSelector.py
@@ -31,6 +31,7 @@ import copy
from PyMca import PyMcaQt as qt
from PyMca import PyMcaDirs
from PyMca import DataObject
+from PyMca import MRCMap
from PyMca import OmnicMap
from PyMca import OpusDPTMap
from PyMca import LuciaMap
@@ -64,7 +65,7 @@ class StackSelector(object):
if not len(filelist):
return None
- if filefilter == "":
+ if filefilter in ["", "All Files (*)"]:
if HDF5:
if h5py.is_hdf5(filelist[0]):
filefilter = "HDF5"
@@ -82,7 +83,11 @@ class StackSelector(object):
if sys.version < '3.0':
line = f.read(10)
else:
- line = str(f.read(10).decode())
+ try:
+ line = str(f.read(10).decode())
+ except UnicodeDecodeError:
+ #give a dummy value
+ line = " "
f.close()
omnicfile = False
if filefilter.upper().startswith('HDF5'):
@@ -150,6 +155,10 @@ class StackSelector(object):
#Roper Scientific format
#handle it as MarCCD stack
stack = QStack(imagestack=True)
+ elif MRCMap.isMRCFile(filelist[0]):
+ stack = MRCMap.MRCMap(filelist[0])
+ omnicfile = True
+ imagestack = True
else:
stack = QSpecFileStack()
@@ -385,6 +394,7 @@ class StackSelector(object):
"OPUS-DPT Files (*.DPT *.dpt)",
"AIFIRA Files (*DAT)",
"SupaVisio Files (*pige *pixe *rbs)",
+ "MRC files (*.mrc *.st)",
"All Files (*)"]
if not HDF5:
idx = fileTypeList.index("HDF5 Files (*.nxs *.hdf *.h5)")
diff --git a/PyMca/XMCDWindow.py b/PyMca/XMCDWindow.py
index d554699..3330259 100644
--- a/PyMca/XMCDWindow.py
+++ b/PyMca/XMCDWindow.py
@@ -1,19 +1,56 @@
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+__author__ = "T. Rueter - ESRF Data Analysis"
import numpy, copy
+from os.path import splitext, basename, dirname, exists, join as pathjoin
from PyMca.PyMca_Icons import IconDict
from PyMca import PyMcaDirs, PyMcaFileDialogs
from PyMca import ConfigDict
-from os.path import splitext, basename, dirname, exists, join as pathjoin
from PyMca import PyMcaQt as qt
from PyMca import specfilewrapper as specfile
-
+from PyMca import PyMcaDataDir
from PyMca import ScanWindow as sw
+if hasattr(qt, "QString"):
+ QString = qt.QString
+ QStringList = qt.QStringList
+else:
+ QString = str
+ QStringList = list
+
DEBUG = 0
if DEBUG:
numpy.set_printoptions(threshold=50)
NEWLINE = '\n'
class TreeWidgetItem(qt.QTreeWidgetItem):
+
+ __legendColumn = 1
+
def __init__(self, parent, itemList):
qt.QTreeWidgetItem.__init__(self, parent, itemList)
@@ -23,7 +60,7 @@ class TreeWidgetItem(qt.QTreeWidgetItem):
valOther = other.text(col)
if val == '---':
ret = True
- elif col > 0:
+ elif col > self.__legendColumn:
try:
ret = (float(val) < float(valOther))
except ValueError:
@@ -43,10 +80,14 @@ class XMCDOptions(qt.QDialog):
# Buttons
buttonOK = qt.QPushButton('OK')
+ buttonOK.setToolTip('Accept the configuration')
buttonCancel = qt.QPushButton('Cancel')
+ buttonCancel.setToolTip('Return to XMCD Analysis\nwithout changes')
if full:
buttonSave = qt.QPushButton('Save')
+ buttonSave.setToolTip('Save configuration to *.cfg-File')
buttonLoad = qt.QPushButton('Load')
+ buttonLoad.setToolTip('Load existing configuration from *.cfg-File')
# OptionLists and ButtonGroups
# GroupBox can be generated from self.getGroupBox
@@ -60,20 +101,23 @@ class XMCDOptions(qt.QDialog):
normBG = qt.QButtonGroup(self)
xrangeBG = qt.QButtonGroup(self)
# ComboBoxes
- normMeth = self.getComboBox(['(y-min(y))/trapz(max(y)-min(y),x)',
- 'y/max(y)',
- '(y-min(y))/(max(y)-min(y))',
- '(y-min(y))/sum(max(y)-min(y))'])
+ normMeth = qt.QComboBox()
+ normMeth.addItems(['(y-min(y))/trapz(max(y)-min(y),x)',
+ 'y/max(y)',
+ '(y-min(y))/(max(y)-min(y))',
+ '(y-min(y))/sum(max(y)-min(y))'])
normMeth.setEnabled(False)
- motor0 = self.getComboBox(mList)
- motor1 = self.getComboBox(mList)
self.optsDict = {
'normalization' : normBG,
'normalizationMethod' : normMeth,
- 'xrange' : xrangeBG,
- 'motor0': motor0,
- 'motor1': motor1
+ 'xrange' : xrangeBG
}
+ for idx in range(5):
+ # key: motor0, motor1, ...
+ key = 'motor%d'%idx
+ tmp = qt.QComboBox()
+ tmp.addItems(mList)
+ self.optsDict[key] = tmp
# Subdivide into GroupBoxes
normGroupBox = self.getGroupBox('Normalization',
normOpts,
@@ -95,10 +139,11 @@ class XMCDOptions(qt.QDialog):
buttonLayout.addWidget(buttonCancel)
normLayout.addWidget(qt.QLabel('Method:'))
normLayout.addWidget(normMeth)
- motorLayout.addWidget(qt.QLabel('Motor 1:'),0,0)
- motorLayout.addWidget(motor0,0,1)
- motorLayout.addWidget(qt.QLabel('Motor 2:'),1,0)
- motorLayout.addWidget(motor1,1,1)
+ for idx in range(5):
+ label = qt.QLabel('Motor %d:'%(idx+1))
+ cbox = self.optsDict['motor%d'%idx]
+ motorLayout.addWidget(label,idx,0)
+ motorLayout.addWidget(cbox,idx,1)
motorGroupBox.setLayout(motorLayout)
normGroupBox.layout().addLayout(normLayout)
mainLayout.addWidget(normGroupBox)
@@ -121,6 +166,8 @@ class XMCDOptions(qt.QDialog):
normBG.button(0).toggled.connect(normMeth.setDisabled)
def showEvent(self, event):
+ # Plugin does not destroy Options Window when accepted
+ # Reset self.saved manually
self.saved = False
qt.QDialog.showEvent(self, event)
@@ -137,11 +184,6 @@ class XMCDOptions(qt.QDialog):
# Motor not found in Motorlist, set to default
obj.setCurrentIndex(idx)
- def getComboBox(self, itemList):
- tmp = qt.QComboBox()
- tmp.addItems(itemList)
- return tmp
-
def getGroupBox(self, title, optionList, buttongroup=None):
'''
title : string
@@ -178,7 +220,7 @@ class XMCDOptions(qt.QDialog):
'offsetAndCounts' : r'(y-min(y))/sum(max(y)-min(y))',
'offsetAndArea' : r'(y-min(y))/trapz(max(y)-min(y),x)'
}
- for (name, eq) in normDict.iteritems():
+ for (name, eq) in normDict.items():
if ident == name:
return eq
if ident == eq:
@@ -299,9 +341,9 @@ class XMCDOptions(qt.QDialog):
name = ddict[option]
if option == 'normalizationMethod':
name = self.normalizationMethod(name)
- if option.startswith('Motor') and name=='None':
+ if option.startswith('Motor') and name == 'None':
name = ''
- idx = obj.findText(qt.QString(name))
+ idx = obj.findText(QString(name))
obj.setCurrentIndex(idx)
elif isinstance(obj, qt.QButtonGroup):
try:
@@ -315,11 +357,20 @@ class XMCDOptions(qt.QDialog):
class XMCDScanWindow(sw.ScanWindow):
plotModifiedSignal = qt.pyqtSignal()
- saveOptionsSignal = qt.pyqtSignal('QString')
+ saveOptionsSignal = qt.pyqtSignal('QString')
def __init__(self,
origin,
parent=None):
+ '''
+ Input
+ -----
+
+ origin : ScanWindow instance
+ Plot window containing the data on which
+ the analysis is performed
+ parent : QWidgit instance
+ '''
sw.ScanWindow.__init__(self,
parent,
name='XLD/XMCD Analysis',
@@ -330,25 +381,24 @@ class XMCDScanWindow(sw.ScanWindow):
# Buttons to push spectra to main Window
buttonWidget = qt.QWidget()
buttonAdd = qt.QPushButton('Add', self)
- buttonAdd.setToolTip('Add active curve to scan window')
+ buttonAdd.setToolTip('Add active curve to main window')
buttonReplace = qt.QPushButton('Replace', self)
- buttonReplace.setToolTip('Replace all curves in scan window with active curve')
+ buttonReplace.setToolTip(
+ 'Replace all curves in main window '
+ +'with active curve in analysis window')
buttonAddAll = qt.QPushButton('Add all', self)
- buttonAddAll.setToolTip('Add all curves to scan window')
+ buttonAddAll.setToolTip(
+ 'Add all curves in analysis window '
+ +'to main window')
buttonReplaceAll = qt.QPushButton('Replace all', self)
- buttonReplaceAll.setToolTip('Replace all curves in scan window with all curves')
- buttonLayout = qt.QHBoxLayout(None)
- buttonLayout.setContentsMargins(0, 0, 0, 0)
- buttonLayout.setSpacing(5)
- # Show XAS & XMCD Buttons
- buttonLayout.addWidget(qt.HorizontalSpacer(self))
- buttonLayout.addWidget(buttonAdd)
- buttonLayout.addWidget(buttonAddAll)
- buttonLayout.addWidget(buttonReplace)
- buttonLayout.addWidget(buttonReplaceAll)
- buttonWidget.setLayout(buttonLayout)
-# self.mainLayout.addLayout(buttonLayout)
- self.mainLayout.addWidget(buttonWidget)
+ buttonReplaceAll.setToolTip(
+ 'Replace all curves in main window '
+ +'with all curves from analysis window')
+ self.graphBottomLayout.addWidget(qt.HorizontalSpacer())
+ self.graphBottomLayout.addWidget(buttonAdd)
+ self.graphBottomLayout.addWidget(buttonAddAll)
+ self.graphBottomLayout.addWidget(buttonReplace)
+ self.graphBottomLayout.addWidget(buttonReplaceAll)
buttonAdd.clicked.connect(self.add)
buttonReplace.clicked.connect(self.replace)
@@ -366,7 +416,8 @@ class XMCDScanWindow(sw.ScanWindow):
'normalizationMethod' : self.NormOffsetAndArea
}
self.xRange = None
- # Keep track of Averages, XMCD and XAS curves
+
+ # Keep track of Averages, XMCD and XAS curves by label
self.avgA = None
self.avgB = None
self.xmcd = None
@@ -396,9 +447,9 @@ class XMCDScanWindow(sw.ScanWindow):
tmp['normalizationMethod'] = self.setNormalizationMethod(normMethod)
# Trigger reclaculation
self.optsDict = tmp
- msel = self.selectionDict['A']
- psel = self.selectionDict['B']
- self.processSelection(msel, psel)
+ groupA = self.selectionDict['A']
+ groupB = self.selectionDict['B']
+ self.processSelection(groupA, groupB)
def setNormalizationMethod(self, fname):
if fname == 'toMaximum':
@@ -423,14 +474,12 @@ class XMCDScanWindow(sw.ScanWindow):
return ynorm
def NormOffsetAndCounts(self, x, y):
- # Check for non-zero values?
ynorm = y - numpy.min(y)
ymax = numpy.sum(ynorm)
ynorm /= ymax
return ynorm
def NormOffsetAndArea(self, x, y):
- # Check for non-zero values?
ynorm = y - numpy.min(y)
ymax = numpy.trapz(ynorm, x)
ynorm /= ymax
@@ -443,38 +492,27 @@ class XMCDScanWindow(sw.ScanWindow):
'''
Input
-----
- fromCurves : Bool
- Uses curves present in self.curvesDict
- if set to true. If set to false, an
- ndarray with equistant interpolation
- points is returned
+ xRange : ndarray
+ x-range on which all curves are interpolated
+ If set to none, the first curve in xRangeList
+ is used
+ equidistant : Bool
+ Determines equidistant xrange on which
+ all curves are interpolated
xRangeList : List
- List of ndarray from whose the overlap
- is determined
-
- Checks dataObjectsDictionary for curves
- present in the ScanWindow and tries to
- find the overlap in the x-range of these
- curves.
-
- If equidistant is True:
- The x-ranges of the curves containing
- the minmal resp. the maximal x-value are
- used to determine the minimal number of
- points (n) in their overlap in order to
- avoid oversampling.
+ List of ndarray from which the overlap
+ is determined. If set to none, self.curvesDict
+ is used.
- If equidistant is False:
- If an active curve in the plotWindow is
- set, its xRange is used as interpolation
- points. If not active curve is set, the
- first curve in the scan sequence is taken
+ Determines the interpolation x-range used for XMCD
+ Analysis specified by the provided parameters. The
+ interpolation x-range is limited by the maximal
+ overlap between the curves present in the plot window.
Returns
-------
out : numpy array
- (Evenly spaced) x-range between xmin and
- xmax containing n points
+ x-range between xmin and xmax containing n points
'''
if not xRangeList:
# Default xRangeList: curvesDict sorted for legends
@@ -508,13 +546,14 @@ class XMCDScanWindow(sw.ScanWindow):
x = xRange
else:
x = xRangeList[0]
+ # Ensure monotonically increasing x-range
+ if not numpy.all(numpy.diff(x)>0.):
+ mask = numpy.nonzero(numpy.diff(x)>0.)[0]
+ x = numpy.take(x, mask)
+ # Exclude the endpoints
mask = numpy.nonzero((x > xmin) &
(x < xmax))[0]
out = numpy.sort(numpy.take(x, mask))
- # Remove remaining duplicates
- if not numpy.all(numpy.diff(out) > 0.):
- mask = numpy.nonzero(numpy.diff(out)>0.)[0]
- out = numpy.take(out, mask)
if DEBUG:
print('interpXRange -- Resulting xrange:')
print('\tmin = %f' % out.min())
@@ -522,14 +561,23 @@ class XMCDScanWindow(sw.ScanWindow):
print('\tnum = %f' % len(out))
return out
- def processSelection(self, msel, psel):
+ def processSelection(self, groupA, groupB):
+ '''
+ Input
+ -----
+ groupA, groupB : Lists of strings
+ Contain the legends of curves selected
+ to Group A resp. B
+ '''
+ # Clear analysis window
all = self.getAllCurves(just_legend=True)
self.removeCurves(all)
self.avgB, self.avgA = None, None
+ self.xas, self.xmcd = None, None
- self.selectionDict['A'] = msel[:]
- self.selectionDict['B'] = psel[:]
- self.curvesDict = self.copyCurves(msel + psel)
+ self.selectionDict['A'] = groupA[:]
+ self.selectionDict['B'] = groupB[:]
+ self.curvesDict = self.copyCurves(groupA + groupB)
if (len(self.curvesDict) == 0) or\
((len(self.selectionDict['A']) == 0) and\
@@ -602,9 +650,16 @@ class XMCDScanWindow(sw.ScanWindow):
def copyCurves(self, selection):
'''
+ Input
+ -----
selection : List
- Contains names of curves to be processed
-
+ Contains legends of curves to be processed
+
+ Creates a deep copy of the curves present in the
+ plot window. In order to avoid interpolation
+ errors later on, it is ensured that the xranges
+ of the data is strictly monotonically increasing.
+
Returns
-------
out : Dictionary
@@ -617,7 +672,25 @@ class XMCDScanWindow(sw.ScanWindow):
for legend in selection:
tmp = self.plotWindow.dataObjectsDict.get(legend, None)
if tmp:
- out[legend] = copy.deepcopy(tmp)
+ tmp = copy.deepcopy(tmp)
+ xarr, yarr = tmp.x, tmp.y
+ #if len(tmp.x) == len(tmp.y):
+ xprocArr, yprocArr = [], []
+ for (x,y) in zip(xarr,yarr):
+ # Sort
+ idx = numpy.argsort(x, kind='mergesort')
+ xproc = numpy.take(x, idx)
+ yproc = numpy.take(y, idx)
+ # Ravel, Increase
+ xproc = xproc.ravel()
+ idx = numpy.nonzero((xproc[1:] > xproc[:-1]))[0]
+ xproc = numpy.take(xproc, idx)
+ yproc = numpy.take(yproc, idx)
+ xprocArr += [xproc]
+ yprocArr += [yproc]
+ tmp.x = xprocArr
+ tmp.y = yprocArr
+ out[legend] = tmp
else:
# TODO: Errorhandling, curve not found
if DEBUG:
@@ -732,8 +805,6 @@ class XMCDScanWindow(sw.ScanWindow):
pass
elif len(labelNames) == 2:
[xlabel, ylabel] = labelNames
-# print 'extractLabels -- using labelNames'
-# print '\t',labelNames
elif sel:
xsel = sel.get('x',[])
ysel = sel.get('y',[])
@@ -743,9 +814,6 @@ class XMCDScanWindow(sw.ScanWindow):
if len(ysel) > 0:
y = ysel[0]
ylabel = labelNames[y]
-# print 'extractLabels -- xsel, ysel:'
-# print '\txsel: ', xsel
-# print '\tysel: ', ysel
return xlabel, ylabel
def performXAS(self):
@@ -819,18 +887,11 @@ class XMCDScanWindow(sw.ScanWindow):
def _saveIconSignal(self):
saveDir = PyMcaDirs.outputDir
-# filter = ['spec File (*.spec)','Any File (*.*)']
- ffilter = 'spec File (*.spec);;Any File (*.*)'
+ filter = 'spec File (*.spec);;Any File (*.*)'
try:
- # filename = PyMcaFileDialogs.\
- # getFileList(parent=self,
- # filetypelist=filter,
- # message='Save XMCD Analysis',
- # mode='SAVE',
- # single=True)[0]
(filelist, append, comment) = getSaveFileName(parent=self,
caption='Save XMCD Analysis',
- filter=ffilter,
+ filter=filter,
directory=saveDir)
filename = filelist[0]
except IndexError:
@@ -841,7 +902,7 @@ class XMCDScanWindow(sw.ScanWindow):
return
if append:
- specf = specfile.Specfile(filename)
+ specf = specfile.Specfile(filename)
scanno = specf.scanno() + 1
else:
scanno = 1
@@ -852,17 +913,41 @@ class XMCDScanWindow(sw.ScanWindow):
filename += ext
try:
if append:
- filehandle = open(filename, 'ab') #
sepFile = splitext(basename(filename))
- sepFilename = sepFile[0] + '_%.2d'%scanno + sepFile[1]
- sepFileName = pathjoin(dirname(filename),sepFilename)
- # TODO: Check if sepFilename exists
+ sepFileName = sepFile[0] + '_%.2d'%scanno + sepFile[1]
+ sepFileName = pathjoin(dirname(filename),sepFileName)
+ if scanno == 2:
+ # Case: Scan appended to file containing
+ # a single scan. Make sure, that the first
+ # scan is also written to seperate file and
+ # the corresponding cfg-file is copied
+ # 1. Create filename of first scan
+ sepFirstFileName = sepFile[0] + '_01' + sepFile[1]
+ sepFirstFileName = pathjoin(dirname(filename),sepFirstFileName)
+ # 2. Guess filename of first config
+ confname = sepFile[0] + '.cfg'
+ confname = pathjoin(dirname(filename),confname)
+ # 3. Create new filename of first config
+ sepFirstConfName = sepFile[0] + '_01' + '.cfg'
+ sepFirstConfName = pathjoin(dirname(filename),sepFirstConfName)
+ # Copy contents
+ firstSeperateFile = open(sepFirstFileName, 'wb')
+ firstSeperateConf = open(sepFirstConfName, 'wb')
+ filehandle = open(filename, 'rb')
+ confhandle = open(confname, 'rb')
+ firstFile = filehandle.read()
+ firstConf = confhandle.read()
+ firstSeperateFile.write(firstFile)
+ firstSeperateConf.write(firstConf)
+ firstSeperateFile.close()
+ firstSeperateConf.close()
+ filehandle = open(filename, 'ab')
seperateFile = open(sepFileName, 'wb')
else:
filehandle = open(filename, 'wb')
seperateFile = None
except IOError:
- msg = qt.QMessageBox(text="Unable to write to '%s'"%filename)
+ msg = qt.QMessageBox(text="Unable to open '%s'"%filename)
msg.exec_()
return
@@ -920,29 +1005,18 @@ class XMCDScanWindow(sw.ScanWindow):
if seperateFile is not None:
self.saveOptionsSignal.emit(splitext(sepFileName)[0])
- #def noiseFilter(self, y):
- # size = asarray([3] * len(y.shape))
- # mean = numpy.correlate(y, ones(size), 'same') / product(size, axis=0)
- # var = (numpy.correlate(y**2, ones(size), 'same') / product(size, axis=0)\
- # - mean**2)
- # noise = numpy.mean(numpy.ravel(var), axis=0)
- # filt = y - mean
- # filt *= (1 - noise/var)
- # filt += mean
- # out = numpy.where(var < noise, mean, res)
- # return out
-
def add(self):
activeCurve = self.getActiveCurve()
if activeCurve is None:
return
(xVal, yVal, legend, info) = activeCurve
- if 'selectionlegend' in info:
- newLegend = info['selectionlegend']
- elif 'operation' in info:
- newLegend = (str(operation) + ' ' + self.title)
- else:
- newLegend = (legend + ' ' + self.title)
+ #if 'selectionlegend' in info:
+ # newLegend = info['selectionlegend']
+ #elif 'operation' in info:
+ # newLegend = (str(operation) + ' ' + self.title)
+ #else:
+ # newLegend = (legend + ' ' + self.title)
+ newLegend = legend
self.plotWindow.addCurve(xVal,
yVal,
newLegend,
@@ -951,12 +1025,13 @@ class XMCDScanWindow(sw.ScanWindow):
def addAll(self):
for (xVal, yVal, legend, info) in self.getAllCurves():
- if 'selectionlegend' in info:
- newLegend = info['selectionlegend']
- elif 'operation' in info:
- newLegend = (str(operation) + ' ' + self.title)
- else:
- newLegend = (legend + ' ' + self.title)
+ #if 'selectionlegend' in info:
+ # newLegend = info['selectionlegend']
+ #elif 'operation' in info:
+ # newLegend = (str(operation) + ' ' + self.title)
+ #else:
+ # newLegend = (legend + ' ' + self.title)
+ newLegend = legend
self.plotWindow.addCurve(xVal,
yVal,
newLegend,
@@ -983,14 +1058,14 @@ class XMCDScanWindow(sw.ScanWindow):
def replaceAll(self):
allCurves = self.getAllCurves()
- for (i, (xVal, yVal, legend, info)) in enumerate(allCurves):
+ for (idx, (xVal, yVal, legend, info)) in enumerate(allCurves):
if 'selectionlegend' in info:
newLegend = info['selectionlegend']
elif 'operation' in info:
newLegend = (str(operation) + ' ' + self.title)
else:
newLegend = (legend + ' ' + self.title)
- if i == 0:
+ if idx == 0:
self.plotWindow.addCurve(xVal,
yVal,
newLegend,
@@ -1003,20 +1078,6 @@ class XMCDScanWindow(sw.ScanWindow):
info)
self.plotModifiedSignal.emit()
- def detrend(self):
- for (k,v) in self.dataObjectsDict.items():
- if k.startswith('XMCD'):
- xmcd = v
- xmcdLegend = k
- break
- xmcd = self.dataObjectsDict[xmcdLegend]
- x = xmcd.x[0]
- y = xmcd.y[0]
- a, b = numpy.polyfit(x,y,1)
- ynew = y - a*x - b
- y = ynew
- self.graph.checky2scale()
-
class XMCDMenu(qt.QMenu):
def __init__(self, parent, title=None):
qt.QMenu.__init__(self, parent)
@@ -1047,6 +1108,10 @@ class XMCDMenu(qt.QMenu):
class XMCDTreeWidget(qt.QTreeWidget):
+ __colGroup = 0
+ __colLegend = 1
+ __colScanNo = 2
+ __colCounter = 3
selectionModifiedSignal = qt.pyqtSignal()
def __init__(self, parent, groups = ['B','A','D'], color=True):
@@ -1067,7 +1132,7 @@ class XMCDTreeWidget(qt.QTreeWidget):
width = vscrollbar.width()
for i in range(self.columnCount()):
width += (2 + self.columnWidth(i))
- return qt.QSize( width, 200 )
+ return qt.QSize( width, 20*22)
def setContextMenu(self, menu):
self.contextMenu = menu
@@ -1147,32 +1212,32 @@ class XMCDTreeWidget(qt.QTreeWidget):
items must be of type [QStringList] (List of Lists)
'''
# Remember selection, then clear list
- sel = self.getColumn(1, True)
+ sel = self.getColumn(self.__colLegend, True)
self.clear()
self.setHeaderLabels(headerLabels)
for item in items:
treeItem = TreeWidgetItem(self, item)
if self.color:
- idx = str(treeItem.text(0))
+ idx = str(treeItem.text(self.__colGroup))
for i in range(self.columnCount()):
treeItem.setBackground(i, self.colorDict[idx])
- if treeItem.text(1) in sel:
+ if treeItem.text(self.__colLegend) in sel:
treeItem.setSelected(True)
- self.resizeColumnToContents(0)
- self.resizeColumnToContents(1)
def setSelectionAs(self, idx):
'''
Sets the items currently selected to
- the identifier given in id.
+ the identifier given in idx.
'''
if idx not in self.groupList:
raise ValueError('XMCDTreeWidget: invalid identifer \'%s\'' % idx)
sel = self.selectedItems()
if idx == self.groupList[-1]:
+ # Last identifier in self.groupList
+ # is the dummy identifier
idx = ''
for item in sel:
- item.setText(0, idx)
+ item.setText(self.__colGroup, idx)
if self.color:
for i in range(self.columnCount()):
item.setBackground(i, self.colorDict[idx])
@@ -1180,8 +1245,8 @@ class XMCDTreeWidget(qt.QTreeWidget):
def setSelectionToSequence(self, seq=None, selectedOnly=False):
'''
- Sets the id column (col 0) to seq. If
- sequence is None, a dialog window is
+ Sets the group column (col 0) to seq.
+ If sequence is None, a dialog window is
shown.
'''
chk = True
@@ -1190,14 +1255,15 @@ class XMCDTreeWidget(qt.QTreeWidget):
else:
root = self.invisibleRootItem()
sel = [root.child(i) for i in range(root.childCount())]
- # Ensure alphabetically ordered list
- self.sortItems(1, qt.Qt.AscendingOrder)
+ # Try to sort for scanNo
+ #self.sortItems(self.__colLegend, qt.Qt.AscendingOrder)
+ self.sortItems(self.__colScanNo, qt.Qt.AscendingOrder)
if not seq:
seq, chk = qt.QInputDialog.\
getText(None,
'Sequence Dialog',
'Valid identifiers are: ' + ', '.join(self.groupList),
- qt.QLineEdit.Normal,
+ qt.QLineEdit.Normal,
'Enter sequence')
seq = str(seq).upper()
if not chk:
@@ -1212,14 +1278,14 @@ class XMCDTreeWidget(qt.QTreeWidget):
if len(sel) != len(seq):
# Assume pattern and repeat
seq = seq * (len(sel)//len(seq) + 1)
- # invalidMsg = qt.QMessageBox(None)
- # invalidMsg.setText('Sequence length does not match item count.')
- # invalidMsg.setStandardButtons(qt.QMessageBox.Ok)
- # invalidMsg.exec_()
+ #invalidMsg = qt.QMessageBox(None)
+ #invalidMsg.setText('Sequence length does not match item count.')
+ #invalidMsg.setStandardButtons(qt.QMessageBox.Ok)
+ #invalidMsg.exec_()
for (idx, item) in zip(seq, sel):
if idx == self.groupList[-1]:
idx = ''
- item.setText(0, idx)
+ item.setText(self.__colGroup, idx)
if self.color:
for i in range(self.columnCount()):
item.setBackground(i, self.colorDict[idx])
@@ -1227,7 +1293,7 @@ class XMCDTreeWidget(qt.QTreeWidget):
def clearSelection(self, selectedOnly=True):
'''
- Empties the id column for the selected rows.
+ Empties the groups column for the selected rows.
'''
if selectedOnly:
sel = self.selectedItems()
@@ -1235,7 +1301,7 @@ class XMCDTreeWidget(qt.QTreeWidget):
root = self.invisibleRootItem()
sel = [root.child(i) for i in range(root.childCount())]
for item in sel:
- item.setText(0,'')
+ item.setText(self.__colGroup,'')
if self.color:
for i in range(self.columnCount()):
item.setBackground(i, self.colorDict[''])
@@ -1244,9 +1310,9 @@ class XMCDTreeWidget(qt.QTreeWidget):
def getSelection(self):
'''
Returns dictionary with where the keys
- are the identifiers and the values are
- (sorted) lists containing legends to
- which the respective identifier is
+ are the identifiers ('D', 'A', 'B') and
+ the values are (sorted) lists containing
+ legends to which the respective identifier is
assigned to.
'''
out = dict((group, []) for group in self.groupList)
@@ -1255,6 +1321,8 @@ class XMCDTreeWidget(qt.QTreeWidget):
item = root.child(i)
group = str(item.text(0))
legend = str(item.text(1))
+ #nCols = item.columnCount()
+ #legend = str(item.text(nCols-1))
if len(group) == 0:
group = self.groupList[-1]
out[group] += [legend]
@@ -1269,7 +1337,7 @@ class XMCDWidget(qt.QWidget):
def __init__(self, parent,
plotWindow,
beamline,
- nSelectors = 2):
+ nSelectors = 5):
"""
Input
-----
@@ -1277,17 +1345,9 @@ class XMCDWidget(qt.QWidget):
ScanWindow from which curves are passed for
XLD/XMCD Analysis
nSelectors : Int
- Number of Comboboxes shown in the widget.
- Every Combobox allows to select a different motor
-
- legendList : List
- Contains curve legends. Format
- ['Legend0', ... , 'LegendX']
- motorsList : List
- Contains dictionaries. Format:
- [{'MotorName0':MotorValue0, ... , 'MotorNameN':MotorValueN},
- ...,
- {'MotorName2':MotorValue2, ... , 'MotorNameM':MotorValueM}]
+ Number of columns show in the widget. Per default
+ these are
+ <Group> <Legend> <ScanNo> <Counter> <Motor 1> ... <Motor5>
"""
qt.QWidget.__init__(self, parent)
self.setWindowIcon(qt.QIcon(IconDict['peak']))
@@ -1304,35 +1364,54 @@ class XMCDWidget(qt.QWidget):
self.analysisWindow = XMCDScanWindow(origin=plotWindow,
parent=None)
self.optsWindow = XMCDOptions(self, self.motorNamesList)
+
+ helpFileName = pathjoin(PyMcaDataDir.PYMCA_DOC_DIR,
+ "HTML",
+ "XMCDInfotext.html")
+ self.helpFileBrowser = qt.QTextBrowser()
+ self.helpFileBrowser.setWindowTitle("XMCD Help")
+ self.helpFileBrowser.setLineWrapMode(qt.QTextEdit.FixedPixelWidth)
+ self.helpFileBrowser.setLineWrapColumnOrWidth(500)
+ self.helpFileBrowser.resize(520,300)
+ try:
+ helpFileHandle = open(helpFileName)
+ helpFileHTML = helpFileHandle.read()
+ helpFileHandle.close()
+ self.helpFileBrowser.setHtml(helpFileHTML)
+ except IOError:
+ if DEBUG:
+ print('XMCDWindow -- init: Unable to read help file')
+ self.helpFileBrowser = None
self.selectionDict = {'D': [],
'B': [],
'A': []}
- self.beamline = beamline
self.setSizePolicy(qt.QSizePolicy.MinimumExpanding,
qt.QSizePolicy.Expanding)
self.setWindowTitle("XLD/XMCD Analysis")
- updatePixmap = qt.QPixmap(IconDict["reload"])
- buttonUpdate = qt.QPushButton(qt.QIcon(updatePixmap), '', self)
+
buttonOptions = qt.QPushButton('Options', self)
- #for i in range(nSelectors):
- # cBox = qt.QComboBox(self)
- # cBox.addItems(self.motorNamesList)
- # cBox.currentIndexChanged['QString'].connect(self.updateTree)
- # self.cBoxList += [cBox]
-
- self.ident = 'Key'
- for ddict in self.infoList:
- if self.ident not in ddict.keys():
- self.ident = 'selectionlegend'
- break
- elif not len(ddict[self.ident]):
- self.ident = 'selectionlegend'
- break
+ buttonOptions.setToolTip(
+ 'Set normalization and interpolation\n'
+ +'method and motors shown')
+
+ buttonInfo = qt.QPushButton('Info')
+ buttonInfo.setToolTip(
+ 'Shows a describtion of the plugins features\n'
+ +'and gives instructions on how to use it')
+
+ updatePixmap = qt.QPixmap(IconDict["reload"])
+ buttonUpdate = qt.QPushButton(
+ qt.QIcon(updatePixmap), '', self)
+ buttonUpdate.setIconSize(qt.QSize(21,21))
+ buttonUpdate.setToolTip(
+ 'Update curves in XMCD Analysis\n'
+ +'by checking the plot window')
self.list = XMCDTreeWidget(self)
- labels = ['Legend'] + nSelectors*['']
+ labels = ['Group', 'Legend', 'S#','Counter']+\
+ (['']*nSelectors)
ncols = len(labels)
self.list.setColumnCount(ncols)
self.list.setHeaderLabels(labels)
@@ -1352,14 +1431,8 @@ class XMCDWidget(qt.QWidget):
('Remove curve(s)', self.removeCurve_)])
self.list.setContextMenu(listContextMenu)
self.expCBox = qt.QComboBox(self)
- self.expCBox.addItems(
- ['Generic Dichorism',
- 'ID08: XLD',
- 'ID08: XLD (old)',
- 'ID08: XMCD',
- 'ID08: XMCD (old)',
- 'Add new configuration'])
- self.expCBox.insertSeparator(5)
+ self.expCBox.setToolTip('Select configuration of predefined\n'
+ +'experiment or configure new experiment')
self.experimentsDict = {
'Generic Dichorism': {
@@ -1367,65 +1440,112 @@ class XMCDWidget(qt.QWidget):
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': '',
- 'motor1': ''
+ 'motor1': '',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
},
- 'ID08: XMCD': {
+ 'ID08: XMCD 9 Tesla Magnet': {
'xrange': 0,
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': 'phaseD',
- 'motor1': 'magnet'
+ 'motor1': 'magnet',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
},
- 'ID08: XMCD (old)': {
+ 'ID08: XMCD 5 Tesla Magnet': {
'xrange': 0,
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': 'PhaseD',
- 'motor1': 'oxPS'
+ 'motor1': 'oxPS',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
},
- 'ID08: XLD (old)': {
+ 'ID08: XLD 5 Tesla Magnet': {
'xrange': 0,
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': 'PhaseD',
- 'motor1': ''
+ 'motor1': '',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
},
- 'ID08: XLD': {
+ 'ID08: XLD 9 Tesla Magnet': {
'xrange': 0,
'normalization': 0,
'normalizationMethod': 'offsetAndArea',
'motor0': 'phaseD',
- 'motor1': ''
+ 'motor1': '',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
+ },
+ 'ID12: XMCD (Flipper)': {
+ 'xrange': 0,
+ 'normalization': 0,
+ 'normalizationMethod': 'offsetAndArea',
+ 'motor0': 'BRUKER',
+ 'motor1': 'OXFORD',
+ 'motor2': 'CRYO',
+ 'motor3': '',
+ 'motor4': ''
+ },
+ 'ID12: XMCD': {
+ 'xrange': 0,
+ 'normalization': 0,
+ 'normalizationMethod': 'offsetAndArea',
+ 'motor0': 'Phase',
+ 'motor1': 'PhaseA',
+ 'motor2': 'BRUKER',
+ 'motor3': 'OXFORD',
+ 'motor4': 'CRYO'
+ },
+ 'ID12: XLD (quater wave plate)': {
+ 'xrange': 0,
+ 'normalization': 0,
+ 'normalizationMethod': 'offsetAndArea',
+ 'motor0': '',
+ 'motor1': '',
+ 'motor2': '',
+ 'motor3': '',
+ 'motor4': ''
}
}
-
- #cBoxLayout = qt.QHBoxLayout(None)
- #self.cBoxWidget = qt.QWidget()
- #cBoxLayout.addWidget(qt.HorizontalSpacer(self))
- #cBoxLayout.addWidget(
- # qt.QLabel('Selected motor(s):', self))
- #for cBox in self.cBoxList:
- # cBoxLayout.addWidget(cBox)
- #self.cBoxWidget.setLayout(cBoxLayout)
- #cBoxLayout.setContentsMargins(0,0,0,0)
+ self.expCBox.addItems(
+ ['Generic Dichorism',
+ 'ID08: XLD 9 Tesla Magnet',
+ 'ID08: XLD 5 Tesla Magnet',
+ 'ID08: XMCD 9 Tesla Magnet',
+ 'ID08: XMCD 5 Tesla Magnet',
+ 'ID12: XLD (quater wave plate)',
+ 'ID12: XMCD (Flipper)',
+ 'ID12: XMCD',
+ 'Add new configuration'])
+ self.expCBox.insertSeparator(len(self.experimentsDict))
topLayout = qt.QHBoxLayout()
topLayout.addWidget(buttonUpdate)
topLayout.addWidget(buttonOptions)
+ topLayout.addWidget(buttonInfo)
topLayout.addWidget(qt.HorizontalSpacer(self))
topLayout.addWidget(self.expCBox)
leftLayout = qt.QGridLayout()
leftLayout.setContentsMargins(1, 1, 1, 1)
leftLayout.setSpacing(2)
- #leftLayout.addWidget(self.cBoxWidget, 2, 0)
- leftLayout.addWidget(self.list, 1, 0)
leftLayout.addLayout(topLayout, 0, 0)
+ leftLayout.addWidget(self.list, 1, 0)
leftWidget = qt.QWidget(self)
leftWidget.setLayout(leftLayout)
self.analysisWindow.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Minimum)
- self.splitter = qt.QSplitter(qt.Qt.Horizontal, self)
+ #self.splitter = qt.QSplitter(qt.Qt.Horizontal, self)
+ self.splitter = qt.QSplitter(qt.Qt.Vertical, self)
self.splitter.addWidget(leftWidget)
self.splitter.addWidget(self.analysisWindow)
stretch = int(leftWidget.width())
@@ -1447,10 +1567,13 @@ class XMCDWidget(qt.QWidget):
self.optsWindow.accepted[()].connect(self.updateTree)
buttonUpdate.clicked.connect(self.updatePlots)
buttonOptions.clicked.connect(self.showOptionsWindow)
+ buttonInfo.clicked.connect(self.showInfoWindow)
self.updateTree()
self.list.sortByColumn(1, qt.Qt.AscendingOrder)
- self._setBeamlineSpecific(self.beamline)
+
+ def sizeHint(self):
+ return self.list.sizeHint() + self.analysisWindow.sizeHint()
def addExperiment(self):
exp, chk = qt.QInputDialog.\
@@ -1487,6 +1610,18 @@ class XMCDWidget(qt.QWidget):
options = self.optsWindow.getOptions()
self.analysisWindow.processOptions(options)
+ def showInfoWindow(self):
+ if self.helpFileBrowser is None:
+ msg = qt.QMessageBox()
+ msg.setWindowTitle('XLD/XMCD Error')
+ msg.setText('No help file found.')
+ msg.exec_()
+ return
+ else:
+ self.helpFileBrowser.show()
+ self.helpFileBrowser.raise_()
+
+
# Implement new assignment routines here BEGIN
def selectExperiment(self, exp):
exp = str(exp)
@@ -1495,18 +1630,25 @@ class XMCDWidget(qt.QWidget):
self.updateTree()
elif exp in self.experimentsDict:
try:
+ # Sets motors 0 to 4 in optsWindow
self.optsWindow.setOptions(self.experimentsDict[exp])
except ValueError:
self.optsWindow.setOptions(
self.experimentsDict['Generic Dichorism'])
return
- self.updateTree()
# Get motor values from tree
+ self.updateTree()
values0 = numpy.array(
- self.list.getColumn(2, convertType=float))
+ self.list.getColumn(4, convertType=float))
values1 = numpy.array(
- self.list.getColumn(3, convertType=float))
- # Calculate p/m selection
+ self.list.getColumn(5, convertType=float))
+ values2 = numpy.array(
+ self.list.getColumn(6, convertType=float))
+ values3 = numpy.array(
+ self.list.getColumn(7, convertType=float))
+ values4 = numpy.array(
+ self.list.getColumn(8, convertType=float))
+ # Determine p/m selection
if exp.startswith('ID08: XLD'):
values = values0
mask = numpy.where(numpy.isfinite(values))[0]
@@ -1516,50 +1658,99 @@ class XMCDWidget(qt.QWidget):
vmax = minmax.max()
vpivot = .5 * (vmax + vmin)
else:
+ vpivot = 0.
values = numpy.array(
[float('NaN')]*len(self.legendList))
elif exp.startswith('ID08: XMCD'):
- values = values0 * values1
+ mask = numpy.where(numpy.isfinite(values0))[0]
+ polarization = values0.take(mask)
+ values1 = values1.take(mask)
+ signMagnets = numpy.sign(values1)
+ if len(polarization)==0:
+ vpivot = 0.
+ values = numpy.array(
+ [float('NaN')]*len(self.legendList))
+ elif numpy.all(signMagnets>=0.) or\
+ numpy.all(signMagnets<=0.) or\
+ numpy.all(signMagnets==0.):
+ vmin = polarization.min()
+ vmax = polarization.max()
+ vpivot = .5 * (vmax + vmin)
+ values = polarization
+ else:
+ vpivot = 0.
+ values = polarization * signMagnets
+ elif exp.startswith('ID12: XLD (quater wave plate)'):
+ # Extract counters from third column
+ counters = self.list.getColumn(3, convertType=str)
+ polarization = []
+ for counter in counters:
+ # Relevant counters Ihor, Iver resp. Ihor0, Iver0, etc.
+ if 'hor' in counter:
+ pol = -1.
+ elif 'ver' in counter:
+ pol = 1.
+ else:
+ pol = float('nan')
+ polarization += [pol]
+ values = numpy.asarray(polarization, dtype=float)
+ vpivot = 0.
+ elif exp.startswith('ID12: XMCD (Flipper)'):
+ # Extract counters from third column
+ counters = self.list.getColumn(1, convertType=str)
+ polarization = []
+ for counter in counters:
+ # Relevant counters: Fminus/Fplus resp. Rminus/Rplus
+ if 'minus' in counter:
+ pol = 1.
+ elif 'plus' in counter:
+ pol = -1.
+ else:
+ pol = float('nan')
+ polarization += [pol]
+ magnets = values0 + values1 + values2
+ values = numpy.asarray(polarization, dtype=float)*\
+ magnets
+ vpivot = 0.
+ elif exp.startswith('ID12: XMCD'):
+ # Sum over phases..
+ polarization = values0 + values1
+ # ..and magnets
+ magnets = values2 + values3 + values4
+ signMagnets = numpy.sign(magnets)
+ if numpy.all(signMagnets==0.):
+ values = polarization
+ else:
+ values = numpy.sign(polarization)*\
+ numpy.sign(magnets)
vpivot = 0.
else:
values = numpy.array([float('NaN')]*len(self.legendList))
vpivot = 0.
+ # Sequence is generate according to values and vpivot
seq = ''
for x in values:
if str(x) == 'nan':
seq += 'D'
- elif x>vpivot:
- seq += 'B'
- else:
+ elif x<vpivot:
+ # Minus group
seq += 'A'
+ else:
+ # Plus group
+ seq += 'B'
self.list.setSelectionToSequence(seq)
# Implement new assignment routines here END
def triggerXMCD(self):
- msel = self.selectionDict['A']
- psel = self.selectionDict['B']
- self.analysisWindow.processSelection(msel, psel)
+ groupA = self.selectionDict['A']
+ groupB = self.selectionDict['B']
+ self.analysisWindow.processSelection(groupA, groupB)
def removeCurve_(self):
- sel = self.list.getColumn(1,
+ sel = self.list.getColumn(1,
selectedOnly=True,
convertType=str)
- # Convert from scan number to legend if needed
- if self.ident == 'Key':
- legends = []
- for item in sel:
- for (idx, info) in enumerate(self.infoList):
- if item == info['Key']:
- legends += [self.legendList[idx]]
- else:
- legends = sel
-
- if DEBUG:
- print('removeCurve_ -- sel(ection):')
- print('\t', sel)
- print('removeCurve_ -- legends:')
- print('\t', legends)
- for legend in legends:
+ for legend in sel:
self.plotWindow.removeCurve(legend)
for selection in self.selectionDict.values():
if legend in selection:
@@ -1574,26 +1765,18 @@ class XMCDWidget(qt.QWidget):
self.updatePlots()
def updateSelectionDict(self):
- # selDict has format {IDENTIFIER0: LIST_OF_IDENTS0, ... }
+ # Get selDict from self.list. It consists of tree items:
+ # {GROUP0: LIST_OF_LEGENDS_IN_GROUP0,
+ # GROUP1: LIST_OF_LEGENDS_IN_GROUP1,
+ # GROUP2: LIST_OF_LEGENDS_IN_GROUP2}
selDict = self.list.getSelection()
# self.selectionDict -> Uses ScanNumbers instead of legends...
newDict = {}
- if self.ident == 'Key':
- # List contains scannumber in the order they were added
- scanNumberList = [info['Key'] for info in self.infoList]
for (idx, selList) in selDict.items():
if idx not in newDict.keys():
newDict[idx] = []
- if self.ident == 'selectionlegend':
- # Uses selectionlegend as identification for scans
- for legend in selList:
- newDict[idx] += [legend]
- else:
- # Uses Key (scan number) as identification for scans:
- for scanNumber in selList:
- scanIdx = scanNumberList.index(scanNumber)
- legend = self.legendList[scanIdx]
- newDict[idx] += [legend]
+ for legend in selList:
+ newDict[idx] += [legend]
self.selectionDict = newDict
self.setSelectionSignal.emit(self.selectionDict['A'],
self.selectionDict['B'])
@@ -1608,6 +1791,7 @@ class XMCDWidget(qt.QWidget):
self.triggerXMCD()
return
self._setLists()
+
self.motorNamesList = [''] + self._getAllMotorNames()
self.motorNamesList.sort()
self.optsWindow.updateMotorList(self.motorNamesList)
@@ -1619,24 +1803,43 @@ class XMCDWidget(qt.QWidget):
def updateTree(self):
mList = self.optsWindow.getMotors()
- if self.ident == 'Key':
- labels = ["Group",'S#'] + mList
- else:
- labels = ["Group",'Legend'] + mList
+ labels = ["Group",'Legend','S#','Counter'] + mList
items = []
for i in range(len(self.legendList)):
+ # Loop through rows
+ # Each row is represented by QStringList
legend = self.legendList[i]
values = self.motorsList[i]
info = self.infoList[i]
selection = ''
+ # Determine Group from selectionDict
for (idx, v) in self.selectionDict.items():
if (legend in v) and (idx != 'D'):
selection = idx
break
- if self.ident == 'Key':
- tmp = qt.QStringList([selection, info['Key']])
- else:
- tmp = qt.QStringList([selection, legend])
+ # Add filename, scanNo, counter
+ #sourceName = info.get('SourceName','')
+ #if isinstance(sourceName,list):
+ # filename = basename(sourceName[0])
+ #else:
+ # filename = basename(sourceName)
+ filename = legend
+ scanNo = info.get('Key','')
+ counter = info.get('ylabel',None)
+ if counter is None:
+ selDict = info.get('selection',{})
+ if len(selDict) == 0:
+ counter = ''
+ else:
+ # When do multiple selections occur?
+ try:
+ yIdx = selDict['y'][0]
+ cntList = selDict['cnt_list']
+ counter = cntList[yIdx]
+ except Exception:
+ counter = ''
+ tmp = QStringList([selection, filename, scanNo, counter])
+ # Determine value for each motor
for m in mList:
if len(m) == 0:
tmp.append('')
@@ -1644,6 +1847,8 @@ class XMCDWidget(qt.QWidget):
tmp.append(str(values.get(m, '---')))
items.append(tmp)
self.list.build(items, labels)
+ for idx in range(self.list.columnCount()):
+ self.list.resizeColumnToContents(idx)
def setAsA(self):
self.list.setSelectionAs('A')
@@ -1690,25 +1895,40 @@ class XMCDWidget(qt.QWidget):
return ret
def _setLists(self):
- curves = self.plotWindow.getAllCurves()
- nCurves = len(curves)
- self.legendList = [leg for (xvals, yvals, leg, info) in curves]
- self.infoList = [info for (xvals, yvals, leg, info) in curves]
- self.motorsList = self._convertInfoDictionary(self.infoList)
-
- def _setBeamlineSpecific(self, beamline):
'''
- beamline : python str
- Beamline identifier, all upper case
- (e.g. ID08, ID12, ..)
+ Curves retrieved from the main plot window using the
+ Plugin1DBase getActiveCurve() resp. getAllCurves()
+ member functions are tuple resp. a list of tuples
+ containing x-data, y-data, legend and the info dictionary.
+
+ _setLists splits these tuples into lists, thus setting
+ the attributes
+
+ self.legendList
+ self.infoList
+ self.motorsList
'''
- options = [str(self.expCBox.itemText(i))\
- for i in range(self.expCBox.count())]
- for (i, option) in enumerate(options):
- if option.startswith(beamline):
- self.expCBox.setCurrentIndex(i)
- self.expCBox.activated[qt.QString].emit(option)
- break
+ if self.plotWindow is not None:
+ curves = self.plotWindow.getAllCurves()
+ else:
+ if DEBUG:
+ print('_setLists -- Set self.plotWindow before calling self._setLists')
+ return
+ # nCurves = len(curves)
+ self.legendList = [leg for (xvals, yvals, leg, info) in curves]
+ self.infoList = [info for (xvals, yvals, leg, info) in curves]
+ # Try to recover the scan number from the legend, if not set
+ # Requires additional import:
+ #from re import search as regexpSearch
+ #for ddict in self.infoList:
+ # key = ddict.get('Key','')
+ # if len(key)== 0:
+ # selectionlegend = ddict['selectionlegend']
+ # match = regexpSearch(r'(?<= )\d{1,5}\.\d{1}',selectionlegend)
+ # if match:
+ # scanNo = match.group(0)
+ # ddict['Key'] = scanNo
+ self.motorsList = self._convertInfoDictionary(self.infoList)
class XMCDFileDialog(qt.QFileDialog):
def __init__(self, parent, caption, directory, filter):
@@ -1756,28 +1976,39 @@ def main():
swin = sw.ScanWindow()
info0 = {'xlabel': 'foo',
'ylabel': 'arb',
- 'MotorNames': 'oxPS Motor11 Motor10',
- 'MotorValues': '1 8.69271399699 21.9836418539'}
- info1 = {'MotorNames': 'PhaseD oxPS Motor16 Motor15',
- 'MotorValues': '0.470746882688 -0.695816070299 0.825780811755 0.25876374531'}
- info2 = {'MotorNames': 'PhaseD oxPS Motor10 Motor8',
- 'MotorValues': '2 0.44400576644 0.613870067852 0.901968648111'}
+ 'MotorNames': 'oxPS PhaseA Phase BRUKER CRYO OXFORD',
+ 'MotorValues': '1 -6.27247094 -3.11222732 6.34150808 -34.75892563 21.99607165'}
+ info1 = {'MotorNames': 'PhaseD oxPS PhaseA Phase BRUKER CRYO OXFORD',
+ 'MotorValues': '0.470746882688 0.25876374531 -0.18515967 -28.31216591 18.54513221 -28.09735532 -26.78833172'}
+ info2 = {'MotorNames': 'PhaseD oxPS PhaseA Phase BRUKER CRYO OXFORD',
+ 'MotorValues': '-9.45353059 -25.37448851 24.37665651 18.88048044 -0.26018745 2 0.901968648111 '}
x = numpy.arange(100.,1100.)
y0 = 10*x + 10000.*numpy.exp(-0.5*(x-500)**2/400) + 1500*numpy.random.random(1000.)
y1 = 10*x + 10000.*numpy.exp(-0.5*(x-600)**2/400) + 1500*numpy.random.random(1000.)
y2 = 10*x + 10000.*numpy.exp(-0.5*(x-400)**2/400) + 1500*numpy.random.random(1000.)
- swin.newCurve(x, y2, legend="Curve2", xlabel='ene_st2', ylabel='zratio2', info=info2, replot=False, replace=False)
- swin.newCurve(x, y0, legend="Curve0", xlabel='ene_st0', ylabel='zratio0', info=info0, replot=False, replace=False)
- swin.newCurve(x, y1, legend="Curve1", xlabel='ene_st1', ylabel='zratio1', info=info1, replot=False, replace=False)
+ swin.newCurve(x, y2, legend="Curve2", xlabel='ene_st2', ylabel='Ihor', info=info2, replot=False, replace=False)
+ swin.newCurve(x, y0, legend="Curve0", xlabel='ene_st0', ylabel='Iver', info=info0, replot=False, replace=False)
+ swin.newCurve(x, y1, legend="Curve1", xlabel='ene_st1', ylabel='Ihor', info=info1, replot=False, replace=False)
# info['Key'] is overwritten when using newCurve
- swin.dataObjectsDict['Curve2 zratio2'].info['Key'] = '1.1'
- swin.dataObjectsDict['Curve0 zratio0'].info['Key'] = '34.1'
- swin.dataObjectsDict['Curve1 zratio1'].info['Key'] = '123.1'
+ swin.dataObjectsDict['Curve2 Ihor'].info['Key'] = '1.1'
+ swin.dataObjectsDict['Curve0 Iver'].info['Key'] = '34.1'
+ swin.dataObjectsDict['Curve1 Ihor'].info['Key'] = '123.1'
- w = XMCDWidget(None, swin, 'ID08', nSelectors = 2)
+ w = XMCDWidget(None, swin, 'ID08', nSelectors = 5)
w.show()
+
+# helpFileBrowser = qt.QTextBrowser()
+# helpFileBrowser.setLineWrapMode(qt.QTextEdit.FixedPixelWidth)
+# helpFileBrowser.setLineWrapColumnOrWidth(500)
+# helpFileBrowser.resize(520,400)
+# helpFileHandle = open('/home/truter/lab/XMCD_infotext.html')
+# helpFileHTML = helpFileHandle.read()
+# helpFileHandle.close()
+# helpFileBrowser.setHtml(helpFileHTML)
+# helpFileBrowser.show()
+
app.exec_()
if __name__ == '__main__':
diff --git a/PyMca/XRFMC/XMSOParser.py b/PyMca/XRFMC/XMSOParser.py
index bad30aa..3bdfd10 100644
--- a/PyMca/XRFMC/XMSOParser.py
+++ b/PyMca/XRFMC/XMSOParser.py
@@ -1,3 +1,29 @@
+#
+# Copyright (C) 2013 V. Armando Sole - ESRF
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+__license__ = "MIT"
+__author__ = "V.A. Sole - ESRF Data Analysis"
import sys
import os
import xml.etree.ElementTree as ElementTree
diff --git a/PyMca/XRFMC/XRFMCHelper.py b/PyMca/XRFMC/XRFMCHelper.py
index 5ff57cf..b3f29a1 100644
--- a/PyMca/XRFMC/XRFMCHelper.py
+++ b/PyMca/XRFMC/XRFMCHelper.py
@@ -1,3 +1,29 @@
+#
+# Copyright (C) 2013 V. Armando Sole - ESRF
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+__license__ = "MIT"
+__author__ = "V.A. Sole - ESRF Data Analysis"
import sys
import os
import tempfile
diff --git a/PyMca/XRFMC/XRFMCPyMca.py b/PyMca/XRFMC/XRFMCPyMca.py
index f16123c..880a8fa 100644
--- a/PyMca/XRFMC/XRFMCPyMca.py
+++ b/PyMca/XRFMC/XRFMCPyMca.py
@@ -1,3 +1,30 @@
+#/*##########################################################################
+# Copyright (C) 2013 V.A. Sole - European Synchrotron Radiation Facility
+#
+# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
+# the ESRF by the Software group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMca 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
+# PyMca; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# PyMca follows the dual licensing model of Riverbank's PyQt and cannot be
+# used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+__author__ = "V.A. Sole - ESRF Data Analysis"
import sys
import os
import time
diff --git a/PyMca/linalg.py b/PyMca/linalg.py
new file mode 100644
index 0000000..9ec72ce
--- /dev/null
+++ b/PyMca/linalg.py
@@ -0,0 +1,326 @@
+import numpy
+
+# Linear Least Squares
+
+def lstsq(a, b, rcond=None, sigma_b=None, weight=False,
+ uncertainties=True, covariances=False, digested_output=False):
+ """
+ Return the least-squares solution to a linear matrix equation.
+
+ Solves the equation `a x = b` by computing a vector `x` that
+ minimizes the Euclidean 2-norm `|| b - a x ||^2`. The equation may
+ be under-, well-, or over- determined (i.e., the number of
+ linearly independent rows of `a` can be less than, equal to, or
+ greater than its number of linearly independent columns). If `a`
+ is square and of full rank, then `x` (but for round-off error) is
+ the "exact" solution of the equation.
+
+ Parameters
+ ----------
+ a : array_like, shape (M, N)
+ "Model" matrix.
+ b : array_like, shape (M,) or (M, K)
+ Ordinate or "dependent variable" values. If `b` is two-dimensional,
+ the least-squares solution is calculated for each of the `K` columns
+ of `b`.
+ sigma_b : uncertainties on the b values
+
+ weight: 0 - No data weighting.
+ If required, uncertainties will be calculated using either the
+ supplied experimental uncertainties or an experimental
+ uncertainty of 1 for each data point.
+ 1 - Statistical weight.
+ Weighted fit using the supplied experimental uncertainties or the
+ square root of the b values.
+
+ uncertainties: If False, no uncertainties will be calculated unless the covariance
+ matrix is requested.
+
+ covariances: If True, an array of covariance matrix/matrices will be returned.
+
+ digested_output: If True, returns a dictionnary with explicit keys
+
+ Returns
+ -------
+ x : ndarray, shape (N,) or (N, K)
+ Least-squares solution. The shape of `x` depends on the shape of
+ `b`.
+
+ uncertainties: ndarray, shape (N,) or (N, K)
+
+ covariances: ndarray, shape (N, N) or (K, N, N)
+
+ Examples
+ --------
+ Fit a line, ``y = mx + c``, through some noisy data-points:
+
+ >>> x = np.array([0, 1, 2, 3])
+ >>> y = np.array([-1, 0.2, 0.9, 2.1])
+
+ By examining the coefficients, we see that the line should have a
+ gradient of roughly 1 and cut the y-axis at, more or less, -1.
+
+ We can rewrite the line equation as ``y = Ap``, where ``A = [[x 1]]``
+ and ``p = [[m], [c]]``. Now use `lstsq` to solve for `p`:
+
+ >>> A = np.vstack([x, np.ones(len(x))]).T
+ >>> A
+ array([[ 0., 1.],
+ [ 1., 1.],
+ [ 2., 1.],
+ [ 3., 1.]])
+
+ >>> m, c = np.linalg.lstsq(A, y)[0]
+ >>> print m, c
+ 1.0 -0.95
+
+ Plot the data along with the fitted line:
+
+ >>> import matplotlib.pyplot as plt
+ >>> plt.plot(x, y, 'o', label='Original data', markersize=10)
+ >>> plt.plot(x, m*x + c, 'r', label='Fitted line')
+ >>> plt.legend()
+ >>> plt.show()
+
+ """
+
+ a = numpy.array(a, dtype=numpy.float, copy=False)
+ b = numpy.array(b, dtype=numpy.float, copy=False)
+ a_shape = a.shape
+ b_shape = b.shape
+ original = b_shape
+ if len(a_shape) != 2:
+ raise ValueError("Model matrix must be two dimensional")
+ if len(b_shape) == 1:
+ b.shape = b_shape[0], 1
+ b_shape = b.shape
+
+ m = a.shape[0]
+ n = a.shape[1]
+
+ if m != b.shape[0]:
+ raise ValueError('Incompatible dimensions between A and b matrices')
+
+ fastest = False
+ if sigma_b is not None:
+ # experimental uncertainties provided these are the ones to use (if any)
+ w = numpy.abs(numpy.array(sigma_b, dtype=numpy.float, copy=False))
+ w = w + numpy.equal(w, 0)
+ w.shape = b_shape
+ elif weight == 0:
+ # we have an unweighted fit with no uncertainties
+ # assume all the uncertainties equal to 1
+ fastest = True
+ w = numpy.ones(b.shape, numpy.float)
+ else:
+ # "statistical" weight
+ # we are asked to somehow weight the data but no uncertainties provided
+ # assume the uncertainties are the square root of the b values ...
+ w = numpy.sqrt(numpy.abs(b))
+ w = w + numpy.equal(w, 0)
+
+ if covariances:
+ covarianceMatrix = numpy.zeros((b_shape[1], n, n), numpy.float)
+
+ if not weight:
+ # no weight is applied
+ # get the SVD decomposition of the A matrix
+ U, s, V = numpy.linalg.svd(a, full_matrices=False)
+
+ if rcond is None:
+ s_cutoff = n * numpy.finfo(numpy.float).eps
+ else:
+ s_cutoff = rcond * s[0]
+ s[s < s_cutoff] = numpy.inf
+
+ # and get the parameters
+ s.shape = -1
+ dummy = numpy.dot(V.T, numpy.eye(n)*(1./s))
+ parameters = numpy.dot(dummy, numpy.dot(U.T, b))
+ parameters.shape = n, b.shape[1]
+ if uncertainties or covariances:
+ # get the uncertainties
+ #(in the no-weight case without experimental uncertainties,
+ # the uncertainties on the data points are ignored and the
+ # uncertainty on the fitted parameters are independent of the input data!!!!)
+ if fastest:
+ # This is correct for all weights equal to 1
+ _covariance = numpy.dot(dummy, dummy.T)
+ sigmapar = numpy.sqrt(numpy.diag(_covariance))
+ sigmapar = numpy.outer(sigmapar, numpy.ones(b_shape[1]))
+ sigmapar.shape = n, b_shape[1]
+ if covariances:
+ covarianceMatrix[:] = _covariance
+ elif covariances:
+ # loop in order not to use potentially big matrices
+ # but calculates the covariance matrices
+ # It only makes sense if the covariance matrix is requested
+ sigmapar = numpy.zeros((n, b_shape[1]), numpy.float)
+ for k in range(b_shape[1]):
+ pseudoData = numpy.eye(b_shape[0]) * w[:, k]
+ tmpTerm = numpy.dot(dummy, numpy.dot(U.T, pseudoData))
+ _covariance[:, :] = numpy.dot(tmpTerm, tmpTerm.T)
+ sigmapar[:, k] = numpy.sqrt(numpy.diag(_covariance))
+ covarianceMatrix[k] = _covariance
+ else:
+ # loop in order not to use potentially big matrices
+ # but not calculating the covariance matrix
+ d = numpy.zeros(b.shape, numpy.float)
+ sigmapar = numpy.zeros((n, b_shape[1]))
+ for k in range(b_shape[0]):
+ d[k] = w[k]
+ sigmapar += (numpy.dot(dummy, numpy.dot(U.T, d))) ** 2
+ d[k] = 0.0
+ sigmapar[:, :] = numpy.sqrt(sigmapar)
+ else:
+ parameters = numpy.zeros((n, b_shape[1]), numpy.float)
+ sigmapar = numpy.zeros((n, b_shape[1]), numpy.float)
+ for i in range(b_shape[1]):
+ tmpWeight = w[:, i:i+1]
+ tmpData = b[:, i:i+1] / tmpWeight
+ A = a / tmpWeight
+ U, s, V = numpy.linalg.svd(A, full_matrices=False)
+ if rcond is None:
+ s_cutoff = n * numpy.finfo(numpy.float).eps
+ else:
+ s_cutoff = rcond * s[0]
+ s[s < s_cutoff] = numpy.inf
+ s.shape = -1
+ dummy = numpy.dot(V.T, numpy.eye(n)*(1./s))
+ parameters[:, i:i+1] = numpy.dot(dummy, numpy.dot(U.T, tmpData))
+ if uncertainties or covariances:
+ # get the uncertainties
+ _covariance = numpy.dot(dummy, dummy.T)
+ sigmapar[:, i] = numpy.sqrt(numpy.diag(_covariance))
+ if covariances:
+ covarianceMatrix[i] = _covariance
+
+ if len(original) == 1:
+ parameters.shape = -1
+ if covariances:
+ sigmapar.shape = parameters.shape
+ if len(original) == 1:
+ covarianceMatrix.shape = parameters.shape[0], parameters.shape[0]
+ result = [parameters, sigmapar, covarianceMatrix]
+ elif uncertainties:
+ sigmapar.shape = parameters.shape
+ result = [parameters, sigmapar]
+ else:
+ result = [parameters]
+
+ if digested_output:
+ ddict = {}
+ ddict['parameters'] = result[0]
+ if len(result) > 1:
+ ddict['uncertainties'] = result[1]
+ elif covariances:
+ ddict['covariances'] = result[2]
+ return ddict
+ else:
+ return result
+
+
+def getModelMatrixFromFunction(model_function, dummy_parameters, xdata, derivative=None):
+ nPoints = xdata.size
+ nParameters = len(dummy_parameters)
+ modelMatrix = numpy.zeros((nPoints, nParameters) , numpy.float)
+ pwork = dummy_parameters * 1
+ for i in range(len(dummy_parameters)):
+ fitparam = dummy_parameters[i]
+ if derivative is None:
+ delta = (pwork[i] + numpy.equal(fitparam, 0.0)) * 0.00001
+ pwork[i] = fitparam + delta
+ f1 = model_function(pwork, xdata)
+ pwork[i] = fitparam - delta
+ f2 = model_function(pwork, xdata)
+ help0 = (f1-f2) / (2.0 * delta)
+ pwork[i] = fitparam
+ else:
+ help0 = derivative(pwork, i, xdata)
+ help0.shape = -1
+ modelMatrix[:, i] = help0
+ return modelMatrix
+
+def modelFunction(p, x):
+ return p[0] + (p[1] + p[2] * x) * x
+
+def test1():
+ x = numpy.arange(10000.)
+ x.shape = -1, 1
+ y = modelFunction([100., 50., 4.], x)
+ A = getModelMatrixFromFunction(modelFunction, [0.0, 0.0, 0.0], x)
+ parameters, uncertainties = lstsq(A, y, uncertainties=True, weight=False)
+ print("Expected = 100., 50., 4.")
+ print("Obtained = %f, %f, %f" % (parameters[0], parameters[1], parameters[2]))
+
+def test2():
+ import time
+ try:
+ from PyMca import Gefit
+ GEFIT = True
+ def f(p, x):
+ return p[1] * x + p[0]
+ except:
+ GEFIT = False
+ data = "0 0.8214 0.1 1 2.8471 0.3 2 4.852 0.5 3 7.5347 0.7 4 10.2464 0.9 5 10.2707 1.1 6 12.8011 1.3 7 13.7108 1.5 8 17.8501 1.7 9 15.3667 1.9 10 19.3933 2.1"
+ data = numpy.array([float(x) for x in data.split()])
+ data.shape = -1, 3
+
+ # the model matrix for a straight line
+ A = numpy.ones((data.shape[0],2), numpy.float)
+ A[:, 1] = data[:, 0]
+ print("Unweighted results:")
+ t0 = time.time()
+ y = numpy.ones((data.shape[0], 1000), numpy.float) * data[:, 1:2]
+ sigmay = numpy.ones((data.shape[0], 1000), numpy.float) * data[:, 2:3]
+ parameters, uncertainties = lstsq(A, y, #sigma_b=sigmay, #sigma_b=numpy.ones(sigmay.shape),
+ uncertainties=True, weight=False)
+ print("Elapsed = %f" % (time.time() - t0))
+ print("Parameters = %f, %f" % (parameters[0,100], parameters[1, 100]))
+ print("Uncertainties = %f, %f" % (uncertainties[0,100], uncertainties[1, 100]))
+ if GEFIT:
+ t0 = time.time()
+ for i in range(y.shape[1]):
+ parameters, chisq, uncertainties = Gefit.LeastSquaresFit(f, [0.0, 0.0],
+ xdata=data[:,0],
+ ydata=data[:,1],
+ sigmadata=data[:,2],
+ weightflag=0,
+ linear=1)
+ print("Elapsed = %f" % (time.time() - t0))
+ print("Gefit results:")
+ print("Parameters = %f, %f" % (parameters[0], parameters[1]))
+ print("Uncertainties = %f, %f" % (uncertainties[0], uncertainties[1]))
+
+ print("Mathematica results:")
+ print("Parameters = %f, %f" % (1.57043, 1.78945))
+ print("Uncertainties = %f, %f" % (0.68363, 0.11555))
+
+ print("Weighted results")
+ t0 = time.time()
+ #parameters, uncertainties = lstsq(A, data[:, 1], sigma_b=data[:,2],
+ parameters, uncertainties = lstsq(A, y, sigma_b=numpy.outer(data[:,2], numpy.ones((1000, 1))),
+ uncertainties=True, weight=True)
+ print("Elapsed = %f" % (time.time() - t0))
+ print("Parameters = %f, %f" % (parameters[0, 100], parameters[1, 100]))
+ print("Uncertainties = %f, %f" % (uncertainties[0, 100], uncertainties[1, 100]))
+ if GEFIT:
+ parameters, chisq, uncertainties = Gefit.LeastSquaresFit(f, [0.0, 0.0],
+ xdata=data[:,0],
+ ydata=data[:,1],
+ sigmadata=data[:,2],
+ weightflag=1,
+ linear=1)
+ print("Gefit results:")
+ print("Parameters = %f, %f" % (parameters[0], parameters[1]))
+ print("Uncertainties = %f, %f" % (uncertainties[0], uncertainties[1]))
+
+ print("Mathematica results:")
+ print("Parameters = %f, %f" % (0.843827, 1.97982))
+ print("Uncertainties = %f, %f" % (0.092449, 0.07262))
+
+ return data
+
+if __name__ == "__main__":
+ test1()
+ test2()
diff --git a/PyMca/specfile/src/specfile_py.c b/PyMca/specfile/src/specfile_py.c
index 67dc0c1..bbdd9c7 100644
--- a/PyMca/specfile/src/specfile_py.c
+++ b/PyMca/specfile/src/specfile_py.c
@@ -118,6 +118,9 @@ PERFORMANCE OF THIS SOFTWARE.
#ifndef WIN32
#include <Python.h>
#endif
+/* adding next line may raise errors ...
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include <numpy/arrayobject.h>
#include <SpecFile.h>
@@ -678,7 +681,7 @@ scandata_data(PyObject *self,PyObject *args) {
dimensions[0] = data_info[1];
dimensions[1] = data_info[0];
- r_array = (PyArrayObject *)PyArray_SimpleNew(2,dimensions,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(2,dimensions,NPY_DOUBLE);
/*
* Copy
@@ -688,7 +691,7 @@ scandata_data(PyObject *self,PyObject *args) {
for (i=0;i<dimensions[0];i++) {
for (j=0;j<dimensions[1];j++) {
didx = j + i * dimensions[1];
- ((double *)r_array->data)[didx] = data[j][i];
+ ((double *)PyArray_DATA(r_array))[didx] = data[j][i];
}
}
/* memcpy(array->data,data,PyArray_NBYTES(array)); */
@@ -727,9 +730,9 @@ scandata_dataline(PyObject *self,PyObject *args) {
if (ret == -1 )
onError("cannot get data for line");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),data,PyArray_NBYTES(r_array));
return (PyObject *)r_array;
}
@@ -765,10 +768,10 @@ scandata_datacol(PyObject *self,PyObject *args) {
if (ret == -1 )
onError("cannot get data for column");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if (data != (double *) NULL){
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),data,PyArray_NBYTES(r_array));
free(data);
}else{
/* return an empty array? */
@@ -1149,11 +1152,11 @@ scandata_mca (PyObject *self,PyObject *args)
if (ret == -1)
onError("cannot get mca for scan");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if (mcadata != (double *) NULL){
- memcpy(r_array->data,mcadata,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),mcadata,PyArray_NBYTES(r_array));
free(mcadata);
}else{
printf("I should give back an empty array\n");
@@ -1256,13 +1259,13 @@ scandata_col(PyObject *self, Py_ssize_t index) {
if (ret == -1 )
onError("cannot get data for column");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if ( r_array == NULL )
onError("cannot get memory for array data");
if (data != (double *) NULL){
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),data,PyArray_NBYTES(r_array));
free(data);
}else{
/* return an empty array? */
diff --git a/PyMca/specfile/src/specfile_py3.c b/PyMca/specfile/src/specfile_py3.c
index ad263a1..268b0e4 100644
--- a/PyMca/specfile/src/specfile_py3.c
+++ b/PyMca/specfile/src/specfile_py3.c
@@ -16,6 +16,9 @@
#
#############################################################################*/
#include <Python.h>
+/* adding next line may raise errors ...
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include <numpy/arrayobject.h>
#include <SpecFile.h>
@@ -342,13 +345,13 @@ specfile_open(PyObject *self, PyObject *args) /* on x = specfile.Specfile(name)
return NULL;
}
{
- bytesObject = PyUnicode_AsMBCSString(input);
- if (!bytesObject){
- onError("Cannot generate String from object name attribute")
- }
- filename = PyBytes_AsString(bytesObject);
- }
-#else
+ bytesObject = PyUnicode_AsMBCSString(input);
+ if (!bytesObject){
+ onError("Cannot generate String from object name attribute")
+ }
+ filename = PyBytes_AsString(bytesObject);
+ }
+#else
if (!PyArg_ParseTuple(args, "s", &filename))
{
return NULL;
@@ -522,13 +525,13 @@ scandata_col(PyObject *self, Py_ssize_t index) {
if (ret == -1 )
onError("cannot get data for column");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if ( r_array == NULL )
onError("cannot get memory for array data");
if (data != (double *) NULL){
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array), data, PyArray_NBYTES(r_array));
free(data);
}else{
/* return an empty array? */
@@ -582,7 +585,7 @@ scandata_data(PyObject *self,PyObject *args) {
dimensions[0] = data_info[1];
dimensions[1] = data_info[0];
- r_array = (PyArrayObject *)PyArray_SimpleNew(2,dimensions,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(2,dimensions,NPY_DOUBLE);
/*
* Copy
@@ -592,7 +595,7 @@ scandata_data(PyObject *self,PyObject *args) {
for (i=0;i<dimensions[0];i++) {
for (j=0;j<dimensions[1];j++) {
didx = j + i * dimensions[1];
- ((double *)r_array->data)[didx] = data[j][i];
+ ((double *)PyArray_DATA(r_array))[didx] = data[j][i];
}
}
/* memcpy(array->data,data,PyArray_NBYTES(array)); */
@@ -631,9 +634,9 @@ scandata_dataline(PyObject *self,PyObject *args) {
if (ret == -1 )
onError("cannot get data for line");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),data,PyArray_NBYTES(r_array));
return (PyObject *)r_array;
}
@@ -669,10 +672,10 @@ scandata_datacol(PyObject *self,PyObject *args) {
if (ret == -1 )
onError("cannot get data for column");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if (data != (double *) NULL){
- memcpy(r_array->data,data,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),data,PyArray_NBYTES(r_array));
free(data);
}else{
/* return an empty array? */
@@ -1053,11 +1056,11 @@ scandata_mca (PyObject *self,PyObject *args)
if (ret == -1)
onError("cannot get mca for scan");
- r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,PyArray_DOUBLE);
+ r_array = (PyArrayObject *)PyArray_SimpleNew(1,&ret,NPY_DOUBLE);
if (mcadata != (double *) NULL){
- memcpy(r_array->data,mcadata,PyArray_NBYTES(r_array));
+ memcpy(PyArray_DATA(r_array),mcadata,PyArray_NBYTES(r_array));
free(mcadata);
}else{
printf("I should give back an empty array\n");
diff --git a/PyMca/specfit/SpecfitFuns.c b/PyMca/specfit/SpecfitFuns.c
index 12cfe4d..e688b7b 100644
--- a/PyMca/specfit/SpecfitFuns.c
+++ b/PyMca/specfit/SpecfitFuns.c
@@ -25,9 +25,16 @@
# is a problem for you.
#############################################################################*/
#include <Python.h>
+/* adding next line may raise errors
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include <./numpy/arrayobject.h>
#include <math.h>
+#ifndef NPY_ARRAY_ENSURECOPY
+#define NPY_ARRAY_ENSURECOPY NPY_ENSURECOPY
+#endif
+
struct module_state {
PyObject *error;
};
@@ -58,6 +65,7 @@ static struct module_state _state;
void lls(double *data, int size);
void lls_inv(double *data, int size);
void snip1d(double *data, int size, int width);
+void snip1d_multiple(double *data, int n_channels, int snip_width, int n_spectra);
void snip2d(double *data, int nrows, int ncolumns, int width);
void snip3d(double *data, int nx, int ny, int nz, int width);
void lsdf(double *data, int size, int fwhm, double f, double A, double M, double ratio);
@@ -76,42 +84,57 @@ SpecfitFuns_snip1d(PyObject *self, PyObject *args)
int smooth_iterations = 0;
int llsflag = 0;
PyArrayObject *ret;
- int i, size, width;
+ double *doublePointer;
+ int i, n, n_channels, n_spectra, width;
if (!PyArg_ParseTuple(args, "Od|ii", &input, &width0, &smooth_iterations, &llsflag))
return NULL;
ret = (PyArrayObject *)
- PyArray_FROMANY(input, PyArray_DOUBLE, 1, 1, NPY_ENSURECOPY);
+ PyArray_FROMANY(input, NPY_DOUBLE, 1, 2, NPY_ARRAY_ENSURECOPY);
if (ret == NULL){
printf("Cannot create 1D array from input\n");
return NULL;
}
- size = 1;
- for (i=0; i<ret->nd; i++)
+ if(PyArray_NDIM(ret) == 1)
+ {
+ n_spectra = 1;
+ n_channels = (int) (PyArray_DIMS(ret)[0]);
+ }
+ else
{
- size = (int) (size * ret->dimensions[i]);
+ n_spectra = (int) (PyArray_DIMS(ret)[0]);
+ n_channels = (int) (PyArray_DIMS(ret)[1]);
}
width = (int )width0;
- for (i=0; i<smooth_iterations; i++)
+ for (n = 0; n < n_spectra; n++)
{
- smooth1d((double *) ret->data, size);
+ for (i=0; i<smooth_iterations; i++)
+ {
+ doublePointer = (double *) PyArray_DATA(ret);
+ smooth1d(&(doublePointer[n*n_channels]), n_channels);
+ }
+ if (llsflag)
+ {
+ doublePointer = (double *) PyArray_DATA(ret);
+ lls(&(doublePointer[n*n_channels]), n_channels);
+ }
}
- if (llsflag)
- {
- lls((double *) ret->data, size);
- }
- snip1d((double *) ret->data, size, width);
+ snip1d_multiple((double *) PyArray_DATA(ret), n_channels, width, n_spectra);
- if (llsflag)
+ for (n = 0; n < n_spectra; n++)
{
- lls_inv((double *) ret->data, size);
+ if (llsflag)
+ {
+ doublePointer = (double *) PyArray_DATA(ret);
+ lls_inv(&(doublePointer[n*n_channels]), n_channels);
+ }
}
return PyArray_Return(ret);
@@ -131,7 +154,7 @@ SpecfitFuns_snip2d(PyObject *self, PyObject *args)
return NULL;
ret = (PyArrayObject *)
- PyArray_FROMANY(input, PyArray_DOUBLE, 2, 2, NPY_ENSURECOPY);
+ PyArray_FROMANY(input, NPY_DOUBLE, 2, 2, NPY_ARRAY_ENSURECOPY);
if (ret == NULL){
printf("Cannot create 2D array from input\n");
@@ -139,30 +162,30 @@ SpecfitFuns_snip2d(PyObject *self, PyObject *args)
}
size = 1;
- for (i=0; i<ret->nd; i++)
+ for (i=0; i<PyArray_NDIM(ret); i++)
{
- size = (int) (size * ret->dimensions[i]);
+ size = (int) (size * PyArray_DIMS(ret)[i]);
}
- nrows = (int) ret->dimensions[0];
- ncolumns = (int) ret->dimensions[1];
+ nrows = (int) PyArray_DIMS(ret)[0];
+ ncolumns = (int) PyArray_DIMS(ret)[1];
width = (int )width0;
for (i=0; i<smooth_iterations; i++)
{
- smooth2d((double *) ret->data, nrows, ncolumns);
+ smooth2d((double *) PyArray_DATA(ret), nrows, ncolumns);
}
if (llsflag)
{
- lls((double *) ret->data, size);
+ lls((double *) PyArray_DATA(ret), size);
}
- snip2d((double *) ret->data, nrows, ncolumns, width);
+ snip2d((double *) PyArray_DATA(ret), nrows, ncolumns, width);
if (llsflag)
{
- lls_inv((double *) ret->data, size);
+ lls_inv((double *) PyArray_DATA(ret), size);
}
return PyArray_Return(ret);
@@ -182,7 +205,7 @@ SpecfitFuns_snip3d(PyObject *self, PyObject *args)
return NULL;
ret = (PyArrayObject *)
- PyArray_FROMANY(input, PyArray_DOUBLE, 3, 3, NPY_ENSURECOPY);
+ PyArray_FROMANY(input, NPY_DOUBLE, 3, 3, NPY_ARRAY_ENSURECOPY);
if (ret == NULL){
printf("Cannot create 3D array from input\n");
@@ -190,31 +213,31 @@ SpecfitFuns_snip3d(PyObject *self, PyObject *args)
}
size = 1;
- for (i=0; i<ret->nd; i++)
+ for (i=0; i<PyArray_NDIM(ret); i++)
{
- size = (int) (size * ret->dimensions[i]);
+ size = (int) (size * PyArray_DIMS(ret)[i]);
}
- nx = (int) ret->dimensions[0];
- ny = (int) ret->dimensions[1];
- nz = (int) ret->dimensions[2];
+ nx = (int) PyArray_DIMS(ret)[0];
+ ny = (int) PyArray_DIMS(ret)[1];
+ nz = (int) PyArray_DIMS(ret)[2];
width = (int )width0;
for (i=0; i<smooth_iterations; i++)
{
- smooth3d((double *) ret->data, nx, ny, nz);
+ smooth3d((double *) PyArray_DATA(ret), nx, ny, nz);
}
if (llsflag)
{
- lls((double *) ret->data, size);
+ lls((double *) PyArray_DATA(ret), size);
}
- snip3d((double *) ret->data, nx, ny, nz, width);
+ snip3d((double *) PyArray_DATA(ret), nx, ny, nz, width);
if (llsflag)
{
- lls_inv((double *) ret->data, size);
+ lls_inv((double *) PyArray_DATA(ret), size);
}
return PyArray_Return(ret);
@@ -238,20 +261,20 @@ SpecfitFuns_subacold(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O|dd", &input, &c, &niter0))
return NULL;
iarray = (PyArrayObject *)
- PyArray_CopyFromObject(input, PyArray_DOUBLE,1,1);
+ PyArray_CopyFromObject(input, NPY_DOUBLE,1,1);
if (iarray == NULL)
return NULL;
niter = (int ) niter0;
- n = iarray->dimensions[0];
- dimensions[0] = iarray->dimensions[0];
- ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, PyArray_DOUBLE);
+ n = PyArray_DIMS(iarray)[0];
+ dimensions[0] = PyArray_DIMS(iarray)[0];
+ ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(iarray);
return NULL;
}
/* Do the job */
- data = (double *) iarray->data;
+ data = (double *) PyArray_DATA(iarray);
for (i=0;i<niter;i++){
t_old = *(data);
for (j=1;j<n-1;j++) {
@@ -293,21 +316,21 @@ SpecfitFuns_subac(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O|dddO", &input, &c, &niter0,&deltai0, &anchors0))
return NULL;
iarray = (PyArrayObject *)
- PyArray_CopyFromObject(input, PyArray_DOUBLE,1,1);
+ PyArray_CopyFromObject(input, NPY_DOUBLE,1,1);
if (iarray == NULL)
return NULL;
deltai= (int ) deltai0;
if (deltai <=0) deltai = 1;
niter = (int ) niter0;
- n = (int) iarray->dimensions[0];
- dimensions[0] = iarray->dimensions[0];
- ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, PyArray_DOUBLE);
+ n = (int) PyArray_DIMS(iarray)[0];
+ dimensions[0] = PyArray_DIMS(iarray)[0];
+ ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(iarray);
return NULL;
}
PyArray_FILLWBYTE(ret, 0);
- memcpy(ret->data, iarray->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(ret), PyArray_DATA(iarray), PyArray_DIMS(iarray)[0] * sizeof(double));
if (n < (2*deltai+1)){
/*ret = (PyArrayObject *) PyArray_Copy(array);*/
@@ -315,21 +338,21 @@ SpecfitFuns_subac(PyObject *self, PyObject *args)
return PyArray_Return(ret);
}
/* do the job */
- data = (double *) iarray->data;
- retdata = (double *) ret->data;
+ data = (double *) PyArray_DATA(iarray);
+ retdata = (double *) PyArray_DATA(ret);
if (anchors0 != NULL)
{
if (PySequence_Check(anchors0)){
anchors = (PyArrayObject *)
- PyArray_ContiguousFromObject(anchors0, PyArray_INT, 1, 1);
+ PyArray_ContiguousFromObject(anchors0, NPY_INT, 1, 1);
if (anchors == NULL)
{
Py_DECREF(iarray);
Py_DECREF(ret);
return NULL;
}
- anchordata = (int *) anchors->data;
+ anchordata = (int *) PyArray_DATA(anchors);
nanchors = (int) PySequence_Size(anchors0);
for (i=0;i<niter;i++){
for (j=deltai;j<n-deltai;j++) {
@@ -352,7 +375,7 @@ SpecfitFuns_subac(PyObject *self, PyObject *args)
if (*(retdata+j) > (t_mean * c))
*(retdata+j) = t_mean;
}
- memcpy(iarray->data, ret->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(iarray), PyArray_DATA(ret), PyArray_DIMS(iarray)[0] * sizeof(double));
}
Py_DECREF(anchors);
notdone = 0;
@@ -366,7 +389,7 @@ SpecfitFuns_subac(PyObject *self, PyObject *args)
if (*(retdata+j) > (t_mean * c))
*(retdata+j) = t_mean;
}
- memcpy(iarray->data, ret->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(iarray), PyArray_DATA(ret), PyArray_DIMS(iarray)[0] * sizeof(double));
}
}
Py_DECREF(iarray);
@@ -394,20 +417,20 @@ SpecfitFuns_subacfast(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O|dddO", &input, &c, &niter0,&deltai0, &anchors0))
return NULL;
iarray = (PyArrayObject *)
- PyArray_CopyFromObject(input, PyArray_DOUBLE,1,1);
+ PyArray_CopyFromObject(input, NPY_DOUBLE,1,1);
if (iarray == NULL)
return NULL;
deltai= (int ) deltai0;
if (deltai <=0) deltai = 1;
niter = (int ) niter0;
- n = iarray->dimensions[0];
- dimensions[0] = iarray->dimensions[0];
- ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, PyArray_DOUBLE);
+ n = PyArray_DIMS(iarray)[0];
+ dimensions[0] = PyArray_DIMS(iarray)[0];
+ ret = (PyArrayObject *) PyArray_SimpleNew(1, dimensions, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(iarray);
return NULL;
}
- memcpy(ret->data, iarray->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(ret), PyArray_DATA(iarray), PyArray_DIMS(iarray)[0] * sizeof(double));
if (n < (2*deltai+1)){
/*ret = (PyArrayObject *) PyArray_Copy(array);*/
@@ -415,19 +438,19 @@ SpecfitFuns_subacfast(PyObject *self, PyObject *args)
return PyArray_Return(ret);
}
/* do the job */
- retdata = (double *) ret->data;
+ retdata = (double *) PyArray_DATA(ret);
if (PySequence_Check(anchors0)){
anchors = (PyArrayObject *)
- PyArray_ContiguousFromObject(anchors0, PyArray_INT, 1, 1);
+ PyArray_ContiguousFromObject(anchors0, NPY_INT, 1, 1);
if (anchors == NULL)
{
Py_DECREF(iarray);
Py_DECREF(ret);
return NULL;
}
- anchordata = (int *) anchors->data;
+ anchordata = (int *) PyArray_DATA(anchors);
nanchors = (int) PySequence_Size(anchors0);
- memcpy(iarray->data, ret->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(iarray), PyArray_DATA(ret), PyArray_DIMS(iarray)[0] * sizeof(double));
for (i=0;i<niter;i++){
for (j=deltai;j<n-deltai;j++) {
notdoit = 0;
@@ -454,7 +477,7 @@ SpecfitFuns_subacfast(PyObject *self, PyObject *args)
}
else
{
- memcpy(iarray->data, ret->data, iarray->dimensions[0] * sizeof(double));
+ memcpy(PyArray_DATA(iarray), PyArray_DATA(ret), PyArray_DIMS(iarray)[0] * sizeof(double));
for (i=0;i<niter;i++){
for (j=deltai;j<n-deltai;j++) {
t_mean = 0.5 * (*(retdata+j-deltai) + *(retdata+j+deltai));
@@ -510,40 +533,40 @@ SpecfitFuns_gauss(PyObject *self, PyObject *args)
}
param = (PyArrayObject *)
- PyArray_ContiguousFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -566,7 +589,7 @@ SpecfitFuns_gauss(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -576,12 +599,12 @@ SpecfitFuns_gauss(PyObject *self, PyObject *args)
log2 = 0.69314718055994529;
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = pgauss[i].fwhm/(2.0*sqrt(2.0*log2));
dhelp = (*px - pgauss[i].centroid)/dhelp;
@@ -596,7 +619,7 @@ SpecfitFuns_gauss(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = pgauss[i].fwhm/(2.0*sqrt(2.0*log2));
dhelp = (*px - pgauss[i].centroid)/dhelp;
@@ -639,40 +662,40 @@ SpecfitFuns_agauss(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -695,7 +718,7 @@ SpecfitFuns_agauss(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -708,12 +731,12 @@ SpecfitFuns_agauss(PyObject *self, PyObject *args)
tosigma=1.0/(2.0*sqrt(2.0*log2));
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
sigma = pgauss[i].fwhm*tosigma;
dhelp = (*px - pgauss[i].centroid)/sigma;
@@ -726,12 +749,12 @@ SpecfitFuns_agauss(PyObject *self, PyObject *args)
for (j=0;j<nd_x;j++){
k = (int) (dim_x [j] * k);
}
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
sigma = pgauss[i].fwhm*tosigma;
dhelp0 = pgauss[i].area/(sigma*sqrt2PI);
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
for (j=0;j<k;j++){
if (i==0)
*pret = 0.0;
@@ -782,40 +805,40 @@ SpecfitFuns_fastagauss(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -838,7 +861,7 @@ SpecfitFuns_fastagauss(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -851,12 +874,12 @@ SpecfitFuns_fastagauss(PyObject *self, PyObject *args)
tosigma=1.0/(2.0*sqrt(2.0*log2));
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
sigma = pgauss[i].fwhm*tosigma;
dhelp = (*px - pgauss[i].centroid)/sigma;
@@ -869,12 +892,12 @@ SpecfitFuns_fastagauss(PyObject *self, PyObject *args)
for (j=0;j<nd_x;j++){
k = (int) (dim_x [j] * k);
}
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
sigma = pgauss[i].fwhm*tosigma;
dhelp0 = pgauss[i].area/(sigma*sqrt2PI);
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
for (j=0;j<k;j++){
if (i==0)
*pret = 0.0;
@@ -935,40 +958,40 @@ SpecfitFuns_splitgauss(PyObject *self, PyObject *args)
}
param = (PyArrayObject *)
- PyArray_ContiguousFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -991,7 +1014,7 @@ SpecfitFuns_splitgauss(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1001,24 +1024,24 @@ SpecfitFuns_splitgauss(PyObject *self, PyObject *args)
log2 = 0.69314718055994529;
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
- dhelp = (*px - pgauss[i].centroid) * (2.0*sqrt(2.0*log2));
- if (dhelp > 0)
- {
- dhelp = dhelp/pgauss[i].fwhm2;
- }else{
- dhelp = dhelp/pgauss[i].fwhm1;
- }
+ dhelp = (*px - pgauss[i].centroid) * (2.0*sqrt(2.0*log2));
+ if (dhelp > 0)
+ {
+ dhelp = dhelp/pgauss[i].fwhm2;
+ }else{
+ dhelp = dhelp/pgauss[i].fwhm1;
+ }
if (dhelp <= 20) {
*pret += pgauss[i].height * exp (-0.5 * dhelp * dhelp);
}
- }
+ }
}else{
k = 1;
for (j=0;j<nd_x;j++){
@@ -1026,17 +1049,17 @@ SpecfitFuns_splitgauss(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- pgauss = (gaussian *) param->data;
+ pgauss = (gaussian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
- dhelp = (*px - pgauss[i].centroid) * (2.0*sqrt(2.0*log2));
- if (dhelp > 0)
- {
- dhelp = dhelp /pgauss[i].fwhm2;
- }else{
- dhelp = dhelp /pgauss[i].fwhm1;
- }
+ dhelp = (*px - pgauss[i].centroid) * (2.0*sqrt(2.0*log2));
+ if (dhelp > 0)
+ {
+ dhelp = dhelp /pgauss[i].fwhm2;
+ }else{
+ dhelp = dhelp /pgauss[i].fwhm1;
+ }
if (dhelp <= 20) {
- *pret += pgauss[i].height * exp (-0.5 * dhelp * dhelp);
+ *pret += pgauss[i].height * exp (-0.5 * dhelp * dhelp);
}
}
pret++;
@@ -1075,40 +1098,40 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1131,7 +1154,7 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1140,12 +1163,12 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = (*px - ppvoigt[i].centroid) / (0.5 * ppvoigt[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1159,7 +1182,7 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = (*px - ppvoigt[i].centroid) / (0.5 * ppvoigt[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1178,11 +1201,11 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
tosigma=1.0/(2.0*sqrt(2.0*log2));
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
sigma = ppvoigt[i].fwhm * tosigma;
dhelp = (*px - ppvoigt[i].centroid)/sigma;
@@ -1198,7 +1221,7 @@ SpecfitFuns_apvoigt(PyObject *self, PyObject *args)
k = (int) (dim_x [j] * k);
}
for (j=0;j<k;j++){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
sigma = ppvoigt[i].fwhm * tosigma;
dhelp = (*px - ppvoigt[i].centroid)/sigma;
@@ -1249,40 +1272,40 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1305,7 +1328,7 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1314,12 +1337,12 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = (*px - ppvoigt[i].centroid) / (0.5 * ppvoigt[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1332,7 +1355,7 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = (*px - ppvoigt[i].centroid) / (0.5 * ppvoigt[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1348,11 +1371,11 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
log2 = 0.69314718055994529;
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = ppvoigt[i].fwhm/(2.0*sqrt(2.0*log2));
dhelp = (*px - ppvoigt[i].centroid)/dhelp;
@@ -1367,7 +1390,7 @@ SpecfitFuns_pvoigt(PyObject *self, PyObject *args)
k = (int) (dim_x [j] * k);
}
for (j=0;j<k;j++){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = ppvoigt[i].fwhm/(2.0*sqrt(2.0*log2));
dhelp = (*px - ppvoigt[i].centroid)/dhelp;
@@ -1416,40 +1439,40 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1472,7 +1495,7 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1481,19 +1504,19 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/5);i++){
dhelp = (*px - ppvoigt[i].centroid);
- if (dhelp > 0){
- dhelp = dhelp /(0.5 * ppvoigt[i].fwhm2);
- }else{
- dhelp = dhelp /(0.5 * ppvoigt[i].fwhm1);
- }
+ if (dhelp > 0){
+ dhelp = dhelp /(0.5 * ppvoigt[i].fwhm2);
+ }else{
+ dhelp = dhelp /(0.5 * ppvoigt[i].fwhm1);
+ }
dhelp = 1.0 + (dhelp * dhelp);
*pret += ppvoigt[i].eta * (ppvoigt[i].height / dhelp);
}
@@ -1504,14 +1527,14 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/5);i++){
dhelp = (*px - ppvoigt[i].centroid);
- if (dhelp > 0){
- dhelp = dhelp /(0.5 * ppvoigt[i].fwhm2);
- }else{
- dhelp = dhelp /(0.5 * ppvoigt[i].fwhm1);
- }
+ if (dhelp > 0){
+ dhelp = dhelp /(0.5 * ppvoigt[i].fwhm2);
+ }else{
+ dhelp = dhelp /(0.5 * ppvoigt[i].fwhm1);
+ }
dhelp = 1.0 + (dhelp * dhelp);
*pret += ppvoigt[i].eta * (ppvoigt[i].height / dhelp);
}
@@ -1525,18 +1548,18 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
log2 = 0.69314718055994529;
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/5);i++){
- dhelp = (*px - ppvoigt[i].centroid);
- if (dhelp >0){
- dhelp = dhelp /(ppvoigt[i].fwhm2/(2.0*sqrt(2.0*log2)));
- }else{
- dhelp = dhelp /(ppvoigt[i].fwhm1/(2.0*sqrt(2.0*log2)));
- }
+ dhelp = (*px - ppvoigt[i].centroid);
+ if (dhelp >0){
+ dhelp = dhelp /(ppvoigt[i].fwhm2/(2.0*sqrt(2.0*log2)));
+ }else{
+ dhelp = dhelp /(ppvoigt[i].fwhm1/(2.0*sqrt(2.0*log2)));
+ }
if (dhelp <= 35) {
*pret += (1.0 - ppvoigt[i].eta) * ppvoigt[i].height \
* exp (-0.5 * dhelp * dhelp);
@@ -1548,14 +1571,14 @@ SpecfitFuns_splitpvoigt(PyObject *self, PyObject *args)
k = (int) (dim_x [j] * k);
}
for (j=0;j<k;j++){
- ppvoigt = (pvoigtian *) param->data;
+ ppvoigt = (pvoigtian *) PyArray_DATA(param);
for (i=0;i<(npars/5);i++){
- dhelp = (*px - ppvoigt[i].centroid);
- if (dhelp > 0){
- dhelp = dhelp /(ppvoigt[i].fwhm2/(2.0*sqrt(2.0*log2)));
- }else{
- dhelp = dhelp /(ppvoigt[i].fwhm1/(2.0*sqrt(2.0*log2)));
- }
+ dhelp = (*px - ppvoigt[i].centroid);
+ if (dhelp > 0){
+ dhelp = dhelp /(ppvoigt[i].fwhm2/(2.0*sqrt(2.0*log2)));
+ }else{
+ dhelp = dhelp /(ppvoigt[i].fwhm1/(2.0*sqrt(2.0*log2)));
+ }
if (dhelp <= 35) {
*pret += (1.0 - ppvoigt[i].eta) * ppvoigt[i].height \
* exp (-0.5 * dhelp * dhelp);
@@ -1599,40 +1622,40 @@ SpecfitFuns_lorentz(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1655,7 +1678,7 @@ SpecfitFuns_lorentz(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1664,12 +1687,12 @@ SpecfitFuns_lorentz(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = (*px - plorentz[i].centroid) / (0.5 * plorentz[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1682,7 +1705,7 @@ SpecfitFuns_lorentz(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = (*px - plorentz[i].centroid) / (0.5 * plorentz[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1724,40 +1747,40 @@ SpecfitFuns_alorentz(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1780,7 +1803,7 @@ SpecfitFuns_alorentz(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1789,12 +1812,12 @@ SpecfitFuns_alorentz(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = (*px - plorentz[i].centroid) / (0.5 * plorentz[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1807,7 +1830,7 @@ SpecfitFuns_alorentz(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = (*px - plorentz[i].centroid) / (0.5 * plorentz[i].fwhm);
dhelp = 1.0 + (dhelp * dhelp);
@@ -1849,40 +1872,40 @@ SpecfitFuns_splitlorentz(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -1905,7 +1928,7 @@ SpecfitFuns_splitlorentz(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -1914,19 +1937,19 @@ SpecfitFuns_splitlorentz(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = *px - plorentz[i].centroid;
- if (dhelp > 0){
- dhelp = dhelp /(0.5 * plorentz[i].fwhm2);
- }else{
- dhelp = dhelp /(0.5 * plorentz[i].fwhm1);
- }
+ if (dhelp > 0){
+ dhelp = dhelp /(0.5 * plorentz[i].fwhm2);
+ }else{
+ dhelp = dhelp /(0.5 * plorentz[i].fwhm1);
+ }
dhelp = 1.0 + (dhelp * dhelp);
*pret += (plorentz[i].height / dhelp);
}
@@ -1937,16 +1960,16 @@ SpecfitFuns_splitlorentz(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- plorentz = (lorentzian *) param->data;
+ plorentz = (lorentzian *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = *px - plorentz[i].centroid;
- if (dhelp > 0){
- dhelp = dhelp /(0.5 * plorentz[i].fwhm2);
- }else{
- dhelp = dhelp /(0.5 * plorentz[i].fwhm1);
- }
- dhelp = 1.0 + (dhelp * dhelp);
- *pret += (plorentz[i].height / dhelp);
+ if (dhelp > 0){
+ dhelp = dhelp /(0.5 * plorentz[i].fwhm2);
+ }else{
+ dhelp = dhelp /(0.5 * plorentz[i].fwhm1);
+ }
+ dhelp = 1.0 + (dhelp * dhelp);
+ *pret += (plorentz[i].height / dhelp);
}
pret++;
px++;
@@ -1985,40 +2008,40 @@ SpecfitFuns_downstep(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -2041,7 +2064,7 @@ SpecfitFuns_downstep(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2050,15 +2073,15 @@ SpecfitFuns_downstep(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
tosigma=1.0/(2.0*sqrt(2.0*log(2.0)));
if (nd_x == 0){
*pret = 0;
- perrorfc = (errorfc *) param->data;
+ perrorfc = (errorfc *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = perrorfc[i].fwhm * tosigma;
dhelp = (*px - perrorfc[i].centroid) / (sqrt(2)*dhelp);
@@ -2071,7 +2094,7 @@ SpecfitFuns_downstep(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- perrorfc = (errorfc *) param->data;
+ perrorfc = (errorfc *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = perrorfc[i].fwhm * tosigma;
dhelp = (*px - perrorfc[i].centroid) / (sqrt(2)*dhelp);
@@ -2114,40 +2137,40 @@ SpecfitFuns_upstep(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -2170,7 +2193,7 @@ SpecfitFuns_upstep(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2179,14 +2202,14 @@ SpecfitFuns_upstep(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
tosigma=1.0/(2.0*sqrt(2.0*log(2.0)));
if (nd_x == 0){
*pret = 0;
- perrorf = (errorf *) param->data;
+ perrorf = (errorf *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = perrorf[i].fwhm * tosigma;
dhelp = (*px - perrorf[i].centroid) / (sqrt(2)*dhelp);
@@ -2199,7 +2222,7 @@ SpecfitFuns_upstep(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- perrorf = (errorf *) param->data;
+ perrorf = (errorf *) PyArray_DATA(param);
for (i=0;i<(npars/3);i++){
dhelp = perrorf[i].fwhm * tosigma;
dhelp = (*px - perrorf[i].centroid) / (sqrt(2)*dhelp);
@@ -2243,40 +2266,40 @@ SpecfitFuns_slit(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -2299,7 +2322,7 @@ SpecfitFuns_slit(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2308,14 +2331,14 @@ SpecfitFuns_slit(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
tosigma=1.0/(2.0*sqrt(2.0*log(2.0)));
if (nd_x == 0){
*pret = 0;
- perrorf = (errorf *) param->data;
+ perrorf = (errorf *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = perrorf[i].beamfwhm * tosigma;
centroid1=perrorf[i].position - 0.5 * perrorf[i].fwhm;
@@ -2331,7 +2354,7 @@ SpecfitFuns_slit(PyObject *self, PyObject *args)
}
for (j=0;j<k;j++){
*pret = 0;
- perrorf = (errorf *) param->data;
+ perrorf = (errorf *) PyArray_DATA(param);
for (i=0;i<(npars/4);i++){
dhelp = perrorf[i].beamfwhm * tosigma;
centroid1=perrorf[i].position - 0.5 * perrorf[i].fwhm;
@@ -2370,26 +2393,26 @@ SpecfitFuns_erfc(PyObject *self, PyObject *args)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (x == NULL){
return NULL;
}
- nd_x = x->nd;
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_x = %d\n",nd_x);
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -2398,7 +2421,7 @@ SpecfitFuns_erfc(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(x);
return NULL;
@@ -2406,8 +2429,8 @@ SpecfitFuns_erfc(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
dhelp = *px;
@@ -2450,26 +2473,26 @@ SpecfitFuns_erf(PyObject *self, PyObject *args)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (x == NULL){
return NULL;
}
- nd_x = x->nd;
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_x = %d\n",nd_x);
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
@@ -2478,7 +2501,7 @@ SpecfitFuns_erf(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(x);
return NULL;
@@ -2486,8 +2509,8 @@ SpecfitFuns_erf(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if (nd_x == 0){
dhelp = *px;
@@ -2546,46 +2569,46 @@ SpecfitFuns_ahypermet(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
/* The gaussian terms must always be there */
if(tails <= 0){
/* I give back a matrix filled with zeros */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2627,7 +2650,7 @@ SpecfitFuns_ahypermet(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2640,9 +2663,9 @@ SpecfitFuns_ahypermet(PyObject *self, PyObject *args)
tosigma=1.0/(2.0*sqrt(2.0*log2));
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
- phyper = (hypermet *) param->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
+ phyper = (hypermet *) PyArray_DATA(param);
if(0){
if(debug !=0){
for (i=0;i<(npars/expected_pars);i++){
@@ -2652,7 +2675,7 @@ printf("Area%d=%f,Pos%d=%f,FWHM%d=%f\n",i,phyper[i].area,i,phyper[i].position,i,
}
if (nd_x == 0){
*pret = 0;
- phyper = (hypermet *) param->data;
+ phyper = (hypermet *) PyArray_DATA(param);
for (i=0;i<(npars/expected_pars);i++){
/* g_term = st_term = lt_term = step_term = 0; */
x1 = phyper[i].area;
@@ -2716,7 +2739,7 @@ printf("LT_Area=%f,LT_Slope=%f\n",phyper[i].lt_area_r,phyper[i].lt_slope_r);
}
for (j=0;j<k;j++){
*pret = 0;
- phyper = (hypermet *) param->data;
+ phyper = (hypermet *) PyArray_DATA(param);
for (i=0;i<(npars/expected_pars);i++){
/* g_term = st_term = lt_term = step_term = 0; */
x1 = phyper[i].area;
@@ -2867,46 +2890,46 @@ SpecfitFuns_fastahypermet(PyObject *self, PyObject *args)
return NULL;
param = (PyArrayObject *)
- PyArray_ContiguousFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(input1, NPY_DOUBLE,0,0);
if (param == NULL)
return NULL;
x = (PyArrayObject *)
- PyArray_ContiguousFromObject(input2, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(input2, NPY_DOUBLE,0,0);
if (x == NULL){
Py_DECREF(param);
return NULL;
}
- nd_param = param->nd;
- nd_x = x->nd;
+ nd_param = PyArray_NDIM(param);
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_param = %d nd_x = %d\n",nd_param,nd_x);
}
if (nd_param == 1) {
- dim_param [0] = param->dimensions[0];
+ dim_param [0] = PyArray_DIMS(param)[0];
dim_param [1] = 0;
}else{
- dim_param [0] = param->dimensions[0];
- dim_param [1] = param->dimensions[1];
+ dim_param [0] = PyArray_DIMS(param)[0];
+ dim_param [1] = PyArray_DIMS(param)[1];
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
/* The gaussian terms must always be there */
if(tails <= 0){
/* I give back a matrix filled with zeros */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2948,7 +2971,7 @@ SpecfitFuns_fastahypermet(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(param);
Py_DECREF(x);
@@ -2961,9 +2984,9 @@ SpecfitFuns_fastahypermet(PyObject *self, PyObject *args)
tosigma=1.0/(2.0*sqrt(2.0*log2));
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
- phyper = (hypermet *) param->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
+ phyper = (hypermet *) PyArray_DATA(param);
if(0){
if(debug !=0){
for (i=0;i<(npars/expected_pars);i++){
@@ -2973,7 +2996,7 @@ printf("Area%d=%f,Pos%d=%f,FWHM%d=%f\n",i,phyper[i].area,i,phyper[i].position,i,
}
if (nd_x == 0){
*pret = 0;
- phyper = (hypermet *) param->data;
+ phyper = (hypermet *) PyArray_DATA(param);
for (i=0;i<(npars/expected_pars);i++){
/* g_term = st_term = lt_term = step_term = 0; */
x1 = phyper[i].area;
@@ -3040,13 +3063,13 @@ printf("LT_Area=%f,LT_Slope=%f\n",phyper[i].lt_area_r,phyper[i].lt_slope_r);
for (j=0;j<nd_x;j++){
k = (int) (dim_x [j] * k);
}
- phyper = (hypermet *) param->data;
+ phyper = (hypermet *) PyArray_DATA(param);
for (i=0;i<(npars/expected_pars);i++){
if (i == 0){
*pret = 0;
}else{
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
}
x1 = phyper[i].area;
x2 = phyper[i].position;
@@ -3174,29 +3197,29 @@ SpecfitFuns_seek(PyObject *self, PyObject *args)
&debug_info, &relevance_info ))
return NULL;
yspec = (PyArrayObject *)
- PyArray_CopyFromObject(input, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input, NPY_DOUBLE,0,0);
if (yspec == NULL)
return NULL;
if (Sensitivity < 0.1) {
Sensitivity = 3.25;
}
- nd = yspec->nd;
+ nd = PyArray_NDIM(yspec);
if (nd == 0) {
printf("I need at least a vector!\n");
Py_DECREF(yspec);
return NULL;
}
- nchannels = (long) yspec->dimensions[0];
+ nchannels = (long) PyArray_DIMS(yspec)[0];
if (nd > 1) {
if (nchannels == 1){
- nchannels = (long) yspec->dimensions[0];
+ nchannels = (long) PyArray_DIMS(yspec)[0];
}
}
- pvalues = (double *) yspec->data;
+ pvalues = (double *) PyArray_DATA(yspec);
seek_result=SpecfitFuns_seek2(BeginChannel, EndChannel, nchannels,
FWHM, Sensitivity, debug_info,
@@ -3215,19 +3238,18 @@ SpecfitFuns_seek(PyObject *self, PyObject *args)
if (relevance_info) {
dimensions [0] = npeaks;
dimensions [1] = 2;
- result = (PyArrayObject *) PyArray_SimpleNew(2,dimensions,PyArray_DOUBLE);
+ result = (PyArrayObject *) PyArray_SimpleNew(2,dimensions,NPY_DOUBLE);
+ pvalues = (double *) PyArray_DATA(result);
for (i=0;i<npeaks;i++){
- /*printf("Peak %ld found at %g rel %g\n",i+1,peaks[i],relevances[i]);*/
- *((double *) (result->data + i*result->strides[0])) = peaks[i];
- *((double *) (result->data +(i*result->strides[0] + result->strides[1]))) = relevances[i];
+ pvalues[2*i] = peaks[i];
+ pvalues[2*i + 1] = relevances[i];
}
-
}else{
dimensions [0] = npeaks;
- result = (PyArrayObject *) PyArray_SimpleNew(1,dimensions,PyArray_DOUBLE);
+ result = (PyArrayObject *) PyArray_SimpleNew(1,dimensions,NPY_DOUBLE);
+ pvalues = (double *) PyArray_DATA(result);
for (i=0;i<npeaks;i++){
- /*printf("Peak %ld found at %g\n",i+1,peaks[i]);*/
- *((double *) (result->data +i*result->strides[0])) = peaks[i];
+ pvalues[i] = peaks[i];
}
}
return PyArray_Return(result);
@@ -3507,8 +3529,8 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
npy_intp nd_y, nd_x, index1, *points, *indices, max_points;
/*int dimensions[1];*/
npy_intp npoints;
- npy_intp dimensions[1];
- npy_intp dim_xinter[1];
+ npy_intp dimensions[2];
+ npy_intp dim_xinter[2];
double *helppointer;
/* statements */
@@ -3517,12 +3539,12 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
return NULL;
}
ydata = (PyArrayObject *)
- PyArray_CopyFromObject(yinput, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(yinput, NPY_DOUBLE,0,0);
if (ydata == NULL){
printf("Copy from Object error!\n");
return NULL;
}
- nd_y = ydata->nd;
+ nd_y = PyArray_NDIM(ydata);
if (nd_y == 0) {
printf("I need at least a vector!\n");
Py_DECREF(ydata);
@@ -3530,7 +3552,7 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
}
/*
for (i=0;i<nd_y;i++){
- printf("Dimension %d = %d\n",i,ydata->dimensions[i]);
+ printf("Dimension %d = %d\n",i,PyArray_DIMS(ydata)[i]);
}
*/
/* xdata parsing */
@@ -3548,11 +3570,11 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
for (i=0;i<nd_y;i++){
/* printf("i = %d\n",i);*/
/*xdata[i] = (PyArrayObject *)
- PyArray_CopyFromObject(yinput,PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(yinput,NPY_DOUBLE,0,0);
*/
xdata[i] = (PyArrayObject *)
PyArray_CopyFromObject((PyObject *)
- (PySequence_Fast_GET_ITEM(xinput,i)), PyArray_DOUBLE,0,0);
+ (PySequence_Fast_GET_ITEM(xinput,i)), NPY_DOUBLE,0,0);
if (xdata[i] == NULL){
printf("x Copy from Object error!\n");
for (j=0;j<i;j++){
@@ -3567,13 +3589,13 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
/* check x dimensions are appropriate */
j=0;
for (i=0;i<nd_y;i++){
- nd_x = xdata[i]->nd;
+ nd_x = PyArray_NDIM(xdata[i]);
if (nd_x != 1) {
printf("I need a vector!\n");
j++;
break;
}
- if (xdata[i]->dimensions[0] != ydata->dimensions[i]){
+ if (PyArray_DIMS(xdata[i])[0] != PyArray_DIMS(ydata)[i]){
printf("xdata[%d] does not have appropriate dimension\n", (int) i);
j++;
break;
@@ -3588,10 +3610,10 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
return NULL;
}
- xinter = (PyArrayObject *) PyArray_ContiguousFromObject(xinter0, PyArray_DOUBLE,0,0);
+ xinter = (PyArrayObject *) PyArray_ContiguousFromObject(xinter0, NPY_DOUBLE,0,0);
- if (xinter->nd == 1){
- dim_xinter[0] = xinter->dimensions[0];
+ if (PyArray_NDIM(xinter) == 1){
+ dim_xinter[0] = PyArray_DIMS(xinter)[0];
dim_xinter[1] = 0;
if (dim_xinter[0] != nd_y){
printf("Wrong size\n");
@@ -3604,8 +3626,8 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
return NULL;
}
}else{
- dim_xinter[0] = xinter->dimensions[0];
- dim_xinter[1] = xinter->dimensions[1];
+ dim_xinter[0] = PyArray_DIMS(xinter)[0];
+ dim_xinter[1] = PyArray_DIMS(xinter)[1];
if (dim_xinter[1] != nd_y){
printf("Wrong size\n");
for (j=0;j<nd_y;j++){
@@ -3618,8 +3640,8 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
}
}
- npoints = xinter->dimensions[0];
- helppointer = (double *) xinter->data;
+ npoints = PyArray_DIMS(xinter)[0];
+ helppointer = (double *) PyArray_DATA(xinter);
/* printf("npoints = %d\n",npoints);
printf("ndimensions y = %d\n",nd_y);
*/
@@ -3637,7 +3659,7 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
factors = malloc(nd_y * sizeof(double));
dimensions [0] = npoints;
- result = (PyArrayObject *) PyArray_SimpleNew(1,dimensions,PyArray_DOUBLE);
+ result = (PyArrayObject *) PyArray_SimpleNew(1,dimensions,NPY_DOUBLE);
for (i=0;i<npoints;i++){
badpoint = 0;
@@ -3645,8 +3667,8 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
index1 = -1;
if (badpoint == 0){
value = *helppointer++;
- k=xdata[j]->dimensions[0] - 1;
- nvalue = (double *) (xdata[j]->data + k * xdata[j]->strides[0]);
+ k=PyArray_DIMS(xdata[j])[0] - 1;
+ nvalue = (double *) (PyArray_BYTES(xdata[j]) + k * (PyArray_STRIDES(xdata[j])[0]));
/* test against other version
valueold = PyFloat_AsDouble(
PySequence_Fast_GET_ITEM(PySequence_Fast_GET_ITEM(xinter0,i),j));
@@ -3657,20 +3679,20 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
if (value > *nvalue){
badpoint = 1;
}else{
- nvalue = (double *) (xdata[j]->data);
+ nvalue = (double *) (PyArray_DATA(xdata[j]));
if (value < *nvalue){
badpoint = 1;
}
}
if (badpoint == 0){
if (1){
- k = xdata[j]->dimensions[0];
+ k = PyArray_DIMS(xdata[j])[0];
jl = -1;
ju = k-1;
if (badpoint == 0){
while((ju-jl) > 1){
k = (ju+jl)/2;
- nvalue = (double *) (xdata[j]->data + k * xdata[j]->strides[0]);
+ nvalue = (double *) (PyArray_BYTES(xdata[j]) + k * (PyArray_STRIDES(xdata[j])[0]));
if (value >= *nvalue){
jl=k;
}else{
@@ -3684,8 +3706,8 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
if (0){
k=0;
ju = -1;
- while(k < (xdata[j]->dimensions[0] - 1)){
- nvalue = (double *) (xdata[j]->data + k * xdata[j]->strides[0]);
+ while(k < (PyArray_DIMS(xdata[j])[0] - 1)){
+ nvalue = (double *) (PyArray_BYTES(xdata[j]) + k * (PyArray_STRIDES(xdata[j])[0]));
/*printf("nvalue = %g\n",*nvalue);*/
if (value >= *nvalue){
ju = k;
@@ -3694,14 +3716,14 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
}
if (ju != index1){
printf("i = %d, j= %d, value = %.5f indexvalue = %d, newvalue = %d\n",\
- (int) i, (int) j,value, (int) ju, (int) index1);
+ (int) i, (int) j,value, (int) ju, (int) index1);
}
}
if (index1 < 0){
badpoint = 1;
}else{
- x1 = (double *) (xdata[j]->data + index1 * xdata[j]->strides[0]);
- x2 = (double *) (xdata[j]->data + (index1+1) * xdata[j]->strides[0]);
+ x1 = (double *) (PyArray_BYTES(xdata[j])+ index1 * (PyArray_STRIDES(xdata[j])[0]));
+ x2 = (double *) (PyArray_BYTES(xdata[j])+(index1+1) * (PyArray_STRIDES(xdata[j])[0]));
factors[j] = (value - *x1) / (*x2 - *x1);
indices[j] = index1;
}
@@ -3738,7 +3760,7 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
}else{
l = ((nd_y * k) + j);
}
- offset += points[(nd_y * k) + j] * (ydata -> strides[j]);
+ offset += points[(nd_y * k) + j] * (PyArray_STRIDES(ydata)[j]);
/*printf("factors[%d] = %g\n",j,factors[j]);*/
if ((l % 2) == 0){
dhelp = (1.0 - factors[j]) * dhelp;
@@ -3746,10 +3768,10 @@ SpecfitFuns_interpol(PyObject *self, PyObject *args)
dhelp = factors[j] * dhelp;
}
}
- yresult += *((double *) (ydata -> data + offset)) * dhelp;
+ yresult += *((double *) (PyArray_BYTES(ydata) + offset)) * dhelp;
}
}
- *((double *) (result->data +i*result->strides[0])) = yresult;
+ *((double *) (PyArray_BYTES(result) + i*PyArray_STRIDES(result)[0])) = yresult;
}
free(points);
free(indices);
@@ -3800,8 +3822,8 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
}
grid = (PyArrayObject *)
- PyArray_ContiguousFromObject(grid_input, PyArray_NOTYPE,0,0);
- switch (grid->descr->type_num){
+ PyArray_ContiguousFromObject(grid_input, NPY_NOTYPE,0,0);
+ switch (PyArray_DESCR(grid)->type_num){
case NPY_DOUBLE:
double_flag = 1;
break;
@@ -3811,12 +3833,12 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
Py_DECREF(grid);
if (double_flag){
grid = (PyArrayObject *)
- PyArray_ContiguousFromObject(grid_input, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(grid_input, NPY_DOUBLE,0,0);
} else {
grid = (PyArrayObject *)
- PyArray_ContiguousFromObject(grid_input, PyArray_FLOAT,0,0);
+ PyArray_ContiguousFromObject(grid_input, NPY_FLOAT,0,0);
}
- nd_grid = grid->nd;
+ nd_grid = PyArray_NDIM(grid);
if (nd_grid == 0) {
printf("Grid should be at least a vector!\n");
Py_DECREF(grid);
@@ -3824,7 +3846,7 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
}
hits = (PyArrayObject *)
- PyArray_ContiguousFromObject(hits_input, PyArray_INT,0,0);
+ PyArray_ContiguousFromObject(hits_input, NPY_INT,0,0);
if (hits == NULL) {
Py_DECREF(grid);
return NULL;
@@ -3846,7 +3868,7 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
}
ydata = (PyArrayObject *)
- PyArray_ContiguousFromObject(yinput, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(yinput, NPY_DOUBLE,0,0);
if (ydata == NULL){
printf("Contiguous from object error!\n");
Py_DECREF(grid);
@@ -3855,7 +3877,7 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
}
limits = (PyArrayObject *)
- PyArray_ContiguousFromObject(limits_input, PyArray_DOUBLE,0,0);
+ PyArray_ContiguousFromObject(limits_input, NPY_DOUBLE,0,0);
if (limits == NULL){
printf("Limits. Contiguous from object error!\n");
Py_DECREF(grid);
@@ -3878,7 +3900,7 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
for (i=0;i<nd_grid;i++){
xdata[i] = (PyArrayObject *)
PyArray_ContiguousFromObject((PyObject *)
- (PySequence_Fast_GET_ITEM(xinput,i)), PyArray_DOUBLE,0,0);
+ (PySequence_Fast_GET_ITEM(xinput,i)), NPY_DOUBLE,0,0);
if (xdata[i] == NULL){
printf("x Copy from Object error!\n");
for (j=0;j<i;j++){
@@ -3911,24 +3933,24 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
if (i==0){
delta_index[nd_grid-1] = 1;
}else{
- delta_index[nd_grid-1-i] = delta_index[nd_grid-i] * grid->dimensions[nd_grid-i];
+ delta_index[nd_grid-1-i] = delta_index[nd_grid-i] * PyArray_DIMS(grid)[nd_grid-i];
}
}
/* get the number of points in each of the arrays */
npoints = 0;
- for (i=0; i<ydata->nd;i++){
+ for (i=0; i<PyArray_NDIM(ydata);i++){
if (i==0)
- npoints = ydata->dimensions[0];
+ npoints = PyArray_DIMS(ydata)[0];
else
- npoints *= ydata->dimensions[i];
+ npoints *= PyArray_DIMS(ydata)[i];
}
/* do the work */
- data_pointer = (double *) ydata->data;
- grid_pointerf = (float *) grid->data;
- grid_pointerd = (double *) grid->data;
- hits_pointer = (int *) hits->data;
+ data_pointer = (double *) PyArray_DATA(ydata);
+ grid_pointerf = (float *) PyArray_DATA(grid);
+ grid_pointerd = (double *) PyArray_DATA(grid);
+ hits_pointer = (int *) PyArray_DATA(hits);
for (i=0;i<npoints;i++){
if (use_datathreshold){
@@ -3938,13 +3960,13 @@ SpecfitFuns_voxelize(PyObject *self, PyObject *args)
goodpoint = 1;
grid_position = 0;
for (j=0; j< nd_grid; j++){
- double_pointer = (double *) xdata[j]->data;
+ double_pointer = (double *) PyArray_DATA(xdata[j]);
value = *(double_pointer+i);
- double_pointer = (double *) limits->data;
+ double_pointer = (double *) PyArray_DATA(limits);
limit0 = *(double_pointer+j);
limit1 = *(double_pointer+j+nd_grid);
- index = (int)(grid->dimensions[j]*(value - limit0)/(limit1-limit0));
- if ((index < 0) || (index >= grid->dimensions[j]))
+ index = (int)(PyArray_DIMS(grid)[j]*(value - limit0)/(limit1-limit0));
+ if ((index < 0) || (index >= PyArray_DIMS(grid)[j]))
{
/* this point is not going to contribute */
goodpoint = 0;
@@ -3993,25 +4015,25 @@ SpecfitFuns_pileup(PyObject *self, PyObject *args)
return NULL;
x = (PyArrayObject *)
- PyArray_CopyFromObject(input1, PyArray_DOUBLE,0,0);
+ PyArray_CopyFromObject(input1, NPY_DOUBLE,0,0);
if (x == NULL)
return NULL;
- nd_x = x->nd;
+ nd_x = PyArray_NDIM(x);
if(debug !=0) {
printf("nd_x = %d\n",nd_x);
}
if (nd_x == 1) {
- dim_x [0] = x->dimensions[0];
+ dim_x [0] = PyArray_DIMS(x)[0];
dim_x [1] = 0;
}else{
if (nd_x == 0) {
dim_x [0] = 0;
dim_x [1] = 0;
}else{
- dim_x [0] = x->dimensions[0];
- dim_x [1] = x->dimensions[1];
+ dim_x [0] = PyArray_DIMS(x)[0];
+ dim_x [1] = PyArray_DIMS(x)[1];
}
}
if(debug !=0) {
@@ -4019,7 +4041,7 @@ SpecfitFuns_pileup(PyObject *self, PyObject *args)
}
/* Create the output array */
- ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, PyArray_DOUBLE);
+ ret = (PyArrayObject *) PyArray_SimpleNew(nd_x, dim_x, NPY_DOUBLE);
if (ret == NULL){
Py_DECREF(x);
return NULL;
@@ -4027,17 +4049,17 @@ SpecfitFuns_pileup(PyObject *self, PyObject *args)
PyArray_FILLWBYTE(ret, 0);
/* the pointer to the starting position of par data */
- px = (double *) x->data;
- pret = (double *) ret->data;
+ px = (double *) PyArray_DATA(x);
+ pret = (double *) PyArray_DATA(ret);
if(1){
*pret = 0;
k = (int )(zero/gain);
for (i=input2;i<dim_x[0];i++){
- pall=(double *) x->data;
+ pall=(double *) PyArray_DATA(x);
if ((i+k) >= 0)
{
- pret = (double *) ret->data+(i+k);
+ pret = (double *) PyArray_DATA(ret)+(i+k);
for (j=0;j<dim_x[0]-i-k;j++){
*pret += *px * (*pall);
pall++;
@@ -4070,7 +4092,7 @@ SpecfitFuns_SavitskyGolay(PyObject *self, PyObject *args)
return NULL;
ret = (PyArrayObject *)
- PyArray_FROMANY(input, PyArray_DOUBLE, 1, 1, NPY_ENSURECOPY);
+ PyArray_FROMANY(input, NPY_DOUBLE, 1, 1, NPY_ARRAY_ENSURECOPY);
if (ret == NULL){
printf("Cannot create 1D array from input\n");
@@ -4079,7 +4101,7 @@ SpecfitFuns_SavitskyGolay(PyObject *self, PyObject *args)
npoints = (int ) dpoints;
if (!(npoints % 2)) npoints +=1;
- n = (int) ret->dimensions[0];
+ n = (int) PyArray_DIMS(ret)[0];
if((npoints < MIN_SAVITSKY_GOLAY_WIDTH) || (n < npoints))
{
@@ -4096,7 +4118,7 @@ SpecfitFuns_SavitskyGolay(PyObject *self, PyObject *args)
}
/* do the job */
- output = (double *) ret->data;
+ output = (double *) PyArray_DATA(ret);
/* simple smoothing at the beginning */
for (j=0; j<=(int)(npoints/3); j++)
diff --git a/PyMca/specfit/setup.py b/PyMca/specfit/setup.py
index 150bebb..6c4b945 100644
--- a/PyMca/specfit/setup.py
+++ b/PyMca/specfit/setup.py
@@ -22,7 +22,7 @@ setup (
name = "SpecfitFuns",
version = "2.1",
description = "fit functions module",
- author = "V.A. Sole - BLISS Group",
+ author = "V.A. Sole - Software Group",
author_email = "sole@esrf.fr",
url = "http://www.esrf.fr/computing/bliss/",
diff --git a/PyMca/specfit/snip1d.c b/PyMca/specfit/snip1d.c
index a40633e..73c760b 100644
--- a/PyMca/specfit/snip1d.c
+++ b/PyMca/specfit/snip1d.c
@@ -1,140 +1,152 @@
-#/*##########################################################################
-# Copyright (C) 2004-2009 European Synchrotron Radiation Facility
-#
-# This file is part of the PyMCA X-ray Fluorescence Toolkit developed at
-# the ESRF by the Beamline Instrumentation Software Support (BLISS) group.
-#
-# This toolkit 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 2 of the License, or (at your option)
-# any later version.
-#
-# PyMCA 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
-# PyMCA; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
-# Suite 330, Boston, MA 02111-1307, USA.
-#
-# PyMCA follows the dual licensing model of Trolltech's Qt and Riverbank's PyQt
-# and cannot be used as a free plugin for a non-free program.
-#
-# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
-# is a problem for you.
-#############################################################################*/
-/*
- Implementation of the algorithm SNIP in 1D described in
- Miroslav Morhac et al. Nucl. Instruments and Methods in Physics Research A401 (1997) 113-132.
-
- The original idea for 1D and the low-statistics-digital-filter (lsdf) come from
- C.G. Ryan et al. Nucl. Instruments and Methods in Physics Research B34 (1988) 396-402.
-*/
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#define MIN(x, y) (((x) < (y)) ? (x) : (y))
-#define MAX(x, y) (((x) > (y)) ? (x) : (y))
-
-void lls(double *data, int size);
-void lls_inv(double *data, int size);
-void snip1d(double *data, int size, int width);
-void lsdf(double *data, int size, int fwhm, double f, double A, double M, double ratio);
-
-void lls(double *data, int size)
-{
- int i;
- for (i=0; i< size; i++)
- {
- data[i] = log(log(sqrt(data[i]+1.0)+1.0)+1.0);
- }
-}
-
-void lls_inv(double *data, int size)
-{
- int i;
- double tmp;
- for (i=0; i< size; i++)
- {
- /* slightly different than the published formula because
- with the original formula:
-
- tmp = exp(exp(data[i]-1.0)-1.0);
- data[i] = tmp * tmp - 1.0;
-
- one does not recover the original data */
-
- tmp = exp(exp(data[i])-1.0)-1.0;
- data[i] = tmp * tmp - 1.0;
- }
-}
-
-void lsdf(double *data, int size, int fwhm, double f, double A, double M, double ratio)
-{
- int channel, i, j;
- double L, R, S;
- int width;
- double dhelp;
-
- width = (int) (f * fwhm);
- for (channel=width; channel<(size-width); channel++)
- {
- i = width;
- while(i>0)
- {
- L=0;
- R=0;
- for(j=channel-i; j<channel; j++)
- {
- L += data[j];
- }
- for(j=channel+1; j<channel+i; j++)
- {
- R += data[j];
- }
- S = data[channel] + L + R;
- if (S<M)
- {
- data[channel] = S /(2*i+1);
- break;
- }
- dhelp = (R+1)/(L+1);
- if ((dhelp < ratio) && (dhelp > (1/ratio)))
- {
- if (S<(A*sqrt(data[channel])))
- {
- data[channel] = S /(2*i+1);
- break;
- }
- }
- i=i-1;
- }
- }
-}
-
-
-void snip1d(double *data, int size, int width)
-{
- int i;
- int p;
- double *w;
-
- i = (int) (0.5*width);
- /* lsdf(data, size, i, 1.5, 75., 10., 1.3); */
-
- w = (double *) malloc(size * sizeof(double));
-
- for (p=width; p > 0; p--)
- {
- for (i=p; i<(size-p); i++)
- {
- w[i] = MIN(data[i], 0.5*(data[i-p]+data[i+p]));
- }
- for (i=p; i<(size-p); i++)
- {
- data[i] = w[i];
- }
- }
- free(w);
-}
+#/*##########################################################################
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
+#
+# This file is part of the PyMCA X-ray Fluorescence Toolkit developed at
+# the ESRF by the Beamline Instrumentation Software Support (BLISS) group.
+#
+# This toolkit 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 2 of the License, or (at your option)
+# any later version.
+#
+# PyMCA 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
+# PyMCA; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA 02111-1307, USA.
+#
+# PyMCA follows the dual licensing model of Trolltech's Qt and Riverbank's PyQt
+# and cannot be used as a free plugin for a non-free program.
+#
+# Please contact the ESRF industrial unit (industry@esrf.fr) if this license
+# is a problem for you.
+#############################################################################*/
+/*
+ Implementation of the algorithm SNIP in 1D described in
+ Miroslav Morhac et al. Nucl. Instruments and Methods in Physics Research A401 (1997) 113-132.
+
+ The original idea for 1D and the low-statistics-digital-filter (lsdf) come from
+ C.G. Ryan et al. Nucl. Instruments and Methods in Physics Research B34 (1988) 396-402.
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+
+void lls(double *data, int size);
+void lls_inv(double *data, int size);
+void snip1d(double *data, int n_channels, int snip_width);
+void snip1d_multiple(double *data, int n_channels, int snip_width, int n_spectra);
+void lsdf(double *data, int size, int fwhm, double f, double A, double M, double ratio);
+
+void lls(double *data, int size)
+{
+ int i;
+ for (i=0; i< size; i++)
+ {
+ data[i] = log(log(sqrt(data[i]+1.0)+1.0)+1.0);
+ }
+}
+
+void lls_inv(double *data, int size)
+{
+ int i;
+ double tmp;
+ for (i=0; i< size; i++)
+ {
+ /* slightly different than the published formula because
+ with the original formula:
+
+ tmp = exp(exp(data[i]-1.0)-1.0);
+ data[i] = tmp * tmp - 1.0;
+
+ one does not recover the original data */
+
+ tmp = exp(exp(data[i])-1.0)-1.0;
+ data[i] = tmp * tmp - 1.0;
+ }
+}
+
+void lsdf(double *data, int size, int fwhm, double f, double A, double M, double ratio)
+{
+ int channel, i, j;
+ double L, R, S;
+ int width;
+ double dhelp;
+
+ width = (int) (f * fwhm);
+ for (channel=width; channel<(size-width); channel++)
+ {
+ i = width;
+ while(i>0)
+ {
+ L=0;
+ R=0;
+ for(j=channel-i; j<channel; j++)
+ {
+ L += data[j];
+ }
+ for(j=channel+1; j<channel+i; j++)
+ {
+ R += data[j];
+ }
+ S = data[channel] + L + R;
+ if (S<M)
+ {
+ data[channel] = S /(2*i+1);
+ break;
+ }
+ dhelp = (R+1)/(L+1);
+ if ((dhelp < ratio) && (dhelp > (1/ratio)))
+ {
+ if (S<(A*sqrt(data[channel])))
+ {
+ data[channel] = S /(2*i+1);
+ break;
+ }
+ }
+ i=i-1;
+ }
+ }
+}
+
+
+void snip1d(double *data, int n_channels, int snip_width)
+{
+ snip1d_multiple(data, n_channels, snip_width, 1);
+}
+
+void snip1d_multiple(double *data, int n_channels, int snip_width, int n_spectra)
+{
+ int i;
+ int j;
+ int p;
+ int offset;
+ double *w;
+
+ i = (int) (0.5 * snip_width);
+ /* lsdf(data, size, i, 1.5, 75., 10., 1.3); */
+
+ w = (double *) malloc(n_channels * sizeof(double));
+
+ for (j=0; j < n_spectra; j++)
+ {
+ offset = j * n_channels;
+ for (p = snip_width; p > 0; p--)
+ {
+ for (i=p; i<(n_channels - p); i++)
+ {
+ w[i] = MIN(data[i + offset], 0.5*(data[i + offset - p] + data[ i + offset + p]));
+ }
+ for (i=p; i<(n_channels - p); i++)
+ {
+ data[i+offset] = w[i];
+ }
+ }
+ }
+ free(w);
+}
diff --git a/PyMca/sps/Src/sps_py.c b/PyMca/sps/Src/sps_py.c
index be3cfdc..5114863 100644
--- a/PyMca/sps/Src/sps_py.c
+++ b/PyMca/sps/Src/sps_py.c
@@ -30,6 +30,9 @@
#include <sps.h>
/* #include <stdio.h> */
#include <Python.h>
+/* adding next line may raise errors ...
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include <numpy/arrayobject.h>
static PyObject *SPSError;
diff --git a/PyMca/sps/Src/spslut_py.c b/PyMca/sps/Src/spslut_py.c
index 39eae5b..78c5588 100644
--- a/PyMca/sps/Src/spslut_py.c
+++ b/PyMca/sps/Src/spslut_py.c
@@ -1,5 +1,5 @@
#/*##########################################################################
-# Copyright (C) 2004-2011 European Synchrotron Radiation Facility
+# Copyright (C) 2004-2013 European Synchrotron Radiation Facility
#
# This file is part of the PyMCA X-ray Fluorescence Toolkit developed at
# the ESRF by the Beamline Instrumentation Software Support (BLISS) group.
@@ -50,6 +50,9 @@
*/
#include <stdio.h>
#include <Python.h>
+/*
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+*/
#include <numpy/arrayobject.h>
#include <sps_lut.h>
@@ -172,11 +175,11 @@ static PyObject *spslut_transform(PyObject *self, PyObject *args)
}
if (!(src = (PyArrayObject*) PyArray_ContiguousFromObject(in_src,
- PyArray_NOTYPE, 2, 2))) {
+ NPY_NOTYPE, 2, 2))) {
onError("Input Array is not a 2x2 array");
}
- switch (src->descr->type_num) {
+ switch (PyArray_DESCR(src)->type_num) {
case NPY_UINT:
type = SPS_UINT; break;
case NPY_ULONG:
@@ -201,9 +204,9 @@ static PyObject *spslut_transform(PyObject *self, PyObject *args)
onError("Input Array type not supported");
}
- data = src->data;
- cols = (int) src->dimensions[1]; /*FIX THIS cols and rows are turned around */
- rows = (int) src->dimensions[0]; /*###CHANGED - ALEXANDRE 24/07/2001*/
+ data = PyArray_DATA(src);
+ cols = (int) PyArray_DIMS(src)[1]; /*FIX THIS cols and rows are turned around */
+ rows = (int) PyArray_DIMS(src)[0]; /*###CHANGED - ALEXANDRE 24/07/2001*/
@@ -234,7 +237,7 @@ static PyObject *spslut_transform(PyObject *self, PyObject *args)
Py_DECREF(src);
return NULL;
}
- as_pointer = (char *) as_aux -> data;
+ as_pointer = (char *) PyArray_DATA(as_aux);
as_r = (char *) r;
memcpy(as_pointer, as_r, as_dim[0] * as_dim[1]);
@@ -307,11 +310,11 @@ static PyObject *spslut_transformarray(PyObject *self, PyObject *args)
}
if (!(src = (PyArrayObject*) PyArray_ContiguousFromObject(in_src,
- PyArray_NOTYPE, 2, 2))) {
+ NPY_NOTYPE, 2, 2))) {
onError("spslut.transformarray: Input Array is not a 2x2 array");
}
- switch (src->descr->type_num) {
+ switch (PyArray_DESCR(src)->type_num) {
case NPY_ULONG:
type = SPS_ULONG; break;
case NPY_UINT:
@@ -336,9 +339,9 @@ static PyObject *spslut_transformarray(PyObject *self, PyObject *args)
onError("Input Array type not supported");
}
- data = src->data;
- cols = (int) src->dimensions[1]; /*FIX THIS cols and rows are turned around */
- rows = (int) src->dimensions[0]; /*###CHANGED - ALEXANDRE 24/07/2001*/
+ data = PyArray_DATA(src);
+ cols = (int) PyArray_DIMS(src); /*FIX THIS cols and rows are turned around */
+ rows = (int) PyArray_DIMS(src); /*###CHANGED - ALEXANDRE 24/07/2001*/
r = SPS_PaletteArray (data, type, cols, rows, reduc, fastreduc, meth, gamma,
autoscale, mapmin, mapmax, Xservinfo, palette_code,
@@ -350,13 +353,13 @@ static PyObject *spslut_transformarray(PyObject *self, PyObject *args)
as_dim[0] = strlen(mode);
as_dim[1] = prows * pcols;
/* printf("dim[0] = %d dim[1] = %d \"%s\" \n",as_dim[0],as_dim[1],mode); */
- aux = (PyArrayObject*) PyArray_SimpleNew(2, as_dim, PyArray_CHAR);
+ aux = (PyArrayObject*) PyArray_SimpleNew(2, as_dim, NPY_CHAR);
if (aux == NULL){
free(r);
Py_DECREF(src);
return NULL;
}
- as_pointer = (char *) aux -> data;
+ as_pointer = (char *) PyArray_DATA(aux);
as_r = (char *) r;
memcpy(as_pointer, as_r, as_dim[0] * as_dim[1]);
free(r);
diff --git a/changelog.txt b/changelog.txt
index a324727..0ab07cb 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,17 @@
+VERSION 4.7.1
+
+Support SOLEIL multiple-file different-scan-number maps.
+
+Support batch fitting of multiple HDF5 files.
+
+Fast XRF linear fit stack plugin.
+
+Possibility to load image shifts in the image alignment stack plugin.
+
+Basic support of MRC file format.
+
+Add ID08 advanced alignment scan plugin.
+
VERSION 4.7.0
Add basic support for calculating multiple excitation corrections via the
diff --git a/cx_setup.py b/cx_setup.py
index 377ba3a..76b0192 100644
--- a/cx_setup.py
+++ b/cx_setup.py
@@ -1,3 +1,23 @@
+#
+# These Python module have been developed by V.A. Sole, from the European
+# Synchrotron Radiation Facility (ESRF) to build a frozen version of PyMca.
+# Given the nature of this work, these module can be considered public domain.
+# Therefore redistribution and use in source and binary forms, with or without
+# modification, are permitted provided the following disclaimer is accepted:
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND THE ESRF ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) AND/OR THE ESRF BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
# A cx_freeze setup script to create PyMca executables
#
# Use "python cx_setup.py install"
diff --git a/py2app_setup.py b/py2app_setup.py
index 6b31ed6..63fd69e 100755
--- a/py2app_setup.py
+++ b/py2app_setup.py
@@ -1,3 +1,22 @@
+#
+# These Python module have been developed by V.A. Sole, from the European
+# Synchrotron Radiation Facility (ESRF) to build a frozen version of PyMca.
+# Given the nature of this work, these module can be considered public domain.
+# Therefore redistribution and use in source and binary forms, with or without
+# modification, are permitted provided the following disclaimer is accepted:
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND THE ESRF ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) AND/OR THE ESRF BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
"""
Script for building the PyMca bundle.
For a distributable application Platypus is needed
diff --git a/scripts/pymca_win_post_install.py b/scripts/pymca_win_post_install.py
index 363282a..39c7ed2 100644
--- a/scripts/pymca_win_post_install.py
+++ b/scripts/pymca_win_post_install.py
@@ -1,4 +1,29 @@
#!python
+#
+# Copyright (C) 2004-2013 V. Armando Sole - ESRF
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+__license__ = "MIT"
"""Windows-specific part of the installation"""
import os, sys, shutil
@@ -106,5 +131,5 @@ if len(sys.argv) > 1:
elif sys.argv[1] in ['-remove', 'remove']:
remove()
else:
- print "Script was called with option %s" % sys.argv[1]
- print "It has to be called with option -install or -remove"
+ print("Script was called with option %s" % sys.argv[1])
+ print("It has to be called with option -install or -remove")
diff --git a/setup.py b/setup.py
index 70d688f..d7f334b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,22 @@
+#
+# This Python module has been developed by V.A. Sole, from the European
+# Synchrotron Radiation Facility (ESRF) to build PyMca.
+# Given the nature of this work, these module can be considered public domain.
+# Therefore redistribution and use in source and binary forms, with or without
+# modification, are permitted provided the following disclaimer is accepted:
+#
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND THE ESRF ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) AND/OR THE ESRF BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
import sys,os
import glob
import platform
@@ -214,17 +233,26 @@ def build_Object3DCTools(ext_modules):
include_dirs = includes)
ext_modules.append(module)
-def build_Object3DQhull(ext_modules):
+
+def build_Object3DQhull(extensions):
if sys.platform == "win32":
libraries = ['opengl32', 'glu32']
+ elif sys.platform == "darwin":
+ libraries = []
else:
- libraries = ['GL', 'GLU']
- module = Extension(name = 'PyMca.Object3D.Object3DQhull',
- sources = glob.glob('PyMca/Object3D/Object3DQhull/src/*.c'),
- define_macros = define_macros,
- include_dirs = [numpy.get_include()])
+ libraries = ['GL', 'GLU']
+ sources = ["PyMca/Object3D/Object3DQhull/Object3DQhull.c"]
+ sources += glob.glob("third-party/qhull/src/*.c")
+
+ module = Extension(name='PyMca.Object3D.Object3DQhull',
+ sources=sources,
+ define_macros=define_macros,
+ libraries=libraries,
+ include_dirs=[numpy.get_include(),
+ "third-party/qhull/src"])
+
+ extensions.append(module)
- ext_modules.append(module)
def build_PyMcaSciPy(ext_modules):
packages.append('PyMca.PyMcaSciPy')
@@ -550,6 +578,40 @@ description = "Mapping and X-Ray Fluorescence Analysis"
long_description = """Stand-alone application and Python tools for interactive and/or batch processing analysis of X-Ray Fluorescence Spectra. Graphical user interface (GUI) and batch processing capabilities provided
"""
+#######################
+# build_doc commands #
+#######################
+
+try:
+ import sphinx
+ import sphinx.util.console
+ sphinx.util.console.color_terminal = lambda: False
+ from sphinx.setup_command import BuildDoc
+except:
+ sphinx = None
+
+if sphinx:
+ class build_doc(BuildDoc):
+
+ def run(self):
+
+ # make sure the python path is pointing to the newly built
+ # code so that the documentation is built on this and not a
+ # previously installed version
+
+ build = self.get_finalized_command('build')
+ sys.path.insert(0, os.path.abspath(build.build_lib))
+
+ # Build the Users Guide in HTML and TeX format
+ for builder in ('html', 'latex'):
+ self.builder = builder
+ self.builder_target_dir = os.path.join(self.build_dir, builder)
+ self.mkpath(self.builder_target_dir)
+ builder_index = 'index_{0}.txt'.format(builder)
+ BuildDoc.run(self)
+ sys.path.pop(0)
+ cmdclass['build_doc'] = build_doc
+
distrib = setup(name="PyMca",
version= __version__,
description = description,