Author Topic: {Challenge} connect each two points whose distance is shorter than given value  (Read 102015 times)

0 Members and 4 Guests are viewing this topic.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8766
  • AKA Daniel
This version I posted here
http://www.theswamp.org/index.php?topic=32874.msg383742#msg383742
seems to work with 3d

pkohut

  • Guest
I was able to cut another 25% of the time using a bit of caching. only has an effect on larger sets

@ 1,000,000

Using multiple cores to make Daniel's flame thrower code even hotter (AC2008 binary attached)

The multi core times are with OMP. It's interesting that the referenced temp variables caused a significant slow down on OMP, and changing them to objects had a small performance hit compared to not using temp variables. Maybe there is an OMP setting that could help, but OMP can get complicated and this is beyond what I know. Not using temp variables with OMP always ran faster than the version with temp variables.

Quote
Single core
No temps 19.304 s
Temps - 15.685 s

Multi core use
No temps - 14.704 s (about 65% of 4 core processor utilization)
With temps as object - 15.790 s (about 65% 4 C PU)
With temps as reference type - 20.770 s (about 50% 4 C PU)
With temps as pointer - 20.074 s (about 50% 4 C PU)

A good OMP reference
http://www.codeguru.com/cpp/cpp/cpp_mfc/general/print.php/c15419

OMP enabled code listing, this is the fastest version. Note the use of #pragma omp critical, this ensures that adding the entity to the DB is done by a single thread (otherwise Autocad vaporizes immediately), and it's critical that the newed AcDbLine is inside the block too, otherwise Autocad will throw a thread exception when the function exits.
Code: [Select]
#pragma omp parallel
            {           
#pragma omp for
                for (long i = 0; i < len; i++)
                {
                    for (long j = i + 1; j < len; j++)
                    {
                        if ((points[j].x - points[i].x) > distance)
                        {
                            break;
                        }
                        else if ( distsqrd(points[i],points[j]) < distancesqrd)
                        {
#pragma omp critical
                            {
                                AcDbLine *pLine = new AcDbLine(points[i],points[j]);
                                if(pRec->appendAcDbEntity(pLine) != Acad::eOk)
                                    delete pLine;
                                pLine->close();
                            }
                        }
                    }
                }
            }

Full ArxDist_doit replacement for playing with parallel processing.  #if 1 = no temp variables, #if 0 = temp variables
Code: [Select]
#include <omp.h>
...
    static void ArxDist_doit(void)
    {
        double distance = 0.0;

        if(acedGetDist(0,_T("\nGetDist: "),&distance) != RTNORM)
            return;

        const double distancesqrd = pow(distance,2) + 1.192092896e-07F;

        __int64 freq, start, end, diff;
        QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
        QueryPerformanceCounter((LARGE_INTEGER*)&start);

        std::vector<AcGePoint3d> points;
        AcDbBlockTableRecord *pRec;
        AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();

        if(acdbOpenAcDbObject((AcDbObject *&) pRec,pDb->currentSpaceId(), AcDb::kForWrite) == Acad::eOk)
        {
            AcDbBlockTableRecordIterator *pIter = NULL;
            if(pRec->newIterator(pIter) == Acad::eOk)
            {
                for(pIter->start(); !pIter->done(); pIter->step())
                {
                    AcDbEntity *pEnt = NULL;
                    if(pIter->getEntity(pEnt, AcDb::kForRead) == Acad::eOk)
                    {
                        AcDbPoint *pPoint = AcDbPoint::cast(pEnt);
                        if(pPoint)
                            points.push_back(pPoint->position());
                        pEnt->close();
                    }
                }
                delete pIter;
            }
            std::sort(points.begin(),points.end(),psort);
            size_t len = points.size();

#if 1
            // No temp variables
#pragma omp parallel
            {           
#pragma omp for
                for (long i = 0; i < len; i++)
                {
                    for (long j = i + 1; j < len; j++)
                    {
                        if ((points[j].x - points[i].x) > distance)
                        {
                            break;
                        }
                        else if ( distsqrd(points[i],points[j]) < distancesqrd)
                        {
#pragma omp critical
                            {
                                AcDbLine *pLine = new AcDbLine(points[i],points[j]);
                                if(pRec->appendAcDbEntity(pLine) != Acad::eOk)
                                    delete pLine;
                                pLine->close();
                            }
                        }
                    }
                }
            }
#else
            // With Temp variables as object
#pragma omp parallel
            {           
#pragma omp for
                for (long i = 0; i < len; i++)
                {
                    const AcGePoint3d a = points[i];
                    for (long j = i + 1; j < len; j++)
                    {
                        const AcGePoint3d b = points[j];
                        if ((b.x - a.x) > distance)
                        {
                            break;
                        }
                        else if ( distsqrd(a,b) < distancesqrd)
                        {
#pragma omp critical
                            {
                                AcDbLine *pLine = new AcDbLine(a,b);
                                if(pRec->appendAcDbEntity(pLine) != Acad::eOk)
                                    delete pLine;
                                pLine->close();
                            }
                        }
                    }
                }
            }

#endif
            pRec->close();
        }
        QueryPerformanceCounter((LARGE_INTEGER*)&end);
        acutPrintf(_T("\n%g Seconds\n"), (double)(end - start) / (double) freq);
    }

} ;

