# TheSwamp

## Code Red => ARX Programming => Topic started by: LE on January 11, 2007, 11:09:09 PM

Title: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: LE on January 11, 2007, 11:09:09 PM
For those still interesting in ARX and C++, here are some functions I'm porting from AutoLisp to ARX

The lisp functions belong to a routine about to draw automatically walls from a selection of lines (autowalls lisp was posted in show your stuff forum)

lisp function to find the max or min point on a list of points
Code: [Select]
`(defun lbx-getmimmax-pt (lst1 pt1 cve / lth cont d d1 pmx)  (setq lth  (length lst1) cont 0 pmx  (car lst1) d    (distance pmx pt1) )  (while (< cont lth)    (setq d1 (distance (nth cont lst1) pt1))    (if (= cve "min")      (if (< d1 d) (setq d   d1       pmx (nth cont lst1)       ) )      )    (if (= cve "max")      (if (> d1 d) (setq d   d1       pmx (nth cont lst1)       ) )      )    (setq cont (1+ cont))    )  (if (> lth 1)    pmx    (car lst1)    )  )`

version in arx
Code: [Select]
`AcGePoint3d getMinMaxPt (AcGePoint3dArray points, AcGePoint3d pt1, int option){ AcGePoint3d result; long lth = points.length(); int cont = 0; AcGePoint3d pmx = points.at(0); double d = acutDistance(asDblArray(pmx), asDblArray(pt1)); while (cont < lth) { double d1 = acutDistance(asDblArray(points.at(cont)), asDblArray(pt1)); switch (option) { case 0: if (d1 < d) { d = d1; pmx = points.at(cont); } break; case 1: if (d1 > d) { d = d1; pmx = points.at(cont); } break; }//end of switch cont = 1 + cont; }//end of while cont < lth if (lth > 1) result.set(pmx.x, pmx.y, pmx.z); else result.set(points.at(0).x, points.at(0).y, points.at(0).z); return result;}`
arx function to emulate the auto lisp subst function
Code: [Select]
`AcGePoint3dArray subst (AcGePoint3d newitem, AcGePoint3d olditem, AcGePoint3dArray lst){ int index; if (lst.find(olditem, index)) { lst.removeAt(index); lst.append(newitem); } return lst;}`
lisp function to sort a list of points base on a point
Code: [Select]
`(defun lbx-sort->pts-bspt       (lst pt / lth cont cont1 px dmx lst1 lst2 d1 d p pt1)  (setq lth  (length lst) cont 0 px   (lbx-getmimmax-pt lst pt "max") dmx  (distance px pt) lst2 lst )  (while (< cont lth)    (setq cont1 0   d dmx   p px   )    (while (< cont1 lth)      (setq d1 (distance (setq pt1 (nth cont1 lst2)) pt))      (if (< d1 d) (setq d d1       p pt1       ) )      (setq cont1 (1+ cont1))      )    (setq lst1 (append lst1 (list p))   lst2 (subst px p lst2)   cont (1+ cont)   )    )  lst1  )`
version in arx
Code: [Select]
`AcGePoint3dArray sortPtsBspt (AcGePoint3dArray lst, AcGePoint3d pt){ long lth = lst.length(); int cont = 0; AcGePoint3d px = getMinMaxPt(lst, pt, 1); double dmx = acutDistance(asDblArray(px), asDblArray(pt)); AcGePoint3dArray list1, list2; // pass all the lst items to list2 for (int i = 0; i < lst.length(); i++) list2.append(lst.at(i)); while (cont < lth) { int cont1 = 0; double d = dmx; AcGePoint3d p; p.set(px.x, px.y, px.z); while (cont1 < lth) { AcGePoint3d pt1 = list2.at(cont1); double d1 = acutDistance(asDblArray(pt1), asDblArray(pt)); if (d1 < d) { d = d1; p.set(pt1.x, pt1.y, pt1.z); } cont1 = 1 + cont1; }//end of while cont1<lth list1.append(p); list2 = subst(px, p, list2); cont = 1 + cont; }//end of while cont<lth return list1;}`
lisp function to define all the points that pass over a node of two or more lines
Code: [Select]
`(defun lbx-node-line  (pt    /    sel lth   cont  ent1  dat1 obj1        tst1  tst2  v01 v11   v02   v12   ang1 pa1        pb1   pa2   pb2 pv)   ;pa pb  (setq sel  sel3 lth  (sslength sel) cont 0 tst  nil pv1  nil pv2  nil pv3  nil pv4  nil)    (while (< cont lth)    (setq ent1 (ssname sel cont)   dat1 (entget ent1)   obj1 (lbx-dxf 0 dat1)   tst1 nil   tst2 nil)        (if (and (= obj "LINE") (= obj1 "LINE"))      (progn (setq v01  (polar v0 (+ ang ort) mw)       v11  (polar v1 (+ ang ort) mw)       v02  (polar v0 (- ang ort) mw)       v12  (polar v1 (- ang ort) mw)       pa   (trans (lbx-dxf 10 dat1) 0 1)       pb   (trans (lbx-dxf 11 dat1) 0 1)       ang1 (angle pa pb)       pa1  (polar pa (+ ang1 ort) mw)       pb1  (polar pb (+ ang1 ort) mw)       pa2  (polar pa (- ang1 ort) mw)       pb2  (polar pb (- ang1 ort) mw)) (if (lbx-equal-point (inters pa pb p0 p1) pt)   (progn     (if (or (lbx-equal-point pt p0)     (lbx-equal-point pt p1))       (progn (if   (lbx-pt-on-vector     (inters pa1 pb1 p0 p1 nil)     p0     p1)    (setq p   pa2 pa2 pa1 pa1 p p   pb2 pb2 pb1 pb1 p)) (if (setq pv (inters pa2 pb2 v01 v11))   (setq pv1 (append pv1 (list pv)))) (if (setq pv (inters pa2 pb2 v02 v12))   (setq pv2 (append pv2 (list pv)))) (if (setq pv (inters pa1 pb1 v01 v11 nil))   (setq pv3  (append pv3 (list pv)) tst1 T)) (if (setq pv (inters pa1 pb1 v02 v12 nil))   (setq pv4  (append pv4 (list pv)) tst2 T)) )       (progn (if (setq pv (inters pa1 pb1 v01 v11))   (setq pv1 (append pv1 (list pv)))) (if (setq pv (inters pa2 pb2 v01 v11))   (setq pv1 (append pv1 (list pv)))) (if (setq pv (inters pa1 pb1 v02 v12))   (setq pv2 (append pv2 (list pv)))) (if (setq pv (inters pa2 pb2 v02 v12))   (setq pv2 (append pv2 (list pv)))) )))) ))    (setq cont (1+ cont))    (if (and tst1 tst2)      (setq tst T))        ))`
version in arx
Code: [Select]
`static void nodeLine (AcGePoint3d pt,    ads_name sel,    double ang,    double ort,    double mw,    AcGePoint3d v0,    AcGePoint3d v1,    AcGePoint3d p0,    AcGePoint3d p1,    AcGePoint3dArray pointsV1,    AcGePoint3dArray pointsV2,    AcGePoint3dArray pointsV3,    AcGePoint3dArray pointsV4){ long lth = 0; if (acedSSLength(sel, &lth) != RTNORM || lth == 0) { acedSSFree(sel); //return; } int cont = 0, tst = 0; //AcGePoint3dArray pointsV1, pointsV2, pointsV3, pointsV4; while (cont < lth) { int tst1 = 0, tst2 = 0; AcDbObjectId objId; ads_name ename; acedSSName(sel, cont, ename); if (acdbGetObjectId(objId, ename) != Acad::eOk) return; AcDbObjectPointer<AcDbLine> ent1(objId, AcDb::kForRead); if (ent1.openStatus() == Acad::eOk) { ads_point v01, v11, v02, v12, pa, pb; acutPolar(asDblArray(v0), (ang + ort), mw, v01); acutPolar(asDblArray(v1), (ang + ort), mw, v11); acutPolar(asDblArray(v0), (ang - ort), mw, v02); acutPolar(asDblArray(v1), (ang - ort), mw, v12); AcGePoint3d startPoint, endPoint; ent1->getStartPoint(startPoint); ent1->getEndPoint(endPoint); ads_point_set(asDblArray(startPoint), pa); ads_point_set(asDblArray(endPoint), pb); acdbWcs2Ucs(pa, pa, false); acdbWcs2Ucs(pb, pb, false); double ang1 = acutAngle(pa, pb); ads_point pa1, pb1, pa2, pb2; acutPolar(pa, (ang1 + ort), mw, pa1); acutPolar(pb, (ang1 + ort), mw, pb1); acutPolar(pa, (ang1 - ort), mw, pa2); acutPolar(pb, (ang1 - ort), mw, pb2); ads_point pin; if (acdbInters(pa, pb, asDblArray(p0), asDblArray(p1), 1, pin) == RTNORM) { // convert intersection point to AcGePoint3d AcGePoint3d ptInt(pin[X], pin[Y], pin[Z]); double fuzz = 0.00001; // check for equality of points ptInt == v0 if (ptInt.distanceTo(pt) <= fuzz) { // verify if any of the pair of points are equal if (pt.distanceTo(p0) <= fuzz || pt.distanceTo(p1) <= fuzz) { //ads_point pin; if (acdbInters(pa1, pb1, asDblArray(p0), asDblArray(p1), 0, pin) == RTNORM) { AcGePoint3d ptInt(pin[X], pin[Y], pin[Z]); // check if the point is on the vector p0-p1 if (eqDoubles( p0.distanceTo(ptInt) + p1.distanceTo(ptInt), p0.distanceTo(p1), fuzz)) { ads_point p; ads_point_set(pa2, p); ads_point_set(pa1, pa2); ads_point_set(p, pa1); ads_point_set(pb2, p); ads_point_set(pb1, pb2); ads_point_set(p, pb1); } }//end of acdbInters(pa1, pb1, p0, p1, 0, pin) ads_point pv; if (acdbInters(pa2, pb2, v01, v11, 1, pv) == RTNORM) pointsV1.append(asPnt3d(pv)); if (acdbInters(pa2, pb2, v02, v12, 1, pv) == RTNORM) pointsV2.append(asPnt3d(pv)); if (acdbInters(pa1, pb1, v01, v11, 0, pv) == RTNORM) { pointsV3.append(asPnt3d(pv)); tst1 = 1; } if (acdbInters(pa1, pb1, v02, v12, 0, pv) == RTNORM) { pointsV4.append(asPnt3d(pv)); tst2 = 1; } }//end of v0.distanceTo else { ads_point pv; if (acdbInters(pa1, pb1, v01, v11, 1, pv) == RTNORM) pointsV1.append(asPnt3d(pv)); if (acdbInters(pa2, pb2, v01, v11, 1, pv) == RTNORM) pointsV1.append(asPnt3d(pv)); if (acdbInters(pa1, pb1, v02, v12, 1, pv) == RTNORM) pointsV2.append(asPnt3d(pv)); if (acdbInters(pa2, pb2, v02, v12, 1, pv) == RTNORM) pointsV2.append(asPnt3d(pv)); } }//end of ptInt.distanceTo }//end of acdbInters(pa, pb, p0, p1, 1, pin) }//end of ent1.openStatus cont = 1 + cont; if (tst1 == 1 && tst2 == 1) tst = 1; }//end of while cont<lth}`
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: It's Alive! on January 11, 2007, 11:57:20 PM
Awesome Luis, thats makes for a nice 3000th post.   :-D
thanks for sharing. I am very interested in this too
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: It's Alive! on January 12, 2007, 12:06:57 AM
Luis,

