I have a suggestion about modifications to the JTS DD class to yield higher 
performance for certain applications.
 
The JTS DD class provides routines for extending the precision of 
floating-point arithmetic operations by representing numbers using two-doubles 
instead of one (attaining approximately 30 digits of decimal precision).  
Recently, I have been experimenting with using DD in a Java application I have 
for creating Triangulated Irregular Networks (TINs), or "triangular meshes", 
from lidar data.  One of the key operations in all triangular mesh building 
operations is the "in-circle" method which determines if an arrangement of 
neighboring points is triangulated in an optimal manner.   This method gets 
called quite frequently.  For a 1.02 million points sample, my application 
performs about 18.7 in-circle tests.   But because in-circle depends on the 
evaluation of a determinant that can often be very close to zero (but still 
significant), precision is an important consideration. Thus the motivation for 
using DD.  In fact, the DD class actually includes an implementation of a 
method called DD.inCircleDDNormalized().
 
The problem is that DD is substantially more expensive than straight 
floating-point operations. In my testing, I developed two routines, one that 
would use DD only when "absolutely necessary" and one that used it all the 
time.  The runtimes for the application variations were:
 
a)  Standard floating point:  0.769 seconds
b)  Using DD:                 8.078 seconds  
 
Part of that difference is unavoidable.  Extended precision operations simply 
cost more than hardware-based calculations. But looking at the code I noticed 
that one of the features of DD is that in using it, you have to create a very 
large number of short-lived objects.  For example, to add a+b, you need to 
create at least two DD objects (one for a, one for b, and then you can either 
store the result in a or produce a third object depending on whether or not you 
use one of what DD calls "self" methods).  Once you create an object, there is 
no way to set their value so that they may be While Java has made great strides 
over the years in terms of handling the creation and garbage collection of 
large numbers of objects, it would be far more efficient if the DD objects 
could be reused.  
 
For example, I hacked a version of DD to add a couple of "set" methods that let 
me set the values of DD objects.  I created all the DD objects I needed at 
application start up and used the set method to recycle them every time the 
in-circle method was called.  The results:
 
a)  Using DD:                 8.078 seconds 
b)  Recycling Objects:        4.404 seconds 
 
 
The nearly 50 percent reduction in run time was due to just the savings in not 
creating and garbage collecting objects.  The cost of the real work done by DD 
did not change.
 
These changes are only worthwhile in applications that perform a large number 
of the same calculation over-and-over again. Of course, that's just the kind of 
thing that shows up in computational geometry applications.   Although it could 
be argued that "non-mutable" objects are "safer" than mutable objects I believe 
that any developer with basic experience in handling data would understand how 
to use mutable objects without mishap.  And, after all, the authors of DD 
already found it necessary to implement "self" objects that mutate the content 
of DD objects, so there is a precedent.
 
Basically I suggest the introduction methods such as set(),  setSubtract(a,b),  
setMultiply(a,b), etc. to DD. Developers could then allow apply them to their 
code where appropriate.
 
The code snippet below gives the guts of my in-circle implementation. The 
algebra is the same as that used in DD.inCircleDDNormalized().  All DD objects 
are instantiated in the constructor (not shown).
 
            //  inCircle for coordinates a, b, c, d (DD used p instead of d)
            // "q" variables are pre-allocated DD objects.  Set methods are 
            //  used to set values of the object.
 
            q11.setSubtract(a.x, d.x);
            q21.setSubtract(b.x, d.x);
            q31.setSubtract(c.x, d.x);
 
            q12.setSubtract(a.y, d.y);
            q22.setSubtract(b.y, d.y);
            q32.setSubtract(c.y, d.y);
 
            q11s.setSqr(q11);
            q12s.setSqr(q12);
            q21s.setSqr(q21);
            q22s.setSqr(q22);
            q31s.setSqr(q31);
            q32s.setSqr(q32);
 
            q11_22.set(q11);
            q11_32.set(q11);
            q21_12.set(q21);
            q21_32.set(q21);
            q31_22.set(q31);
            q31_12.set(q31);
 
            q21_32.selfMultiply(q32);
            q31_22.selfMultiply(q22);
            q31_12.selfMultiply(q12);
            q11_32.selfMultiply(q32);
            q11_22.selfMultiply(q22);
            q21_12.selfMultiply(q12);
 
            // the following lines use s1,s2,s3, etc. as a convenience
            // naturally, you have to be careful about what you overwrite...
            DD s1 = q11s.selfAdd(q12s);
            DD s2 = q21s.selfAdd(q22s);
            DD s3 = q31s.selfAdd(q32s);
 
            DD t1 = q21_32.selfSubtract(q31_22);
            DD t2 = q31_12.selfSubtract(q11_32);
            DD t3 = q11_22.selfSubtract(q21_12);
 
            s1.selfMultiply(t1);
            s2.selfMultiply(t2);
            s3.selfMultiply(t3);
            s1.selfAdd(s2).selfAdd(s3);
       
            return s1.doubleValue();
------------------------------------------------------------------------------
"Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE
Instantly run your Selenium tests across 300+ browser/OS combos.  Get 
unparalleled scalability from the best Selenium testing platform available.
Simple to use. Nothing to install. Get started now for free."
http://p.sf.net/sfu/SauceLabs
_______________________________________________
Jts-topo-suite-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jts-topo-suite-user

Reply via email to