<p dir="auto">Hi all,<br>
Maybe this is not the right place to ask for hints but is the place that I know ;)</p>
<p dir="auto">In order to improve the efficiency of a python script, I am trying to convert a script based on a lot of "for loop" operations on a points cloud thanks to Numpy to speed up the process.</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/60317740/74780354-b77e3200-529f-11ea-922d-dcec62d36955.JPG"><img src="https://user-images.githubusercontent.com/60317740/74780354-b77e3200-529f-11ea-922d-dcec62d36955.JPG" alt="PointCloud2" style="max-width: 100%;"></a></p>
<p dir="auto">In a nutshell, I have a 3d model represented as a set of 3d points (x,y,z coordinates) contained in a np.array (dimension : (188706, 3))</p>
<div class="highlight highlight-text-md notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[[168.998 167.681   0.]    &lt;-- point 1
 [169.72  167.695   0.]    &lt;-- point 2
 [170.44  167.629   0.]    &lt;-- point 3
 ...
 [148.986 163.271  25.8]    &lt;-- point 188704
 [148.594 163.634  25.8]    &lt;-- point 188705
 [148.547 163.667  25.8]]   &lt;-- point 188706"><pre class="notranslate"><span class="pl-s">[[</span>168.998 167.681   0.<span class="pl-s">]</span>    &lt;-- point 1
 <span class="pl-s">[</span>169.72  167.695   0.<span class="pl-s">]</span>    &lt;-- point 2
 <span class="pl-s">[</span>170.44  167.629   0.<span class="pl-s">]</span>    &lt;-- point 3
 ...
 <span class="pl-s">[</span>148.986 163.271  25.8<span class="pl-s">]</span>    &lt;-- point 188704
 <span class="pl-s">[</span>148.594 163.634  25.8<span class="pl-s">]</span>    &lt;-- point 188705
 <span class="pl-s">[</span>148.547 163.667  25.8<span class="pl-s">]]</span>   &lt;-- point 188706</pre></div>
<p dir="auto">Each pair of [[row <em>x</em>-1][row <em>x</em>]] represents a segment in 3D</p>
<div class="highlight highlight-text-md notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[[168.998 167.681   0.]    [169.72  167.695   0.]    &lt;-- SEGMENT 1 (points 1 &amp; 2)
 [169.72  167.695   0.]    [170.44  167.629   0.]    &lt;-- SEGMENT 2 (points 2 &amp; 3)
 [170.44  167.629   0.]    [171.149 167.483   0.]    &lt;-- SEGMENT 3 (points 3 &amp; 4)
 ...
 [149.328 162.853  25.8]   [148.986 163.271  25.8]    &lt;-- SEGMENT 94351 (points 188703 &amp; 188704)
 [148.986 163.271  25.8]   [148.594 163.634  25.8]    &lt;-- SEGMENT 94352 (points 18874 &amp; 188705)
 [148.594 163.634  25.8]   [148.547 163.667  25.8]]   &lt;-- SEGMENT 94353 (points 188705 &amp; 188706)"><pre class="notranslate"><span class="pl-s">[[</span>168.998 167.681   0.<span class="pl-s">]</span>    <span class="pl-s">[</span>169.72  167.695   0.<span class="pl-s">]</span>    &lt;-- SEGMENT 1 (points 1 &amp; 2)
 <span class="pl-s">[</span>169.72  167.695   0.<span class="pl-s">]</span>    <span class="pl-s">[</span>170.44  167.629   0.<span class="pl-s">]</span>    &lt;-- SEGMENT 2 (points 2 &amp; 3)
 <span class="pl-s">[</span>170.44  167.629   0.<span class="pl-s">]</span>    <span class="pl-s">[</span>171.149 167.483   0.<span class="pl-s">]</span>    &lt;-- SEGMENT 3 (points 3 &amp; 4)
 ...
 <span class="pl-s">[</span>149.328 162.853  25.8<span class="pl-s">]</span>   <span class="pl-s">[</span>148.986 163.271  25.8<span class="pl-s">]</span>    &lt;-- SEGMENT 94351 (points 188703 &amp; 188704)
 <span class="pl-s">[</span>148.986 163.271  25.8<span class="pl-s">]</span>   <span class="pl-s">[</span>148.594 163.634  25.8<span class="pl-s">]</span>    &lt;-- SEGMENT 94352 (points 18874 &amp; 188705)
 <span class="pl-s">[</span>148.594 163.634  25.8<span class="pl-s">]</span>   <span class="pl-s">[</span>148.547 163.667  25.8<span class="pl-s">]]</span>   &lt;-- SEGMENT 94353 (points 188705 &amp; 188706)</pre></div>
