<html><head><style type="text/css"><!-- DIV {margin:0px;} --></style></head><body><div style="font-family:arial, helvetica, sans-serif;font-size:10pt;color:#000000;">Hi All,<div><br></div><div>While tracking some lost particles I found a bug in MBOrientedBox::intersect_ray. It was due to subtracting a squared distance. More specifically, the fact that a squared distance becomes larger if the distance is greater than one, but smaller if the distance is less than one (assuming distance is always positive). With Jason's help I tried to make the tolerances used in the test more consistent. Below is a diff of the fix. The fix reduces the number of lost particles by ~50%.</div><div><br></div><div>Are there any changes/suggestions to this diff?</div><div><br></div><div>Brandon</div><div><br></div><div><div>Index: MBOrientedBox.hpp</div><div>===================================================================</div><div>--- MBOrientedBox.hpp &nbsp; (revision
 3533)</div><div>+++ MBOrientedBox.hpp &nbsp; (working copy)</div><div>@@ -53,8 +53,8 @@</div><div>&nbsp;</div><div>&nbsp;&nbsp; inline double inner_radius() const; //!&lt; radius of inscribed sphere</div><div>&nbsp;&nbsp; inline double outer_radius() const; //!&lt; radius of circumscribed sphere</div><div>- &nbsp;inline double outer_radius_squared() const; //!&lt; square of radius of circumsphere</div><div>- &nbsp;inline double inner_radius_squared() const; //!&lt; square of radius if inscribed sphere</div><div>+ &nbsp;inline double outer_radius_squared(const double reps) const; //!&lt; square of (radius+at least epsilon) of circumsphere</div><div>+ &nbsp;inline double inner_radius_squared(const double reps) const; //!&lt; square of (radius-epsilon) of inscribed sphere</div><div>&nbsp;&nbsp; inline double volume() const; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //!&lt; volume of box</div><div>&nbsp;&nbsp; inline MBCartVect dimensions() const;
 &nbsp; &nbsp; &nbsp; //!&lt; number of dimensions for which box is not flat</div><div>&nbsp;&nbsp; inline double area() const; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //!&lt; largest side area</div><div>@@ -176,24 +176,30 @@</div><div>&nbsp;#endif</div><div>&nbsp;}</div><div>&nbsp;</div><div>-double MBOrientedBox::outer_radius_squared() const</div><div>+// Add at least epsilon to the radius, before squaring it.</div><div>+double MBOrientedBox::outer_radius_squared(const double reps) const</div><div>&nbsp;{</div><div>&nbsp;#if MB_ORIENTED_BOX_OUTER_RADIUS</div><div>- &nbsp;return radius * radius;</div><div>+ &nbsp;return (radius+reps)*(radius+reps);</div><div>&nbsp;#elif MB_ORIENTED_BOX_UNIT_VECTORS</div><div>- &nbsp;return length % length;</div><div>+ &nbsp;MBCartVect tmp(length[0]+reps,length[1]+reps,length[2]+reps);</div><div>+ &nbsp;return tmp % tmp;</div><div>&nbsp;#else</div><div>- &nbsp;const MBCartVect half_diag = axis[0] +
 axis[1] + axis[2];</div><div>+ &nbsp;MBCartVect half_diag = axis[0] + axis[1] + axis[2];</div><div>+ &nbsp;half_diag += MBCartVect(reps,reps,reps);</div><div>&nbsp;&nbsp; return half_diag % half_diag;</div><div>&nbsp;#endif</div><div>&nbsp;}</div><div>&nbsp;</div><div>-double MBOrientedBox::inner_radius_squared() const</div><div>+// Subtract epsilon from the length of the shortest axis, before squaring it.</div><div>+double MBOrientedBox::inner_radius_squared(const double reps) const</div><div>&nbsp;{</div><div>&nbsp;#if MB_ORIENTED_BOX_UNIT_VECTORS</div><div>- &nbsp;return length[0] * length[0];</div><div>+ &nbsp;return (length[0]-reps) * (length[0]-reps);</div><div>&nbsp;#else</div><div>- &nbsp;return axis[0] % axis[0];</div><div>+ &nbsp;MBCartVect tmp = axis[0];</div><div>+ &nbsp;tmp -= MBCartVect(reps,reps,reps);</div><div>+ &nbsp;return (tmp % tmp);</div><div>&nbsp;#endif</div><div>&nbsp;}</div><div>&nbsp;</div></div><div><br></div><div><div>Index:
 MBOrientedBox.cpp</div><div>===================================================================</div><div>--- MBOrientedBox.cpp &nbsp; (revision 3533)</div><div>+++ MBOrientedBox.cpp &nbsp; (working copy)</div><div>@@ -477,16 +477,27 @@</div><div>&nbsp;&nbsp; const MBCartVect cx = center - b;</div><div>&nbsp;&nbsp; double dist_s = cx % m;</div><div>&nbsp;&nbsp; double dist_sq = cx % cx - (dist_s*dist_s);</div><div>- &nbsp;double max_diagsq = outer_radius_squared();</div><div>+ &nbsp;double max_diagsq = outer_radius_squared(reps);</div><div>&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; // if greater than the longest diagonal, we don't hit</div><div>- &nbsp;if (dist_sq &gt; max_diagsq+reps)</div><div>+ &nbsp;if (dist_sq &gt; max_diagsq)</div><div>&nbsp;&nbsp; &nbsp; return false;</div><div>- &nbsp;if (len &amp;&amp; dist_s - max_diagsq &gt; *len)</div><div>- &nbsp; &nbsp;return false;</div><div>- &nbsp;</div><div>+</div><div>+ &nbsp;// If the closest
 possible hit is farther than len, we don't want the hit.</div><div>+ &nbsp;// Problem: the previous method was wrong because max_diagsq will be greater</div><div>+ &nbsp;// then max_diag is max_diag&gt;1 but less than max_diag if max_diag&lt;1.</div><div>+ &nbsp;if (len) {</div><div>+ &nbsp; &nbsp;if (max_diagsq&gt;1) {</div><div>+ &nbsp; &nbsp; &nbsp;if (dist_s - max_diagsq &gt; *len)</div><div>+ &nbsp; &nbsp; &nbsp; &nbsp;return false;</div><div>+ &nbsp; &nbsp;} else {</div><div>+ &nbsp; &nbsp; &nbsp;if (dist_s - 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&gt; *len)</div><div>+ &nbsp; &nbsp; &nbsp; &nbsp;return false;</div><div>+ &nbsp; &nbsp;}</div><div>+ &nbsp;}</div><div>+</div><div>&nbsp;&nbsp; &nbsp; // if smaller than shortest diagonal, we do hit</div><div>- &nbsp;if (dist_sq &lt; inner_radius_squared() - reps &amp;&amp; dist_s &gt;= 0.0)</div><div>+ &nbsp;if (dist_sq &lt; inner_radius_squared(reps) &amp;&amp; dist_s &gt;= 0.0)</div><div>&nbsp;&nbsp;
 &nbsp; return true;</div><div>&nbsp;&nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; // get transpose of axes</div></div></div><br>

      </body></html>