#
##
## Copyright (C) 2011 John Doe (j.doe@somewhere.org)
## Distributed under the GNU General Public License version 3 or later.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program 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 this program. If not, see http://www.gnu.org/licenses/.
##
from __future__ import print_function
from pyformex.gui.draw import *
## GDS:
## - it does not waste memory, by using a for loop for the min distance
## - multiprocessing implemented, but not for single set.
## For the single subset the distance should be computed between each subset and the full set!
def closest2(X,Y=None,return_dist=False,nproc=1):
"""Find the point of Y closest to each of the points of X.
Parameters:
- `X`: (nX,3) shaped array of points
- `Y`: (nY,3) shaped array of points. If None, Y is taken equal to X,
allowing to search for the closest point in a single set. In the latter
case, the point itself is excluded from the search (as otherwise
that would obviously be the closest one).
- `return_dist`: bool. If True, also returns the distances of the closest
points.
Returns:
- `ind`: (nX,) int array with the index of the closest point in Y to the
points of X
- `dist`: (nX,) float array with the distance of the closest point. This
is equal to length(X-Y[ind]). It is only returned if return_dist is True.
"""
from pyformex import multi
def argmin2(ar):
"""Return both argmin and min"""
ind = ar.argmin()
return ind, ar[ind]
if Y is None:
print ('multiprocessing of closest point in single set not yet implemented')
nproc = 1
if nproc == 1:
if Y is None:
data = []
for i, x in enumerate(X):
d = X.distanceFromPoint(x)
d[i] = d.max()+1.
data.append(argmin2(d))
else:
data = [argmin2(Y.distanceFromPoint(x)) for x in X]
data = array(data)
ind, dist = data[:, 0].astype(Int), data[:, 1]
if return_dist:
return ind, dist
else:
return ind
args = multi.splitArgs((X,Y,return_dist),mask=(1,0,0),nproc=nproc)
tasks = [(closest2, a) for a in args]
res = multi.multitask(tasks, nproc)
if return_dist == False:
return concatenate(res)
else:
ind, dist = [r[0] for r in res], [r[1] for r in res]
return concatenate(ind).astype(Int), concatenate(dist)
def run():
"""Main function.
This is automatically executed on each run of an app.
"""
print("This is the pyFormex template script/app")
clear()
warning('please run as an APP to use multiprocessing')
l = Mesh(eltype='line2')
p = l.rotate(70., 2).subdivide(60000)
p = p.fuse().compact().coords
p[:, 1] = p[:, 1]**1.5
p1 = l.scale(1.5).rotate(100., 2).trl([1., 0., 0.])
p1 = p1.subdivide(30000).fuse().compact().coords
draw(p)
draw(p1, color='red')
print (closest2(p, p1, nproc=-1))
from pyformex.geomtools import closest
print (closest(p, p1)) # this raise MemoryError
if __name__ == '__draw__':
print("Running as a script")
run()
# End