All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Functions | Variables
test_distance Namespace Reference

Functions

def test_dAlgo
 

Variables

int _epsilon = 1
 
string OK = '\033[92m'
 
string NO = '\033[91m'
 
string BLUE = '\033[94m'
 
string ENDC = '\033[0m'
 

Function Documentation

def test_distance.test_dAlgo ( )

Definition at line 17 of file larcorealg/test/GeoAlgo/test_distance.py.

17 
18 def test_dAlgo():
19 
20  debug()
21  debug(BLUE + "Precision Being Required to Consider Two numbers Equal: {0:.2e}".format(_epsilon) + ENDC)
22  debug()
23 
24  # number of times to test each function
25  tests = 10000
26 
27  # import Distance Algo
28  dAlgo = geoalgo.GeoAlgo()
29 
30  try:
31 
32  # test distance from point to infinite line
33  info('Testing Point & Infinite Line Distance')
34  totSuccess = 0
35  sqdistT = 0
36  closestT = 0
37  for y in range(tests):
38  success = 1
39  # generate a random point (will be point on line closest to external point
41  # second point on line
43  # generate random line
44  l = geoalgo.Line(p1,p2)
45  # generate a point in a direction transverse to the line
46  transX = random()
47  transY = random()
48  # now ensure perpendicularity by having dot product be == 0
49  dirct = l.Pt2()-l.Pt1()
50  transZ = (-transX*dirct[0]-transY*dirct[1])/dirct[2]
51  vectTranslate = geoalgo.Vector(transX,transY,transZ)
52  # generate point away starting from p1
53  pt = geoalgo.Vector(p1+vectTranslate)
54  # answer will be vectTranslate sq. length
55  answer = vectTranslate.SqLength()
56  # closest point will be p1
57  tim = time()
58  a1 = dAlgo.SqDist(pt,l)
59  sqdistT += (time()-tim)
60  a2 = dAlgo.SqDist(l,pt)
61  tim = time()
62  pAnswer1 = dAlgo.ClosestPt(pt,l)
63  closestT += (time()-tim)
64  pAnswer2 = dAlgo.ClosestPt(l,pt)
65  if not ( abs(answer-a1) < _epsilon ) : success = 0
66  if not ( abs(answer-a2) < _epsilon ) : success = 0
67  for x in xrange(3):
68  if not ( abs(p1[x]-pAnswer1[x]) < _epsilon) : success = 0
69  if not ( abs(p1[x]-pAnswer2[x]) < _epsilon) : success = 0
70  totSuccess += success
71  if ( float(totSuccess)/tests < 1):
72  info(NO + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
73  else:
74  info(OK + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
75  info("Time for SqDist : {0:.3f} us".format(1E6*sqdistT/tests))
76  info("Time for ClosestPt : {0:.3f} us".format(1E6*closestT/tests))
77 
78  # test distance from point to segment
79  info('Testing Point & LineSegment Distance')
80  totSuccess = 0
81  sqdistT_out = 0.
82  closestT_out = 0.
83  sqdistT_in = 0.
84  closestT_in = 0.
85  for y in range(tests):
86  success = 1
87  # generate a random segment
89  # get the segment length
90  lLen = l.Dir().Length()
91  # get the segment direction
92  d = l.Dir()
93  # generate a segment parallel to it
94  # to get a line parallel to the first,
95  # translate the Start and End points
96  # by some amount in a direction perpendicular
97  # to that of the original line
98  transX = random()
99  transY = random()
100  # now ensure perpendicularity by having dot product be == 0
101  transZ = (-transX*d[0]-transY*d[1])/d[2]
102  vectTranslate = geoalgo.Vector(transX,transY,transZ)
103  p1 = l.Start()+vectTranslate
104  p2 = l.End()+vectTranslate
105  # parallel segment:
106  lPar = geoalgo.LineSegment(p1,p2)
107 
108  # first, test a point that is "before start point"
109  # distance to this point should be distance between lines
110  # in quadrature with how much further from start point we go
111  dist = random()
112  # direction vector outwards from line
113  dirOut = lPar.Dir()*(-1*dist/lPar.Dir().Length())
114  pTest = p1+dirOut
115  answer = dirOut.SqLength()+vectTranslate.SqLength()
116  tim = time()
117  a1 = dAlgo.SqDist(pTest,l)
118  sqdistT_out += (time() - tim)
119  a2 = dAlgo.SqDist(l,pTest)
120  if not ( abs(answer-a1) < _epsilon): success = 0
121  if not ( abs(answer-a2) < _epsilon): success = 0
122  tim = time()
123  point1 = dAlgo.ClosestPt(pTest,l)
124  closestT_out += (time() - tim)
125  point2 = dAlgo.ClosestPt(l,pTest)
126  for x in xrange(3):
127  if not ( (l.Start()[x]-point1[x]) < _epsilon ) : success = 0
128  if not ( (l.Start()[x]-point2[x]) < _epsilon ) : success = 0
129 
130  # now, test a point inside the segment.
131  # distance between point & segment should be
132  # pre-determined distance between the two segments
133  dist = random()
134  dirIn = lPar.Dir()*dist #dist ensures < distance of full segment
135  pTest = p1+dirIn
136  answer = vectTranslate.SqLength()
137  tim = time()
138  a1 = dAlgo.SqDist(pTest,l)
139  sqdistT_in += (time() - tim)
140  a2 = dAlgo.SqDist(l,pTest)
141  if not (abs(answer-a1) < _epsilon): success = 0
142  if not (abs(answer-a2) < _epsilon): success = 0
143  pAns = l.Start()+dirIn
144  tim = time()
145  point1 = dAlgo.ClosestPt(pTest,l)
146  closestT_in += (time() - tim)
147  point2 = dAlgo.ClosestPt(l,pTest)
148  for x in xrange(3):
149  if not ( (pAns[x]-point1[x]) < _epsilon ) : success = 0
150  if not ( (pAns[x]-point2[x]) < _epsilon ) : success = 0
151 
152  # now test a point beyond the segment
153  dist = random()
154  dirOut = lPar.Dir()*(dist/lPar.Dir().Length())
155  pTest = p2+dirOut
156  answer = dirOut.SqLength()+vectTranslate.SqLength()
157  if not ( abs(answer-dAlgo.SqDist(pTest,l)) < _epsilon): success = 0
158  if not ( abs(answer-dAlgo.SqDist(l,pTest)) < _epsilon): success = 0
159  point1 = dAlgo.ClosestPt(pTest,l)
160  point2 = dAlgo.ClosestPt(pTest,l)
161  for x in xrange(3):
162  if not ( (l.End()[x]-point1[x]) < _epsilon ) : success = 0
163  if not ( (l.End()[x]-point2[x]) < _epsilon ) : success = 0
164 
165  if (success == 1) : totSuccess += 1
166  if ( float(totSuccess)/tests < 1):
167  info(NO + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
168  else:
169  info(OK + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
170  info("Time for SqDist (Pt Out of Segment) : {0:.3f} us".format(1E6*sqdistT_out/tests))
171  info("Time for ClosestPt (Pt Out of Segment): {0:.3f} us".format(1E6*closestT_out/tests))
172  info("Time for SqDist (Pt In Segment) : {0:.3f} us".format(1E6*sqdistT_in/tests))
173  info("Time for ClosestPt (Pt In Segment) : {0:.3f} us".format(1E6*closestT_in/tests))
174 
175  # test Point to HalfLine distance
176  debug('Testing Point & HalfLine Distance')
177  success = 1
178  totSuccess = 0
179  sqdistT_out = 0.
180  closestT_out = 0.
181  sqdistT_in = 0.
182  closestT_in = 0.
183  for x in range(tests):
184  # generate a random segment
186  # generate a segment parallel to it
187  # to get a line parallel to the first,
188  # translate the Start and End points
189  # by some amount in a direction perpendicular
190  # to that of the original line
191  transX = random()
192  transY = random()
193  # now ensure perpendicularity by having dot product be == 0
194  transZ = (-transX*l.Dir()[0]-transY*l.Dir()[1])/l.Dir()[2]
195  vectTranslate = geoalgo.Vector(transX,transY,transZ)
196  # create the new translated & parallel hal-fline
197  lPar = geoalgo.HalfLine(l.Start()+vectTranslate, l.Dir())
198  # first, test a point that is "before start point"
199  # distance to this point should be distance between lines
200  # in quadrature with how much further from start point we go
201  dist = random()
202  # direction vector outwards from line
203  dirOut = lPar.Dir()*(-1*dist)
204  pTest = lPar.Start()+dirOut
205  answer = dirOut.SqLength()+vectTranslate.SqLength()
206  tim = time()
207  a1 = dAlgo.SqDist(pTest,l)
208  tim = time() - tim
209  sqdistT_out += tim
210  a2 = dAlgo.SqDist(l,pTest)
211  if not ( abs(answer-a1) < _epsilon): success = 0
212  if not ( abs(answer-a2) < _epsilon): success = 0
213  tim = time()
214  point1 = dAlgo.ClosestPt(pTest,l)
215  tim = time() - tim
216  closestT_out += tim
217  point2 = dAlgo.ClosestPt(l,pTest)
218  for x in xrange(3):
219  if not ( (l.Start()[x]-point1[x]) < _epsilon ) : success = 0
220  if not ( (l.Start()[x]-point2[x]) < _epsilon ) : success = 0
221 
222  # now, test a point inside the segment.
223  # distance between point & segment should be
224  # pre-determined distance between the two segments
225  dist = random()
226  dirIn = lPar.Dir()*dist #dist ensures < distance of full segment
227  pTest = lPar.Start()+dirIn
228  answer = vectTranslate.SqLength()
229  pAns = l.Start()+dirIn
230  tim = time()
231  a1 = dAlgo.SqDist(pTest,l)
232  tim = time() - tim
233  sqdistT_in += tim
234  a2 = dAlgo.SqDist(l,pTest)
235  if not ( abs(answer-a1) < _epsilon): success = 0
236  if not ( abs(answer-a2) < _epsilon): success = 0
237  tim = time()
238  point1 = dAlgo.ClosestPt(pTest,l)
239  tim = time() - tim
240  closestT_in += tim
241  point2 = dAlgo.ClosestPt(l,pTest)
242  for x in xrange(3):
243  if not ( (pAns[x]-point1[x]) < _epsilon ) : success = 0
244  if not ( (pAns[x]-point2[x]) < _epsilon ) : success = 0
245 
246  if (success == 1) : totSuccess += 1
247  if ( float(totSuccess)/tests < 1):
248  info(NO + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
249  else:
250  info(OK + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
251  info("Time for SqDist (Pt Out of Segment) : {0:.3f} us".format(1E6*sqdistT_out/tests))
252  info("Time for ClosestPt (Pt Out of Segment): {0:.3f} us".format(1E6*closestT_out/tests))
253  info("Time for SqDist (Pt In Segment) : {0:.3f} us".format(1E6*sqdistT_in/tests))
254  info("Time for ClosestPt (Pt In Segment) : {0:.3f} us".format(1E6*closestT_in/tests))
255 
256  # test Distance between two Infinite Lines
257  debug('Testing Inf Line & Inf Line Distance')
258  totSuccess = 0
259  sqdistT = 0.
260  closestT = 0.
261  for y in range(tests):
262  success = 1
264  # take a point a fixed distance away
265  # generate a random direction in the plane
266  # perpendicular to the plane connecting
267  # the point and the line
268  # the distance between the two lines
269  # should be the fixed amount selected previously
270  # use half-way point to do calculations
271  p1 = (l1.Pt2()+l1.Pt1())/2
272  # get line direction
273  d1 = (l1.Pt2()-l1.Pt1())
274  # move in a random direction perpendicular to line
275  dirx = random()
276  diry = random()
277  dirz = (-dirx*d1[0]-diry*d1[1])/d1[2]
278  vectTranslate = geoalgo.Vector(dirx,diry,dirz)
279  # need to re-orient in some random direction on this plane
280  # this direction has to be perpendicular to both
281  # the line's direction as well as to the direction
282  # of the segment uniting the two lines
283  # use cross-product
284  vectRotate = vectTranslate.Cross(d1)
285  l2 = geoalgo.Line(p1+vectTranslate,p1+vectTranslate+vectRotate)
286  # now calculate distance. Should be vectTranslate.Length()
287  answer = vectTranslate.SqLength()
288  tim = time()
289  a1 = dAlgo.SqDist(l1,l2)
290  tim = time() - tim
291  sqdistT += tim
292  # expect the closest points on both lines to be p1 & l2.Pt1()
293  ptL1 = geoalgo.Vector()
294  ptL2 = geoalgo.Vector()
295  a2 = dAlgo.SqDist(l1,l2,ptL1,ptL2)
296  if not (abs(answer-a1) < _epsilon): success = 0
297  if not (abs(answer-a2) < _epsilon) : success = 0
298  for x in xrange(3):
299  if not ( abs(ptL1[x]-p1[x]) < _epsilon ) : success = 0
300  if not ( abs(ptL2[x]-l2.Pt1()[x]) < _epsilon ) : success = 0
301 
302  if (success == 1) : totSuccess += 1
303  if ( float(totSuccess)/tests < 1):
304  info(NO + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
305  else:
306  info(OK + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
307  info("Time for SqDist : {0:.3f} us".format(1E6*sqdistT/tests))
308 
309  # test Distance between two Half-Infinite Lines
310  debug('Testing Half-Inf Line & Half-Inf Line Distance')
311  totSuccess = 0
312  sqdistT_in = 0
313  timesIN = 0
314  sqdistT_out = 0
315  timesOUT = 0
316  for y in range(tests):
317  success = 1
319  # take a point a fixed distance away
320  # then generate a new half-line starting
321  # at the same point (translated) and with
322  # the same (or opposite) direction.
323  # But rotated outward a bit
324  p1 = l1.Start()
325  # get line direction
326  d1 = l1.Dir()
327  # move in a random direction perpendicular to line
328  dirx = random()
329  diry = random()
330  dirz = (-dirx*d1[0]-diry*d1[1])/d1[2]
331  vectTranslate = geoalgo.Vector(dirx,diry,dirz)
332  # pick some random direction (aligned with 1st or not)
333  aligned = -1
334  if (random() < 0.5) : aligned = 1
335  l2 = geoalgo.HalfLine(p1+vectTranslate,d1+vectTranslate*aligned)
336  # now calculate distance.
337  # if aligned == -1 distance should be == 0 (lines intersect)
338  # if aligned == 1 then the two start points are the closest points
339  if (aligned == -1):
340  timesIN += 1
341  answer = 0.
342  tim = time()
343  a1 = dAlgo.SqDist(l1,l2)
344  tim = time() - tim
345  L1 = geoalgo.Vector()
346  L2 = geoalgo.Vector()
347  a2 = dAlgo.SqDist(l1,l2,L1,L2)
348  sqdistT_in += tim
349  if not (abs(answer-a1) < _epsilon): success = 0
350  if not (abs(answer-a2) < _epsilon): success = 0
351  for x in xrange(3):
352  if not (L1[x]-L2[x] < _epsilon) : success = 0
353  if (aligned == 1):
354  timesOUT += 1
355  answer = vectTranslate.SqLength()
356  tim = time()
357  a1 = dAlgo.SqDist(l1,l2)
358  tim = time() - tim
359  L1 = geoalgo.Vector()
360  L2 = geoalgo.Vector()
361  a2 = dAlgo.SqDist(l1,l2,L1,L2)
362  sqdistT_out += tim
363  if not (abs(answer-a1) < _epsilon): success = 0
364  if not (abs(answer-a2) < _epsilon): success = 0
365  for x in xrange(3):
366  if not (L1[x]-l1.Start()[x] < _epsilon) : success = 0
367  if not (L2[x]-l2.Start()[x] < _epsilon) : success = 0
368 
369  if (success == 1) : totSuccess += 1
370  if ( float(totSuccess)/tests < 1):
371  info(NO + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
372  else:
373  info(OK + "Success: {0}%".format(100*float(totSuccess)/tests) + ENDC)
374  info("Time for SqDist (OUT) : {0:.3f} us".format(1E6*sqdistT_out/timesOUT))
375  info("Time for SqDist (IN) : {0:.3f} us".format(1E6*sqdistT_in/timesIN))
376 
377 
378  # test Distance between Half-Line and Line Segment
379  debug('Testing Half Line & Line Segment Distance')
380  totSuccess1 = 0
381  sqdistT1 = 0
382  totSuccess2 = 0
383  sqdistT2 = 0
384  totSuccess3 = 0
385  sqdistT3 = 0
386  totSuccess4 = 0
387  sqdistT4 = 0
388  for y in range(tests):
389  success1 = 1
390  success2 = 1
391  success3 = 1
392  success4 = 1
394  # take a point a fixed distance away
395  # test multiple scenarios:
396  # 1) segment "away" from half-line but same direction
397  # -> closest points are half-line start and segment end
398  # 2) segment "away" from half-line and rotated
399  # -> closest points are half-line start and segment rotation pivot
400  # 3) segment "close to" half-line and tilted outwards
401  # -> closest points are point on half-line and segment start
402  # 4) segment "close to" half-line and rotated
403  # -> closest points are point on half-line and segment rotation pivot
404  p1 = l1.Start()
405  # get line direction
406  d1 = l1.Dir()
407  # move in a random direction perpendicular to line
408  dirx = random()
409  diry = random()
410  dirz = (-dirx*d1[0]-diry*d1[1])/d1[2]
411  vectTranslate = geoalgo.Vector(dirx,diry,dirz)
412  # 1) generate line-segment "behind" half-line
413  # use unit-vector nature of Dir() to go back slightly more
414  dist = random()
415  seg = geoalgo.LineSegment(p1+vectTranslate-d1*dist,p1+vectTranslate-d1*dist-d1)
416  # distance should be dist
417  # closest points should be seg.Start() and l1.Start()
418  answer = vectTranslate*vectTranslate+dist*dist
419  tim = time()
420  a1 = dAlgo.SqDist(l1,seg)
421  tim = time() - tim
422  sqdistT1 += tim
423  L1 = geoalgo.Vector()
424  L2 = geoalgo.Vector()
425  a2 = dAlgo.SqDist(l1,seg,L1,L2)
426  if not (abs(answer-a1) < _epsilon): success1 = 0
427  if not (abs(answer-a2) < _epsilon): success1 = 0
428  for x in xrange(3):
429  if not (L1[x]-l1.Start()[x] < _epsilon) : success1 = 0
430  if not (L2[x]-seg.Start()[x] < _epsilon) : success1 = 0
431  if (success1 == 1) : totSuccess1 += 1
432  # 2) generate line segment away but rotated
433  # rotate in a direction perpendicular to both line direction and translation direction
434  vectRotate = vectTranslate.Cross(d1)
435  # choose pivot point
436  pivot = p1+vectTranslate-d1*dist
437  seg = geoalgo.LineSegment(pivot-vectRotate*random(),pivot+vectRotate*random())
438  # distance should be pivot distance to half-line start
439  # closest points should be pivot and line start point
440  answer = vectTranslate*vectTranslate+dist*dist
441  tim = time()
442  a1 = dAlgo.SqDist(l1,seg,L1,L2)
443  sqdistT2 += (time()-tim)
444  a2 = dAlgo.SqDist(seg,l1)
445  if not (abs(answer-a1) < _epsilon): success2 = 0
446  if not (abs(answer-a2) < _epsilon): success2 = 0
447  for x in xrange(3):
448  if not (L1[x]-l1.Start()[x] < _epsilon) : success2 = 0
449  if not (L2[x]-pivot[x] < _epsilon) : success2 = 0
450  if (success2 == 1) : totSuccess2 += 1
451  # 3) generate line segment next to but tilted outwards
452  seg = geoalgo.LineSegment(p1+vectTranslate+d1*dist,p1+vectTranslate+d1*dist+vectTranslate*random())
453  # distance should be vectTranslate
454  # closest point should be segment start and point on line "d1*dist" away from line-start
455  answer = vectTranslate*vectTranslate
456  tim = time()
457  a1 = dAlgo.SqDist(l1,seg,L1,L2)
458  sqdistT3 += (time()-tim)
459  a2 = dAlgo.SqDist(seg,l1)
460  if not (abs(answer-a1) < _epsilon): success3 = 0
461  if not (abs(answer-a2) < _epsilon): success3 = 0
462  ptLine = l1.Start()+d1*dist
463  for x in xrange(3):
464  if not (L1[x]-ptLine[x] < _epsilon) : success3 = 0
465  if not (L2[x]-seg.Start()[x] < _epsilon) : success3 = 0
466  if (success3 == 1) : totSuccess3 += 1
467  # 4) generate line segment next to line but rotated
468  pivot = p1+vectTranslate+d1*dist
469  seg = geoalgo.LineSegment(pivot-vectRotate*random(),pivot+vectRotate*random())
470  # distance should be vectTranslate
471  # closest point should be pivot on segment and d1*dist away from start for line
472  answer = vectTranslate*vectTranslate
473  tim = time()
474  a1 = dAlgo.SqDist(l1,seg,L1,L2)
475  sqdistT4 += (time()-tim)
476  a2 = dAlgo.SqDist(seg,l1)
477  if not (abs(answer-a1) < _epsilon): success4 = 0
478  if not (abs(answer-a2) < _epsilon): success4 = 0
479  ptLine = l1.Start()+d1*dist
480  for x in xrange(3):
481  if not (L1[x]-ptLine[x] < _epsilon) : success4 = 0
482  if not (L2[x]-pivot[x] < _epsilon) : success4 = 0
483  if (success4 == 1) : totSuccess4 += 1
484 
485  if ( float(totSuccess1)/tests < 1):
486  info(NO + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
487  else:
488  info(OK + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
489  info("Time for SqDist (Case 1) : {0:.3f} us".format(1E6*sqdistT1/tests))
490  if ( float(totSuccess2)/tests < 1):
491  info(NO + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
492  else:
493  info(OK + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
494  info("Time for SqDist (Case 2) : {0:.3f} us".format(1E6*sqdistT2/tests))
495  if ( float(totSuccess3)/tests < 1):
496  info(NO + "Success: {0}%".format(100*float(totSuccess3)/tests) + ENDC)
497  else:
498  info(OK + "Success: {0}%".format(100*float(totSuccess3)/tests) + ENDC)
499  info("Time for SqDist (Case 3) : {0:.3f} us".format(1E6*sqdistT3/tests))
500  if ( float(totSuccess4)/tests < 1):
501  info(NO + "Success: {0}%".format(100*float(totSuccess4)/tests) + ENDC)
502  else:
503  info(OK + "Success: {0}%".format(100*float(totSuccess4)/tests) + ENDC)
504  info("Time for SqDist (Case 4) : {0:.3f} us".format(1E6*sqdistT4/tests))
505 
506  # test Distance between Half-Line and Line Segment
507  debug('Testing Line Segment & Line Segment Distance')
508  totSuccess1 = 0.
509  sqdistT1 = 0
510  totSuccess2 = 0.
511  sqdistT2 = 0
512  totSuccess3 = 0.
513  sqdistT3 = 0
514  totSuccess4 = 0.
515  sqdistT4 = 0
516  for y in range(tests):
517  success1 = 1
518  success2 = 1
519  success3 = 1
520  success4 = 1
522  # take a point a fixed distance away
523  # test multiple scenarios:
524  # 1) segment "away" from half-line but same direction
525  # -> closest points are half-line start and segment end
526  # 2) segment "away" from half-line and rotated
527  # -> closest points are half-line start and segment rotation pivot
528  # 3) segment "close to" half-line and tilted outwards
529  # -> closest points are point on half-line and segment start
530  # 4) segment "close to" half-line and rotated
531  # -> closest points are point on half-line and segment rotation pivot
532  p1 = seg1.Start()
533  # get line direction
534  p2 = seg1.End()
535  d = p2-p1
536  length = d.Length()
537  # move in a random direction perpendicular to line
538  dirx = random()
539  diry = random()
540  dirz = (-dirx*d[0]-diry*d[1])/d[2]
541  vectTranslate = geoalgo.Vector(dirx,diry,dirz)
542  # 1) generate line-segment "behind" half-line
543  # use unit-vector nature of Dir() to go back slightly more
544  dist = random()
545  seg = geoalgo.LineSegment(p1+vectTranslate-d*dist,p1+vectTranslate-d*dist-d)
546  #seg = geoalgo.LineSegment(p1+vectTranslate,p1+vectTranslate-d)
547  # distance should be dist
548  # closest points should be seg.Start() and seg1.Start()
549  answer = vectTranslate*vectTranslate+dist*dist*d.SqLength()
550  tim = time()
551  a1 = dAlgo.SqDist(seg1,seg)
552  tim = time() - tim
553  sqdistT1 += tim
554  L1 = geoalgo.Vector()
555  L2 = geoalgo.Vector()
556  a2 = dAlgo.SqDist(seg1,seg,L1,L2)
557  if not (abs(answer-a1) < _epsilon): success1 = 0
558  if not (abs(answer-a2) < _epsilon): success1 = 0
559  for x in xrange(3):
560  if not (L1[x]-seg1.Start()[x] < _epsilon) : success1 = 0
561  if not (L2[x]-seg.Start()[x] < _epsilon) : success1 = 0
562  if (success1 == 1) : totSuccess1 += 1
563  # 2) generate line segment away but rotated
564  # rotate in a direction perpendicular to both line direction and translation direction
565  vectRotate = vectTranslate.Cross(d)
566  # choose pivot point
567  pivot = p1+vectTranslate-d*dist
568  seg = geoalgo.LineSegment(pivot-vectRotate*random(),pivot+vectRotate*random())
569  # distance should be pivot distance to half-line start
570  # closest points should be pivot and line start point
571  answer = vectTranslate*vectTranslate+dist*dist*d.SqLength()
572  tim = time()
573  a1 = dAlgo.SqDist(seg1,seg,L1,L2)
574  sqdistT2 += (time()-tim)
575  a2 = dAlgo.SqDist(seg,seg1)
576  if not (abs(answer-a1) < _epsilon): success2 = 0
577  if not (abs(answer-a2) < _epsilon): success2 = 0
578  for x in xrange(3):
579  if not (L1[x]-seg1.Start()[x] < _epsilon) : success2 = 0
580  if not (L2[x]-pivot[x] < _epsilon) : success2 = 0
581  if (success2 == 1) : totSuccess2 += 1
582  # 3) generate line segment next to but tilted outwards
583  distin = length*random() # ensures that we do not pass the segment
584  seg = geoalgo.LineSegment(p1+vectTranslate+d*distin,p1+vectTranslate+d*distin+vectTranslate*random())
585  # distance should be vectTranslate
586  # closest point should be segment start and point on line "d*distin" away from line-start
587  answer = vectTranslate*vectTranslate
588  tim = time()
589  a1 = dAlgo.SqDist(seg1,seg,L1,L2)
590  sqdistT3 += (time()-tim)
591  a2 = dAlgo.SqDist(seg,seg1)
592  if not (abs(answer-a1) < _epsilon): success3 = 0
593  if not (abs(answer-a2) < _epsilon): success3 = 0
594  ptLine = seg1.Start()+d*distin
595  for x in xrange(3):
596  if not (L1[x]-ptLine[x] < _epsilon) : success3 = 0
597  if not (L2[x]-seg.Start()[x] < _epsilon) : success3 = 0
598  if (success3 == 1) : totSuccess3 += 1
599  # 4) generate line segment next to line but rotated
600  pivot = p1+vectTranslate+d*distin
601  seg = geoalgo.LineSegment(pivot-vectRotate*random(),pivot+vectRotate*random())
602  # distance should be vectTranslate
603  # closest point should be pivot on segment and d*distin away from start for line
604  answer = vectTranslate*vectTranslate
605  tim = time()
606  a1 = dAlgo.SqDist(seg1,seg,L1,L2)
607  sqdistT4 += (time()-tim)
608  a2 = dAlgo.SqDist(seg,seg1)
609  if not (abs(answer-a1) < _epsilon): success4 = 0
610  if not (abs(answer-a2) < _epsilon): success4 = 0
611  ptLine = seg1.Start()+d*distin
612  for x in xrange(3):
613  if not (L1[x]-ptLine[x] < _epsilon) : success4 = 0
614  if not (L2[x]-pivot[x] < _epsilon) : success4 = 0
615  if (success4 == 1) : totSuccess4 += 1
616 
617  if ( float(totSuccess1)/tests < 1):
618  info(NO + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
619  else:
620  info(OK + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
621  info("Time for SqDist (Case 1) : {0:.3f} us".format(1E6*sqdistT1/tests))
622  if ( float(totSuccess2)/tests < 1):
623  info(NO + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
624  else:
625  info(OK + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
626  info("Time for SqDist (Case 2) : {0:.3f} us".format(1E6*sqdistT2/tests))
627  if ( float(totSuccess3)/tests < 1):
628  info(NO + "Success: {0}%".format(100*float(totSuccess3)/tests) + ENDC)
629  else:
630  info(OK + "Success: {0}%".format(100*float(totSuccess3)/tests) + ENDC)
631  info("Time for SqDist (Case 3) : {0:.3f} us".format(1E6*sqdistT3/tests))
632  if ( float(totSuccess4)/tests < 1):
633  info(NO + "Success: {0}%".format(100*float(totSuccess4)/float(tests)) + ENDC)
634  else:
635  info(OK + "Success: {0}%".format(100*float(totSuccess4)/float(tests)) + ENDC)
636  info("Time for SqDist (Case 4) : {0:.3f} us".format(1E6*sqdistT4/tests))
637 
638 
639  # test Distance between Point and AABox
640  debug('Testing Point and AABox Distance/Closest Point')
641  success1 = 1
642  totSuccess1 = 0.
643  sqdistT1 = 0
644  closestT1 = 0
645  success2 = 1
646  totSuccess2 = 0.
647  sqdistT2 = 0
648  closestT2 = 0
649  success3 = 1
650  totSuccess3 = 0.
651  sqdistT3 = 0
652  closestT3 = 0
653  success4 = 1
654  totSuccess4 = 0.
655  sqdistT4 = 0
656  closestT4 = 0
657  for y in xrange(tests):
658  success1 = 1
659  success2 = 1
660  success3 = 1
661  success4 = 1
662  # create a simple cubic box from 0,0,0 to 1,1,1
663  b = geoalgo.AABox(0,0,0,1,1,1)
664  # various cases to test:
665  # case 1) Point inside box
666  # case 2) Point outside box
667  # 1) POINT INSIDE BOX
669  # if point not recognized as inside -> error!
670  if not ( b.Contain(p) ) : success1 = 0
671  dTop = 1-p[2]
672  dBot = p[2]
673  dLeft = p[0]
674  dRight = 1-p[0]
675  dFront = p[1]
676  dBack = 1-p[1]
677  # find smallest of these
678  dMin = dTop
679  if ( dBot < dMin ) : dMin = dBot
680  if ( dLeft < dMin ) : dMin = dLeft
681  if ( dRight < dMin ) : dMin = dRight
682  if ( dFront < dMin ) : dMin = dFront
683  if ( dBack < dMin ) : dMin = dBack
684  answer = dMin*dMin
685  tim = time()
686  a1 = dAlgo.SqDist(p,b)
687  sqdistT1 += (time()-tim)
688  a2 = dAlgo.SqDist(b,p)
689  # closest point
690  tim = time()
691  pt1 = dAlgo.ClosestPt(b,p)
692  closestT1 += (time()-tim)
693  pt2 = dAlgo.ClosestPt(p,b)
694  if not (abs(answer-a1) < _epsilon): success1 = 0
695  if not (abs(answer-a2) < _epsilon): success1 = 0
696  for x in xrange(3):
697  if not (pt1[x]-p[x] < _epsilon) : success1 = 0
698  if not (pt2[x]-p[x] < _epsilon) : success1 = 0
699  if (success1 == 1) : totSuccess1 += 1
700  # 2) POINT OUT OF BOX
701  # pick a side that is should exit on at random
702  pick = random()
703  side = 0
704  if ( (pick > 0.33) and (pick < 0.67) ) : side = 1
705  if ( pick > 0.67 ) : side = 2
706  # pick a direction to overflow the box by (-1 = back or +1 = front)
707  direction = 1
708  if ( random() < 0.5 ) : direction = -1
709  if ( side == 0 ) :
710  p = geoalgo.Vector(random()+direction,random(),random())
711  elif ( side == 1 ) :
712  p = geoalgo.Vector(random(),random()+direction,random())
713  else :
714  p = geoalgo.Vector(random(),random(),random()+direction)
715  # if point not recognized as outside -> error!
716  if ( b.Contain(p) ) : success1 = 0
717  # go through cases and find min distance
718  if ( (side == 0) and (direction == 1) ):
719  #overflow on +x direction
720  dMin = p[0]-1
721  pMin = geoalgo.Vector(1,p[1],p[2])
722  if ( (side == 0) and (direction == -1) ):
723  #overflow on -x direction
724  dMin = -p[0]
725  pMin = geoalgo.Vector(0,p[1],p[2])
726  if ( (side == 1) and (direction == 1) ):
727  #overflow on +y direction
728  dMin = p[1]-1
729  pMin = geoalgo.Vector(p[0],1,p[2])
730  if ( (side == 1) and (direction == -1) ):
731  #overflow on -y direction
732  dMin = -p[1]
733  pMin = geoalgo.Vector(p[0],0,p[2])
734  if ( (side == 2) and (direction == 1) ):
735  #overflow on +z direction
736  dMin = p[2]-1
737  pMin = geoalgo.Vector(p[0],p[1],1)
738  if ( (side == 2) and (direction == -1) ):
739  #overflow on -z direction
740  dMin = -p[2]
741  pMin = geoalgo.Vector(p[0],p[1],0)
742  answer = dMin*dMin
743  tim = time()
744  a1 = dAlgo.SqDist(p,b)
745  sqdistT2 += (time()-tim)
746  a2 = dAlgo.SqDist(b,p)
747  # closest point
748  tim = time()
749  pt1 = dAlgo.ClosestPt(b,p)
750  closestT2 += (time()-tim)
751  pt2 = dAlgo.ClosestPt(p,b)
752  #info("Point: [{0}, {1}, {2}]".format(p[0],p[1],p[2]))
753  #info("Expected: {0}. Got: {1}".format(answer,a1))
754  #info("Expected: {0}. Got: {1}".format(answer,a2))
755  if not (abs(answer-a1) < _epsilon): success2 = 0
756  if not (abs(answer-a2) < _epsilon): success2 = 0
757  for x in xrange(3):
758  #info("\tExpected: {0}. Got: {1}".format(p[x],pt1[x]))
759  #info("\tExpected: {0}. Got: {1}".format(p[x],pt2[x]))
760  if not (pt1[x]-pMin[x] < _epsilon) : success2 = 0
761  if not (pt2[x]-pMin[x] < _epsilon) : success2 = 0
762  #info("Success: {0}".format(success2))
763  if (success2 == 1) : totSuccess2 += 1
764 
765  if ( float(totSuccess1)/tests < 1):
766  info(NO + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
767  else:
768  info(OK + "Success: {0}%".format(100*float(totSuccess1)/tests) + ENDC)
769  info("Time for SqDist (Case 1) : {0:.3f} us".format(1E6*sqdistT1/tests))
770  info("Time for ClosestPt (Case 1) : {0:.3f} us".format(1E6*closestT1/tests))
771  if ( float(totSuccess2)/tests < 1):
772  info(NO + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
773  else:
774  info(OK + "Success: {0}%".format(100*float(totSuccess2)/tests) + ENDC)
775  info("Time for SqDist (Case 2) : {0:.3f} us".format(1E6*sqdistT2/tests))
776  info("Time for ClosestPt (Case 2) : {0:.3f} us".format(1E6*closestT2/tests))
777 
778  except Exception:
779  error('geoalgo::DistanceAlgo unit test failed.')
780  print traceback.format_exception(*sys.exc_info())[2]
781  return 1
782 
783  info('geoalgo::DistanceAlgo unit test complete.')
784  return 0
float Length(const PFPStruct &pfp)
Definition: PFPUtils.cxx:3304
Algorithm to compute various geometrical relation among geometrical objects. In particular functions ...
static std::string format(PyObject *obj, unsigned int pos, unsigned int indent, unsigned int maxlen, unsigned int depth)
Definition: fclmodule.cxx:374
Representation of a simple 3D line segment Defines a finite 3D straight line by having the start and ...
Representation of a 3D rectangular box which sides are aligned w/ coordinate axis. A representation of an Axis-Aligned-Boundary-Box, a simple &amp; popular representation of 3D boundary box for collision detection. The concept was taken from the reference, Real-Time-Collision-Detection (RTCD), and in particular Ch. 4.2 (page 77): .
T abs(T value)
Representation of a 3D infinite line. Defines an infinite 3D line by having 2 points which completely...
Representation of a 3D semi-infinite line. Defines a semi-infinite 3D line by having a start point (P...

Variable Documentation

int test_distance._epsilon = 1

Definition at line 9 of file larcorealg/test/GeoAlgo/test_distance.py.

string test_distance.BLUE = '\033[94m'

Definition at line 14 of file larcorealg/test/GeoAlgo/test_distance.py.

string test_distance.ENDC = '\033[0m'

Definition at line 15 of file larcorealg/test/GeoAlgo/test_distance.py.

string test_distance.NO = '\033[91m'

Definition at line 13 of file larcorealg/test/GeoAlgo/test_distance.py.

string test_distance.OK = '\033[92m'

Definition at line 12 of file larcorealg/test/GeoAlgo/test_distance.py.