Are you going to put all your methods in classes that can instantiated ?
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: LE on January 12, 2007, 12:09:34 AM
Awesome Luis, thats makes for a nice 3000th post.   :-D
thanks for sharing. I am very interested in this too

:)

Cool; I have all the night, to see if I can get this running... and some few more beers, and musiccccc.... :)

I'll post more as soon I have it ready.

It could be a good challenge exercise, for all the swampers... I think.

Have fun.
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: LE on January 12, 2007, 12:13:05 AM
Luis,

Are you going to put all your methods in classes that can instantiated ?

Don't think, I would do that, just some of the functions... as I mentioned before, this could be a nice challenge exercise, don't you think?.... if you have  chance, try the AutoWalls lisp (vlx) version I posted here some time ago...

Here is:
http://www.theswamp.org/index.php?topic=7180.msg88472#msg88472
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: LE on January 12, 2007, 12:38:20 AM
lisp function
Code: [Select]
`(defun lbx-pt-on-vector (pt v0 v1 /)  (if (and pt v0 v1)    (if (equal (+ (distance v0 pt) (distance v1 pt))        (distance v0 v1)        0.00001        )      T      )    )  )`
Code: [Select]
`static bool eqDoubles(double i1, double i2, double ftol){ double nom, denom, error; nom = fabs(i1 - i2); denom = fabs(i1) + fabs(i2); if (denom != 0) { error = 2* nom / denom; return (error <= ftol); } return TRUE;}`
arx way...
Code: [Select]
`eqDoubles( p0.distanceTo(ptInt) + p1.distanceTo(ptInt), p0.distanceTo(p1), fuzz)) `
lisp function
Code: [Select]
`(defun lbx-equal-point (p1 p2 /)  (if (and p1 p2)    (if (equal (distance p1 p2) 0 0.00001)      T      )    )  )`
arx way...
Code: [Select]
`double fuzz = 0.00001;if (ptInt.distanceTo(pt) <= fuzz){}`
Title: Re: Porting AutoLisp Code To ObjectARX & C++ - Sample
Post by: MickD on January 12, 2007, 03:43:54 PM
Nice work Luis, looks like you're having fun!
I'm glad to see you haven't chosen to wrap them into classes, while this would be the 'proper/prefered' C++ way it makes it very difficult to export your functions to other languages (think PInvoke). C style functions allow you to do this easily. Although you may need to use pointers as parameters and return items and cast them at the other end??