<p dir="auto">My goal is to measure the euclidean distance between each ordered points//pair of rows(= the length of each segments) so that I can detect where I need to add more points to represent a bit more the surface of my 3d model. In other words, if the segment length is above a threshold value (=0.5mm), I will have to discretize this particular segment with more points and to add those additional points in my points cloud.</p>
<p dir="auto">I've found a way to measure the euclidean distance recurcively between each rows thanks to this code:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="EuclidianDistance = np.linalg.norm(PtCloud[:-1] - PtCloud[1:],axis=1) "><pre class="notranslate"><span class="pl-v">EuclidianDistance</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-s1">linalg</span>.<span class="pl-en">norm</span>(<span class="pl-v">PtCloud</span>[:<span class="pl-c1">-</span><span class="pl-c1">1</span>] <span class="pl-c1">-</span> <span class="pl-v">PtCloud</span>[<span class="pl-c1">1</span>:],<span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">1</span>) </pre></div>
<p dir="auto">Which gives this result:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[0.72213572 0.72301867 0.72387637 ... 0.54008148 0.5342593  0.05742822]"><pre class="notranslate">[<span class="pl-c1">0.72213572</span> <span class="pl-c1">0.72301867</span> <span class="pl-c1">0.72387637</span> ... <span class="pl-c1">0.54008148</span> <span class="pl-c1">0.5342593</span>  <span class="pl-c1">0.05742822</span>]</pre></div>
<p dir="auto">And I found as well how to descretize a segment according to its vertices (extremities):</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def AddEquidistantPoints(p1, p2, parts):
    return np.stack((np.linspace(p1[0], p2[0], parts + 1), np.linspace(p1[1], p2[1], parts + 1)), axis=-1)

if EuclidianDistance &gt; 0.5mm:
    dist = AddEquidistantPoints(currentRow, previousRow, 10) #10 --&gt; nb subdivisions
"><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-v">AddEquidistantPoints</span>(<span class="pl-s1">p1</span>, <span class="pl-s1">p2</span>, <span class="pl-s1">parts</span>):
    <span class="pl-k">return</span> <span class="pl-s1">np</span>.<span class="pl-en">stack</span>((<span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">p1</span>[<span class="pl-c1">0</span>], <span class="pl-s1">p2</span>[<span class="pl-c1">0</span>], <span class="pl-s1">parts</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span>), <span class="pl-s1">np</span>.<span class="pl-en">linspace</span>(<span class="pl-s1">p1</span>[<span class="pl-c1">1</span>], <span class="pl-s1">p2</span>[<span class="pl-c1">1</span>], <span class="pl-s1">parts</span> <span class="pl-c1">+</span> <span class="pl-c1">1</span>)), <span class="pl-s1">axis</span><span class="pl-c1">=</span><span class="pl-c1">-</span><span class="pl-c1">1</span>)

<span class="pl-k">if</span> <span class="pl-v">EuclidianDistance</span> <span class="pl-c1">&gt;</span> <span class="pl-c1">0.5</span><span class="pl-s1">mm</span>:
    <span class="pl-s1">dist</span> <span class="pl-c1">=</span> <span class="pl-v">AddEquidistantPoints</span>(<span class="pl-s1">currentRow</span>, <span class="pl-s1">previousRow</span>, <span class="pl-c1">10</span>) <span class="pl-c">#10 --&gt; nb subdivisions</span></pre></div>
<p dir="auto">But my first issue is those euclidean distances have only to be computed on points where z coordinates are equals. Have I to split my array when z coordinate are not equals ?<br>
With :</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="PtCloud = np.split(PtCloud, np.where(np.diff(PtCloud[:,2])!=0)[0]+1)"><pre class="notranslate"><span class="pl-v">PtCloud</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">split</span>(<span class="pl-v">PtCloud</span>, <span class="pl-s1">np</span>.<span class="pl-en">where</span>(<span class="pl-s1">np</span>.<span class="pl-en">diff</span>(<span class="pl-v">PtCloud</span>[:,<span class="pl-c1">2</span>])<span class="pl-c1">!=</span><span class="pl-c1">0</span>)[<span class="pl-c1">0</span>]<span class="pl-c1">+</span><span class="pl-c1">1</span>)</pre></div>
<p dir="auto">Which gives me a list of arrays so I suppose I will have unfortunately to use a for loop...</p>
<p dir="auto">Here is the proper behavior represented with Excel:<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/60317740/74780334-ab927000-529f-11ea-9f3c-021187a205a1.JPG"><img src="https://user-images.githubusercontent.com/60317740/74780334-ab927000-529f-11ea-9f3c-021187a205a1.JPG" alt="exemple" style="max-width: 100%;"></a></p>
<p dir="auto">And my second problem is related to the recurcive check and discretization step since I don't know how to implement it with this particular case. I wonder if there is a way to do it without any for loops.</p>
<p dir="auto">So I would be very delighted if anyone could help me solve this challenge as I am currently "stuck".<br>
It starts to be very challenging for me.</p>
<p dir="auto">Thanks in advance,<br>
Hervé</p>
<p dir="auto"><em>Original ticket <a href="http://projects.scipy.org/numpy/ticket/2171" rel="nofollow">http://projects.scipy.org/numpy/ticket/2171</a> on 2012-06-19 by trac user edcjones, assigned to unknown.</em></p>
<p dir="auto">I use up-to-date Debian testing (wheezy) linux, amd64 architecture.  I have installed packages python3.2, version 3.2.3~rc2-1 and python3-numpy, version 1:1.6.2-1.</p>
<p dir="auto">I got the same answers with packages python2.7, version 2.7.3~rc2-2.1, and python-numpy, version 1:1.6.2-1.</p>
<p dir="auto">Create a numpy.float128 scalar whose value is 2**64 - 1, and call it "x". int(x) is incorrect.</p>