ElpanovEvgeniy

  • Water Moccasin
  • Posts: 1569
  • Moscow (Russia)
new version:

Code: [Select]
(defun el-1 (l / A)
 (while (setq a (car l)
              l (cdr l)
        ) ;_  setq
  (foreach b l
   (if (< 0. (distance a b) d)
    (entmakex (list '(0 . "LINE") (cons 10 a) (cons 11 b)))
   ) ;_  if
  ) ;_  while
 ) ;_  while
) ;_  defun

(defun el-2 (l la)
 (foreach a l
  (foreach b la
   (if (< 0. (distance a b) d)
    (entmakex (list '(0 . "LINE") (cons 10 a) (cons 11 b)))
   ) ;_  if
  ) ;_  foreach
 ) ;_  foreach
) ;_  defun
(defun c:el (/ A AA B C D E L S TI X Y YY)
 ;;(repeat 3(c:el))
 (setq ti (car (_VL-TIMES))
       a  -1
       d  70.
       s  (ssget "_x" '((0 . "point")))
       y  (mapcar (function (lambda (a) (atoi (rtos (/ a d) 2 0)))) (getvar "EXTMIN"))
       x  (if (minusp (car y))
           (- (car y))
           0
          ) ;_  if
       y  (if (minusp (cadr y))
           (- (cadr y))
           0
          ) ;_  if
       yy y
 ) ;_  setq
 (while (setq e (ssname s (setq a (1+ a))))
  (setq e (cdr (assoc 10 (entget e)))
        e (list (car e) (cadr e))
        l (cons (cons (fix (+ x (/ (car e) d))) (cons (fix (+ y (/ (cadr e) d))) e)) l)
  ) ;_  setq
 ) ;_  while
 (setq l (vl-sort l (function (lambda (a b) (<= (car a) (car b)))))
       a (list (cdar l))
       l (cdr l)
 ) ;_  setq
 (while (and l (= x (caar l)))
  (setq a (cons (cdar l) a)
        l (cdr l)
  ) ;_  setq
 ) ;_  while
 (setq a (vl-sort a (function (lambda (a b) (<= (car a) (car b)))))
       x (1+ x)
 ) ;_  setq
 (while a
  (repeat (- (caar a) y)
   (setq c (cons nil c)
         y (1+ y)
   ) ;_  setq
  ) ;_  repeat
  (while (and a (= y (caar a)))
   (while (and a (= y (caar a)))
    (setq b (cons (cdar a) b)
          a (cdr a)
    ) ;_  setq
   ) ;_  while
   (el-1 b)
   (el-2 b (car c))
   (setq c (cons b c)
         b nil
         y (1+ y)
   ) ;_  setq
  ) ;_  while
 ) ;_  while
 (setq c (reverse c))
 (while l
  (setq aa c
        a  (list (cdar l))
        y  yy
        l  (cdr l)
        b  nil
        c  nil
  ) ;_  setq
  (while (and l (= x (caar l)))
   (setq a (cons (cdar l) a)
         l (cdr l)
   ) ;_  setq
  ) ;_  while
  (setq a (vl-sort a (function (lambda (a b) (<= (car a) (car b)))))
        x (1+ x)
  ) ;_  setq
  (while a
   (repeat (- (caar a) y)
    (setq c (cons nil c)
          y (1+ y)
    ) ;_  setq
   ) ;_  repeat
   (while (and a (= y (caar a)))
    (while (and a (= y (caar a)))
     (setq b (cons (cdar a) b)
           a (cdr a)
     ) ;_  setq
    ) ;_  while
    (el-1 b)
    (el-2 b (car c))
    (setq c (cons b c)
          b nil
          y (1+ y)
    ) ;_  setq
   ) ;_  while
  ) ;_  while
  (setq c (reverse c))
  (mapcar (function el-2) c (mapcar (function append) aa (cdr aa)))
  (mapcar (function el-2) c aa)
 ) ;_  while
 (princ (strcat "\n " (rtos (/ (- (car (_VL-TIMES)) ti) 1000.) 2 4)))
;;; (vl-cmdf "_erase" (ssget "_x" '((0 . "line"))) "")
 (princ)
) ;_  defun

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Dear Evgeniy, thank you very much.

Now the little bug in last version is fixed.

And the speed is more quick.

About 42s (vlx)  ---> last time 48s (vlx) for 500,000 pts.~

http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Hi,here is  my routine.
I used recursion.
Code: [Select]
;;; the main routine
;;; 主程序
(defun C:test (/ TOL sl to ss Pts T0 pp)
  ;;set or input Tolerance
  ;; 输入容差
  (if (not (setq TOL (getdist "\nPlease input the tolerance:")))
    (setq TOL 70)
  )
  ;;也可以用其他方式取得点集
  ;;Get the points
  (setq sl '((0 . "POINT")))
  (setq ss (ssget sl))
  (setq Pts (getpt ss))
  ;;按照X值排序
  ;;sort by X value
  (setq t0 (getvar "TDUSRTIMER"))
  (setq Pts (sortx Pts))
  (princ "\nThe time for sorting these points:")
  (princ (* (- (getvar "TDUSRTIMER") t0) 86400))
  (princ "s.")
  ;;函数用时估算,以了解函数性能
  ;;how long it will take
  (setq t0 (getvar "TDUSRTIMER"))
  (setq pp (f2 Pts TOL))
  (princ "\nThe time for finding the pairs of points:")
  (princ (* (- (getvar "TDUSRTIMER") t0) 86400))
  (princ "s.")
  (if pp
    ;;画最短距离的点对集的连线,可能有多条
    ;;draw the line between these pairs.
    (foreach n pp
      (entmake
(list
  '(0 . "LINE")
  (cons 10 (car n))
  (cons 11 (cadr n))
  (cons 62 1)
)
      )
    )
  )
  (princ)
)
;;; 取点函数,其中i为点的编号
;;; get points.
(defun getpt (ss / i l a b c)
  (setq i 0)
  (if ss
    (repeat (sslength ss)
      (setq a (ssname ss i))
      (setq b (entget a))
      (setq c (cdr (assoc 10 b)))
      (setq l (cons c l))
      (setq i (1+ i))
    )
  )
  (reverse l)
)
;;; 从0到k的点集
;;; the elments of points from 0 to k
(defun Array (Pts k / L1 L2)
  (setq L1 Pts)
  (repeat k
    (setq L2 (cons (car L1) L2))
    (setq L1 (cdr L1))
  )
  (list (reverse L2) L1)
)
;;; 对X排序
;;; sort points by X value.
(defun sortX (pts)
  (vl-sort pts (function (lambda (e1 e2) (< (car e1) (car e2))))
  )
)
;;; 在带形区域查找
;;; search these points in the Tolerance
(defun searchX (Pts x1 x2 / pp)
  (foreach n Pts
    (if (and (>= (car n) x1)
     (<= (car n) x2)
)
      (setq pp (cons n pp))
    )
  )
  (reverse pp)
)

;;; 用递归解决
;;; use recursion to solve this problem (divide-and-conquer)

(defun f2 (Pts TOL / l m n a b pt1 pt2 ppp Pts0 Pts1 Pts2 Pts3 Pts4
   midptx mind1 mind2 qqq)
  (setq l (length Pts))
  (cond
    ((= l 1) nil)
    ((= l 2)
     ;; 两点还用说
     ;; judge directly if two points
     (setq pt1 (car Pts))
     (setq pt2 (cadr Pts))
     (if (and (equal (car pt1) (car pt2) TOL)
      (equal (cadr pt1) (cadr pt2) TOL)
      (< (distance pt1 pt2) TOL)
)
       (list Pts)
     )
    )   
    ((> l 2)
     (setq n (/ l 2)
   m (- l n)
     )
     ;;分治
     ;;divide
     (setq Pts0 (Array Pts n))
     (setq Pts1 (car Pts0))
     (setq Pts2 (cadr Pts0))
     ;;递归左边
     ;;recurse left
     (setq mind1 (f2 Pts1 TOL))
     ;;递归右边
     ;;recurse right
     (setq mind2 (f2 Pts2 TOL))
     ;;合并左右集合
     ;;merge them
     (setq ppp (append mind1 mind2))
     ;;对带形区域的合并
     ;;consider the points in the Tolerance
     (setq midptx (caar Pts2))
     (setq a (- midptx TOL)
   b (+ midptx TOL)
     )
     (if (setq Pts3 (searchX Pts1 a midptx))
       (if (setq Pts4 (searchx Pts2 midptx b))
(foreach n Pts3
   (foreach e Pts4
     (if (equal (cadr n) (cadr e) TOL)
       (if (<= (distance n e) TOL)
(setq ppp (cons (list n e) ppp))
       )
     )
   )
)
       )
     )
     ppp
    )
  )
)
« Last Edit: April 18, 2010, 10:53:38 AM by highflybird »
I am a bilingualist,Chinese and Chinglish.

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
by the way, if it is compiled, it runs 10 times faster.

and compare mine to ElpanovEvgeniy's ,in this sample, if the tolerance is smaller or very small,my algorithm has more advantages.
« Last Edit: April 18, 2010, 05:25:35 AM by highflybird »
I am a bilingualist,Chinese and Chinglish.

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
I improved my program,so now it's faster ,and I made an arx routine. it runs 10 times faster than VLX.
I has compiled the Arx code .see the attachments, maybe it's faster than pkohut's.
I learned a lot from pkohut's. KD-tree,is advanced and hard to understand.
Any ideas, thanks.
I am a bilingualist,Chinese and Chinglish.

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Highflybird, my dear friend.

Thank you for your good program, it is rather quick.

Your arx code is about 0.5s for 100,000 pts in My PC, and about 3.393s for 500,000 pts in My PC.

I will try 1,000,000 pts later.

I cant load pkohut's arx in my AUTOCAD 2004 and 2007. So I cant test.

and your Lisp code is also very quick,  yours and Evgeniy's lisp is the two most quick lisp code.
« Last Edit: May 08, 2010, 10:44:40 AM by yuanqiu »
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8766
  • AKA Daniel
I improved my program,so now it's faster ,and I made an arx routine. it runs 10 times faster than VLX.
I has compiled the Arx code .see the attachments, maybe it's faster than pkohut's.
I learned a lot from pkohut's. KD-tree,is advanced and hard to understand.
Any ideas, thanks.

Excellent work! It's very fast  8-)

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
 I compiled a faster  arx version.
if somebody has visual studio 2005,or 2008, he can compile my attachment to a version for autocad2007-2010

(I corrected a bug in my code. -(GMT +8) 2010.05.09. 05:00 ,Please re-download.)
« Last Edit: May 08, 2010, 04:59:00 PM by highflybird »
I am a bilingualist,Chinese and Chinglish.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8766
  • AKA Daniel
Your CreatLine function is really heavy, you ought to move all the code needed to get the AcDbBlockTableRecord out to the top level function and pass a pointer.

Code: [Select]
Acad::ErrorStatus CreatLine(const AcGePoint3d & ptStart,const AcGePoint3d & ptEnd
                             AcDbBlockTableRecord *pBlockTableRecord)
{
    AcDbLine *pLine = new AcDbLine(ptStart, ptEnd);
    es=pBlockTableRecord->appendAcDbEntity(pLine);
    pLine->close();
    // pBlockTableRecord->close(); close this later
    return es;
}

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Your CreatLine function is really heavy, you ought to move all the code needed to get the AcDbBlockTableRecord out to the top level function and pass a pointer.
...
Daniel,you  are right.Actually ,I realized this question when I begun to optimize my code,but in that time , I was busy, so I didn't post my modified code.
Now ,I finished it. At the begining , I wanted to complish a C++,not just for ARX,so I used the STL, and AcGePoint3d replaced by point2d,and used the deque to store the result(so it will take a longer time). I designed my quick sort function.(because it's faster). And then, I found a bug in my program. I corrected it.
Also I found a bug in Pkohut's,(he doesn't consider the duplicate points.)
Thanks your help,Daniel,I am a C++ beginner,but I found a lot of fun. Now I crazy about it.

Now I attached the new code.
p.s  I finished this program I felt very happy,because it's my algorithm,it's made by myself
« Last Edit: May 12, 2010, 10:31:13 AM by highflybird »
I am a bilingualist,Chinese and Chinglish.

highflyingbird

  • Bull Frog
  • Posts: 415
  • Later equals never.
Code: [Select]
;;; 用递归解决
;;; use recursion to solve this problem (divide-and-conquer)

(defun f2 (Pts TOL / l m n pt1 pt2 Pts1 Pts2 Pts3 Pts4 Mx x1 x2)
  (setq l (length Pts))
  (cond
    ((= l 1) nil)
    ((= l 2)
     ;; 两点还用说
     ;; judge directly if 2 points
     (setq pt1 (car Pts))
     (setq pt2 (cadr Pts))
     (if (and (equal (car pt1) (car pt2) TOL)
      (equal (cadr pt1) (cadr pt2) TOL)
      (<= (distance pt1 pt2) TOL)
)
       (setq pairs (cons pt1 pairs) ;add the start point into pairs;
     pairs (cons pt2 pairs) ;add the end point into pairs;
       )
     )
    )
    ((> l 2)
     (setq n (/ l 2)
   m (- l n)
     )
     (setq Pts1 (Array Pts n)) ;Divide
     (setq Pts2 (cadr Pts1)) ;R points
     (setq Pts1 (car Pts1)) ;L points
     (f2 (reverse Pts1) TOL) ;Recurse Left
     (f2 Pts2 TOL) ;Recurse Right
     (setq Mx (caar Pts2)) ;Midpoint
     (setq x1 (- Mx tol)) ;L points in the TOL
     (setq x2 (+ Mx tol)) ;R points in the TOL
     (while (and pts2 (<= (caar pts2) x2)) ;gather the points in the Right
       (setq Pts3 (cons (cons (car pts2) 1) Pts3)) ;1 means in the Right
       (setq pts2 (cdr pts2))
     )
     (setq pts3 (reverse pts3))
     (while (and pts1 (>= (caar pts1) x1)) ;gather the points in the Left
       (setq Pts3 (cons (cons (car pts1) 0) Pts3)) ;0 means in the Left
       (setq pts1 (cdr pts1))
     )
     (setq Pts3 (sorty pts3 tol)) ;sort these points by Y value
     (setq pts4 (cdr pts3)) ;consider these points one by one
     (if pts4
       (while pts3
(setq pt1 (caar pts3))
(setq pt2 (caar pts4))
(while (and pts4 (<= (- (cadr pt2) (cadr pt1)) tol))
   (if (and (/= (cdar pts3) (cdar pts4)) ;different side;
    (equal (car pt1) (car pt2) tol) ;x value in tol;
    (<= (distance pt1 pt2) tol) ;distance <= tol;
       )
     (setq pairs (cons pt1 pairs) ;add the start point into pairs;
   pairs (cons pt2 pairs) ;add the end point into pairs;
     )
   )
   (setq pts4 (cdr pts4))
   (setq pt2 (caar pts4))
)
(setq pts3 (cdr pts3))
(setq pts4 (cdr pts3))
       )
     )
     Pairs
    )
  )
)
Ok ,this is the main code. I considered the duplicate points. So this program can be used for removing duplicate elements, or finding those closed points,etc.  these kinds of finding will get easier and quicklier. I have no idea for analysing the time complexity of this algorithm. maybe it's  in O(n*log(n)),because I tested it many times, found that it's faster than pkohut's. I think his algorithm is  in O(n*log(n)).
by the way, I posted these LSP files,and  a program for generating  random points(it's real random,not fake random). just for 2004-2006,if  someone can help me to compile these to the other versions,I will thank him very much.
Code: [Select]
//-----------------------------------------------------------------------------
//----- acrxEntryPoint.h
//-----------------------------------------------------------------------------
#include "StdAfx.h"
#include "resource.h"
#include "tchar.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

//-----------------------------------------------------------------------------
#define szRDS _RXST("")

//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CCreatRandomPointsApp : public AcRxArxApp {

public:
CCreatRandomPointsApp () : AcRxArxApp () {}

virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
// TODO: Load dependencies here

// You *must* call On_kInitAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;

// TODO: Add your initialization code here
acutPrintf(_T("\nThe command is:rand."));

return (retCode) ;
}

virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
// TODO: Add your code here

// You *must* call On_kUnloadAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;

// TODO: Unload dependencies here

return (retCode) ;
}

virtual void RegisterServerComponents () {
}


// - CreatRandomPoints._Rand command (do not rename)
static void CreatRandomPoints_Rand(void)
{
// Add your code for command CreatRandomPoints._Rand here

// 输入范围
ads_point pt1,pt2;
int ret=acedGetPoint(NULL,_T("\nPlease drag the First coner of region: "),pt1);
if (ret!= RTNORM)
{
acutPrintf(_T("\nInvalid!"));
return;
}
ret=acedGetCorner(pt1,_T("\nPlease drag the region: "),pt2) ;
if (ret!= RTNORM)
{
acutPrintf(_T("\nInvalid!"));
return;
}

//转化坐标系
acdbUcs2Wcs(pt1,pt1,0);
acdbUcs2Wcs(pt2,pt2,0);

        //防止点过于密集
double deltaX = (pt2[X]-pt1[X]);
double deltaY = (pt2[Y]-pt1[Y]);
if (abs(deltaX) < 1e-4 || abs(deltaY) < 1e-4 )
{
acutPrintf(_T("\nYour region is too small,Please drag it again."));
return;
}
deltaX = deltaX / 32767.0;
deltaY = deltaY / 32767.0;

//输入数量
double Number;
acedInitGet(7,NULL);
ret = acedGetReal(_T("\nPlease Enter the Number of Points:"),&Number);
if (ret!= RTNORM)
{
acutPrintf(_T("\nInvalid input!"));
return;
}
       
//初始化种子
srand((unsigned int)time(NULL));

//获得块表
Acad::ErrorStatus es;
AcDbBlockTable * pBlockTable;
es=acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead);
if(es!=Acad::eOk)
return ;
pBlockTable->close();

//获得当前空间
resbuf tilemode;
AcDbBlockTableRecord * pBlockTableRecord;
acedGetVar(_T("TILEMODE"),&tilemode);
if(tilemode.resval.rint )
es=pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,AcDb::kForWrite);
else
es=pBlockTable->getAt(ACDB_PAPER_SPACE, pBlockTableRecord,AcDb::kForWrite);
if (es!=Acad::eOk)
return;

AcDbPoint * pPoint;
AcGePoint3d  pt;
double Cx,Cy;
Cx = pt1[X];
Cy = pt1[Y];
pt.z = 0;
       
//画点
int n = (int) Number;
for (int i = 0;i<n;i++)
{
pt.x = Cx + deltaX * rand();
pt.y = Cy + deltaY * rand();
pPoint = new AcDbPoint(pt);
es=pBlockTableRecord->appendAcDbEntity(pPoint);
pPoint->close();
}
pBlockTableRecord->close();
}
} ;

//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CCreatRandomPointsApp)

ACED_ARXCOMMAND_ENTRY_AUTO(CCreatRandomPointsApp, CreatRandomPoints, _Rand, Rand, ACRX_CMD_TRANSPARENT, NULL)
« Last Edit: May 14, 2010, 05:28:34 AM by highflybird »
I am a bilingualist,Chinese and Chinglish.

qjchen

  • Bull Frog
  • Posts: 285
  • Best wishes to all
Thank you, Highflybird

I test that when the distance is small, just like 1, not 70
your code is the most quickest one.

your recursion is very cool, thank you~
http://qjchen.mjtd.com
My blog http://chenqj.blogspot.com (Chinese, can be translate into English)

pkohut

  • Guest
Now I attached the new code.

Just had a chance to go through it a bit. First let me express good job getting this to work and it made for a good exercise.  Here's a few items to fix or change.

The CreateLine function has a potential memory leak, consider what would happen if appendAcDbEntity returns something other than Acad::eOk.

The PointArray::equal function should simply be be
Code: [Select]
BOOL PointArray::equal(const double & v1, const double & v2, const double & e)
{
    return (fabs(v2 - v1) <= e);
}
even better would be, this thrown into the point2d class
Code: [Select]
                strikeout this code.
BOOL PointArray::equal const point2d & pt1, const point2d & pt2, const double & e) const
{
    return distance(pt1, pt2) <= e); return;
}

This line

Code: [Select]
// line is OK, checking if x and y are in range before doing the more expensive distance calculation.
if (equal (pt1.x, pt2.x,TOL) && equal (pt1.y ,pt2.y,TOL) && distance(pt1,pt2) <= TOL)
should simply be
Code: [Select]
           strike this code too
if (distance(pt1,pt2) <= TOL)

========================================================================
Now to that all important timing section.  In order to get just the balls out speed I removed the AcDbLine creation from your's and Daniel's code. I also adjusted where Daniel's time starts to more closely match how you've done it.  With those adjustments on 1,000,000 points.
Your's  - 1.43 seconds    (1.45 seconds when setup to use and calc 3D data and distances)
Daniels - 7.69 seconds

For the next test I change where the timer is started in your code to more closely match Daniel's original, and I subtracted 1 from your total time as an allowance to type "all" at the select objects prompt and hit return twice.
Your's  - 22.63 seconds
Daniel's - 8.24 seconds

And finally enable the AcDbLine creation.
Your's  - 31.48 seconds.
Daniel's - 18.90 seconds  (oops forgot to cache a value, now down to 16.4)

========================================================================
So overall very good job. Now I challenge you to make your whole program faster, cause 20 seconds acedSSGet is killing it.
« Last Edit: June 17, 2010, 09:41:55 AM by pkohut »