Revision: 53775
          http://brlcad.svn.sourceforge.net/brlcad/?rev=53775&view=rev
Author:   r_weiss
Date:     2012-11-19 23:18:06 +0000 (Mon, 19 Nov 2012)
Log Message:
-----------
Added two new functions to libbn in file "plane.c". Added 
"bn_distsq_pt3_lseg3_v2" which a test version of "bn_distsq_pt3_lseg3" and 
"bn_are_equal" which is a support function for this new test function. At some 
point this test function and the original will be consolidated.

Modified Paths:
--------------
    brlcad/trunk/src/libbn/plane.c

Modified: brlcad/trunk/src/libbn/plane.c
===================================================================
--- brlcad/trunk/src/libbn/plane.c      2012-11-19 22:05:36 UTC (rev 53774)
+++ brlcad/trunk/src/libbn/plane.c      2012-11-19 23:18:06 UTC (rev 53775)
@@ -2322,6 +2322,205 @@
 
 
 /**
+ * B N _ A R E _ E Q U A L
+ *
+ * This is a support function for the test function "bn_distsq_pt3_lseg3_v2".
+ *
+ */
+int
+bn_are_equal(fastf_t a, fastf_t b, fastf_t t)
+{
+    fastf_t ai, af, bi, bf;
+    int ret = 0;
+
+    af = modf(a, &ai);
+    bf = modf(b, &bi);
+
+    if ((long)ai == (long)bi && t < 1.0) {
+       if (NEAR_EQUAL(af, bf, t)) {
+           ret = 1;
+       }
+    } else {
+       if (NEAR_EQUAL(a, b, t)) {
+           ret = 1;
+       }
+    }
+    return ret;
+}
+
+
+/**
+ * B N _ D I S T S Q _ P T 3 _ L S E G 3 _ v 2
+ *
+ * Find the square of the distance from a point P to a line segment described
+ * by the two endpoints A and B.
+ *
+ *                     P
+ *                    *
+ *                   /.
+ *                  / .
+ *                 /  .
+ *                /   . (dist)
+ *               /    .
+ *              /     .
+ *             *------*--------*
+ *             A      PCA      B
+ *
+ * There are six distinct cases, with these return codes -
+ *     0       P is within tolerance of lseg AB.  *dist =  0.
+ *     1       P is within tolerance of point A.  *dist = 0.
+ *     2       P is within tolerance of point B.  *dist = 0.
+ *     3       PCA is within tolerance of A. *dist = |P-A|**2.
+ *     4       PCA is within tolerance of B. *dist = |P-B|**2.
+ *     5       P is "above/below" lseg AB.  *dist=|PCA-P|**2.
+ *
+ * This function is a test version of "bn_distsq_pt3_lseg3".
+ *
+ */
+int
+bn_distsq_pt3_lseg3_v2(fastf_t *distsq, const fastf_t *a, const fastf_t *b, 
const fastf_t *p, const struct bn_tol *tol)
+{
+    vect_t AtoB, AtoP, BtoP;
+    fastf_t AtoB_mag, AtoP_mag, AtoPCA_mag, PtoPCA_mag, BtoP_mag;
+    fastf_t dot, dt, dist;
+    int ret;
+
+    dt = tol->dist;
+    VSUB2(AtoB, b, a);
+    AtoB_mag = MAGNITUDE(AtoB);
+    VSUB2(AtoP, p, a);
+    AtoP_mag = MAGNITUDE(AtoP);
+    if (AtoB_mag < dt) {
+       /* (A=B) */
+       if (AtoP_mag < dt) {
+           /* ambiguous case: (A=B) (A=P) (B=P) */
+           /* return could be 0 thru 4 */
+           /* P is within tolerance of point A */
+           dist = 0.0;
+           ret = 1;
+       } else {
+           /* ambiguous case: (A=B) (A!=P) */
+           /* return could be 3 thru 5 */
+           /* P is "above/below" lseg AB */
+           dist = AtoP_mag;
+           ret = 5;
+       }
+    } else {
+       /* (A!=B) */
+       if (AtoP_mag < dt) {
+           /* ambiguous case: (A!=B) (A=P) */
+           /* return could be 0,1,3 */
+           dist = 0.0;
+           ret = 1; /* P is within tolerance of point A */
+       } else {
+           /* (A!=B) (A!=P) */
+           if (bn_lseg3_lseg3_parallel(a, b, a, p, tol)) {
+               /* AtoB and AtoP are collinear */
+               dot = VDOT(AtoB, AtoP);
+               if (dot > SMALL_FASTF) {
+                   /* AtoB and AtoP pointing in the same direction */
+                   if (bn_are_equal(AtoB_mag, AtoP_mag, dt) || 
bn_pt3_pt3_equal(b, p, tol)) {
+                       /* AtoB and AtoP pointing in the same direction */
+                       /* (B=P) */
+                       /* ambiguous case: (A!=B) (A!=P) (B=P) */
+                       /* return could be 0, 2, 4 */
+                       dist = 0.0;
+                       ret = 2;
+                   } else if (AtoP_mag > AtoB_mag) {
+                       /* AtoB and AtoP pointing in the same direction */
+                       /* (A!=B) (A!=P) (B!=P), lsegs AtoB and AtoP are 
collinear.
+                        * P is to the right of B, not above/below lseg AtoB.
+                        */
+                       /* both P and PCA and not within tolerance of lseg AtoB 
*/
+                       dist = AtoP_mag - AtoB_mag;
+                       ret = 4;
+                   } else {
+                       /* AtoB and AtoP pointing in the same direction */
+                       /* (A!=B) (A!=P) (B!=P), lsegs AtoB and AtoP are 
collinear */
+                       /* AtoP_mag < AtoB_mag */
+                       /* P is on lseg AtoB */
+                       dist = 0.0;
+                       ret = 0;        
+                   }
+               } else {
+                   /* AtoB and AtoP are collinear */
+                   /* AtoB and AtoP pointing in opposite directions */
+                   /* P is to the left of A, not above/below lseg AtoB. */
+                   /* both P and PCA and not within tolerance of lseg AtoB */
+                   dist = AtoP_mag;
+                   ret = 3;
+               }
+           } else {
+               /* (A!=B) (A!=P) */
+               /* AtoB and AtoP are not collinear */
+               dot = VDOT(AtoP, AtoB);
+               if ZERO(dot) {
+                   /* (A=PCA), lsegs AtoB and AtoP are perpendicular */
+                   dist = AtoP_mag;
+                   ret = 3;
+               } else if (dot > SMALL_FASTF) {
+                   AtoPCA_mag = dot / AtoB_mag;
+                   if (NEAR_ZERO(AtoPCA_mag, dt)) {
+                       /* (A=PCA), lsegs AtoB and AtoP are perpendicular */
+                       dist = AtoP_mag;
+                       ret = 3;
+                   } else if (bn_are_equal(AtoPCA_mag, AtoB_mag, dt) || 
EQUAL(AtoPCA_mag, AtoB_mag)) {
+                       /* (B=PCA) */
+                       VSUB2(BtoP, p, b);
+                       BtoP_mag = MAGNITUDE(BtoP);
+                       if (BtoP_mag < dt) {
+                           /* ambiguous case: (B=PCA) (B=P) */
+                           /* return could be 2 or 4 */
+                           dist = 0.0;
+                           ret = 2;
+                       } else {
+                           /* (B=PCA) (B!=P) */
+                           dist = BtoP_mag;
+                           ret = 4;
+                       }
+                   } else if (AtoPCA_mag < AtoB_mag) {
+                       /* PCA is on lseg AtoB */
+                       PtoPCA_mag = sqrt((AtoP_mag * AtoP_mag) + (AtoPCA_mag * 
AtoPCA_mag));
+                       if (PtoPCA_mag < dt) {
+                           /* P is within tolerance of lseg AtoB */
+                           dist = 0.0;
+                           ret = 0;
+                       } else {
+                           dist = PtoPCA_mag;
+                           ret = 5;
+                       }
+                   } else {
+                       /* AtoPCA_mag > AtoB_mag */
+                       /* P is to the right of B, above/below lseg AtoB. */
+                       /* both P and PCA and not within tolerance of lseg AtoB 
*/
+                       VSUB2(BtoP, p, b);
+                       BtoP_mag = MAGNITUDE(BtoP);
+                       dist = BtoP_mag;
+                       ret = 4;
+                   }
+               } else {
+                   /* dot is neg */
+                   AtoPCA_mag = dot / AtoB_mag;
+                   if (NEAR_ZERO(AtoPCA_mag, dt)) {
+                       /* (PCA=A), lsegs AtoB and AtoP are perpendicular */
+                       dist = AtoP_mag;
+                       ret = 3;
+                   } else {
+                       /* (PCA!=A), PCA is not on lseg AtoB */
+                       /* both P and PCA and not within tolerance of lseg AtoB 
*/
+                       dist = AtoP_mag;
+                       ret = 3;
+                   }
+               }
+           }
+       }
+    }
+    *distsq = dist * dist;
+    return ret;
+}
+
+
+/**
  * B N _ D I S T _ P T 3 _ L S E G 3
  *@brief
  * Find the distance from a point P to a line segment described by the

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to