Triangulate.cpp
上传用户:ynjin1970
上传日期:2014-10-13
资源大小:6438k
文件大小:16k
源码类别:

中间件编程

开发平台:

Visual C++

  1. // GenerateTri1.cpp: implementation of the CTriangulate class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. //#include "ct.h"
  6. #include "Triangulate.h"
  7. #include "globalfunctions.h"
  8. #include <math.h>
  9. #include <strstrea.h>
  10. #ifdef _DEBUG
  11. #undef THIS_FILE
  12. static char THIS_FILE[]=__FILE__;
  13. #define new DEBUG_NEW
  14. #endif
  15. //////////////////////////////////////////////////////////////////////
  16. // Construction/Destruction
  17. //////////////////////////////////////////////////////////////////////
  18. CTriangulate::CTriangulate()
  19. {
  20. nv_ = 0;
  21. ntri_ = 0;
  22. }
  23. CTriangulate::~CTriangulate()
  24. {
  25. delete []pv_;
  26. delete ptri_;
  27. }
  28. /*******************************************************************
  29.    Triangulation subroutine
  30.    Takes as input NV vertices in array pxyz
  31.    Returned is a list of ntri triangular faces in the array v
  32.    These triangles are arranged in a consistent clockwise order.
  33.    The triangle array 'v' should be malloced to 3 * nv
  34.    The vertex array pxyz must be big enough to hold 3 more points
  35.    The vertex array must be sorted in increasing x values say
  36.    qsort(p,nv,sizeof(XYZ),XYZCompare);
  37.       :
  38.    int XYZCompare(void *v1,void *v2)
  39.    {
  40.       XYZ *p1,*p2;
  41.       p1 = v1;
  42.       p2 = v2;
  43.       if (p1->x < p2->x)
  44.          return(-1);
  45.       else if (p1->x > p2->x)
  46.          return(1);
  47.       else
  48.          return(0);
  49.    }
  50. ******************************************************************/
  51. int CTriangulate::Triangulate(int nv, XYZ *pxyz, int *ntri, TRIANGLE *v)
  52.   // nv为存储在顶点数组pxyz中的顶点的个数
  53.   // 返回存储在V中的三角形,其个数由ntri指定
  54. {
  55.    int *complete = NULL; //在点已按x轴排序的情况下表示三角形是否需要处理
  56.    IEDGE *edges = NULL;
  57.    int nedge = 0;
  58.    int trimax; // 三角形的最多个数
  59.    int emax = 200; //边缓冲区的最大长度,会自然增长。与edges关联
  60.    int status = 0;  //非0表示错误
  61.    int inside;
  62.    int i,j,k;
  63.    double xp,yp,x1,y1,x2,y2,x3,y3,xc,yc,r; //判断点是否在外接圆内
  64.    double xmin,xmax,ymin,ymax,xmid,ymid,dx, dy, dmax; //超级三角形
  65.    /* Allocate memory for the completeness list, flag for each triangle */
  66.    trimax = 4 * nv;
  67.    if ((complete = (int *) malloc(trimax*sizeof(int))) == NULL) {
  68.       status = 1;
  69.       goto skip;
  70.    }
  71.    /* Allocate memory for the edge list */
  72.    if ((edges = (IEDGE *) malloc(emax*(long)sizeof(IEDGE))) == NULL) {
  73.       status = 2;
  74.       goto skip;
  75.    }
  76.    /*
  77.       Find the maximum and minimum vertex bounds.
  78.       This is to allow calculation of the bounding triangle
  79.    */
  80.    xmin = pxyz[0].x;
  81.    ymin = pxyz[0].y;
  82.    xmax = xmin;
  83.    ymax = ymin;
  84.    for (i=1;i<nv;i++) {
  85.       if (pxyz[i].x < xmin) xmin = pxyz[i].x;
  86.       if (pxyz[i].x > xmax) xmax = pxyz[i].x;
  87.       if (pxyz[i].y < ymin) ymin = pxyz[i].y;
  88.       if (pxyz[i].y > ymax) ymax = pxyz[i].y;
  89.    }
  90.    dx = xmax - xmin;
  91.    dy = ymax - ymin;
  92.    dmax = (dx > dy) ? dx : dy;
  93.    xmid = (xmax + xmin) / 2.0;
  94.    ymid = (ymax + ymin) / 2.0;
  95.    /*
  96.       Set up the supertriangle
  97.       This is a triangle which encompasses all the sample points.
  98.       The supertriangle coordinates are added to the end of the
  99.       vertex list. The supertriangle is the first triangle in
  100.       the triangle list.
  101.    */
  102.    pxyz[nv+0].x = xmid - 20 * dmax;
  103.    pxyz[nv+0].y = ymid - dmax;
  104.    pxyz[nv+0].z = 0.0;
  105.    pxyz[nv+1].x = xmid;
  106.    pxyz[nv+1].y = ymid + 20 * dmax;
  107.    pxyz[nv+1].z = 0.0;
  108.    pxyz[nv+2].x = xmid + 20 * dmax;
  109.    pxyz[nv+2].y = ymid - dmax;
  110.    pxyz[nv+2].z = 0.0;
  111.    v[0].p1 = nv;
  112.    v[0].p2 = nv+1;
  113.    v[0].p3 = nv+2;
  114.    complete[0] = FALSE;
  115.    *ntri = 1;
  116.    /*
  117.       Include each point one at a time into the existing mesh
  118.    */
  119.    for (i=0;i<nv;i++) {
  120.       xp = pxyz[i].x;
  121.       yp = pxyz[i].y;
  122.       nedge = 0;
  123.       /*
  124.          Set up the edge buffer.
  125.          If the point (xp,yp) lies inside the circumcircle then the
  126.          three edges of that triangle are added to the edge buffer
  127.          and that triangle is removed.
  128.       */
  129.       for (j=0;j<(*ntri);j++) {
  130.          if (complete[j])
  131.             continue;
  132.          x1 = pxyz[v[j].p1].x;
  133.          y1 = pxyz[v[j].p1].y;
  134.          x2 = pxyz[v[j].p2].x;
  135.          y2 = pxyz[v[j].p2].y;
  136.          x3 = pxyz[v[j].p3].x;
  137.          y3 = pxyz[v[j].p3].y;
  138.          inside = CircumCircle(xp,yp,x1,y1,x2,y2,x3,y3,&xc,&yc,&r);
  139.          if (xc + r < xp)
  140.             complete[j] = TRUE;
  141.          if (inside) {
  142.             /* Check that we haven't exceeded the edge list size */
  143.             if (nedge+3 >= emax) {
  144.                emax += 100;
  145.                if ((edges = (IEDGE *) realloc(edges,emax*(long)sizeof(IEDGE))) == NULL) {
  146.                   status = 3;
  147.                   goto skip;
  148.                }
  149.             }
  150.             edges[nedge+0].p1 = v[j].p1;
  151.             edges[nedge+0].p2 = v[j].p2;
  152.             edges[nedge+1].p1 = v[j].p2;
  153.             edges[nedge+1].p2 = v[j].p3;
  154.             edges[nedge+2].p1 = v[j].p3;
  155.             edges[nedge+2].p2 = v[j].p1;
  156.             nedge += 3;
  157.             v[j] = v[(*ntri)-1];
  158.             complete[j] = complete[(*ntri)-1];
  159.             (*ntri)--;
  160.             j--;
  161.          }
  162.       }
  163.       /*
  164.          Tag multiple edges
  165.          Note: if all triangles are specified anticlockwise then all
  166.                interior edges are opposite pointing in direction.
  167.       */
  168.       for (j=0;j<nedge-1;j++) {
  169.          for (k=j+1;k<nedge;k++) {
  170.             if ((edges[j].p1 == edges[k].p2) && (edges[j].p2 == edges[k].p1)) {
  171.                edges[j].p1 = -1;
  172.                edges[j].p2 = -1;
  173.                edges[k].p1 = -1;
  174.                edges[k].p2 = -1;
  175.             }
  176.             /* Shouldn't need the following, see note above */
  177.             if ((edges[j].p1 == edges[k].p1) && (edges[j].p2 == edges[k].p2)) {
  178.                edges[j].p1 = -1;
  179.                edges[j].p2 = -1;
  180.                edges[k].p1 = -1;
  181.                edges[k].p2 = -1;
  182.             }
  183.          }
  184.       }
  185.       /*
  186.          Form new triangles for the current point
  187.          Skipping over any tagged edges.
  188.          All edges are arranged in clockwise order.
  189.       */
  190.       for (j=0;j<nedge;j++) {
  191.          if (edges[j].p1 < 0 || edges[j].p2 < 0)
  192.             continue;
  193.          if ((*ntri) >= trimax) {
  194.             status = 4;
  195.             goto skip;
  196.          }
  197.          v[*ntri].p1 = edges[j].p1;
  198.          v[*ntri].p2 = edges[j].p2;
  199.          v[*ntri].p3 = i;
  200.          complete[*ntri] = FALSE;
  201.          (*ntri)++;
  202.       }
  203.    }
  204.    /*
  205.       Remove triangles with supertriangle vertices
  206.       These are triangles which have a vertex number greater than nv
  207.    */
  208.    for (i=0;i<(*ntri);i++) {
  209.       if (v[i].p1 >= nv || v[i].p2 >= nv || v[i].p3 >= nv) {
  210.          v[i] = v[(*ntri)-1];
  211.          (*ntri)--;
  212.          i--;
  213.       }
  214.    }
  215. skip:
  216.    free(edges);
  217.    free(complete);
  218.    return(status);
  219. }
  220. /////////////////////////////////////////////////////////////////////
  221. /*
  222.    Return TRUE if a point (xp,yp) is inside the circumcircle made up
  223.    of the points (x1,y1), (x2,y2), (x3,y3)
  224.    The circumcircle centre is returned in (xc,yc) and the radius r
  225.    NOTE: A point on the edge is inside the circumcircle
  226. */
  227. int CTriangulate::CircumCircle(double xp,double yp,
  228.    double x1,double y1,double x2,double y2,double x3,double y3,
  229.    double *xc,double *yc,double *r)
  230. {
  231.    double m1,m2,mx1,mx2,my1,my2;
  232.    double dx,dy,rsqr,drsqr;
  233.    double EPSILON = 0.000001;
  234.    /* Check for coincident points */
  235.    if (fabs(y1-y2) < EPSILON && fabs(y2-y3) < EPSILON)
  236.        return(FALSE);
  237.    if (fabs(y2-y1) < EPSILON) {
  238.       m2 = - (x3-x2) / (y3-y2);
  239.       mx2 = (x2 + x3) / 2.0;
  240.       my2 = (y2 + y3) / 2.0;
  241.       *xc = (x2 + x1) / 2.0;
  242.       *yc = m2 * (*xc - mx2) + my2;
  243.    } else if (fabs(y3-y2) < EPSILON) {
  244.       m1 = - (x2-x1) / (y2-y1);
  245.       mx1 = (x1 + x2) / 2.0;
  246.       my1 = (y1 + y2) / 2.0;
  247.       *xc = (x3 + x2) / 2.0;
  248.       *yc = m1 * (*xc - mx1) + my1;
  249.    } else {
  250.       m1 = - (x2-x1) / (y2-y1);
  251.       m2 = - (x3-x2) / (y3-y2);
  252.       mx1 = (x1 + x2) / 2.0;
  253.       mx2 = (x2 + x3) / 2.0;
  254.       my1 = (y1 + y2) / 2.0;
  255.       my2 = (y2 + y3) / 2.0;
  256.       *xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
  257.       *yc = m1 * (*xc - mx1) + my1;
  258.    }
  259.    dx = x2 - *xc;
  260.    dy = y2 - *yc;
  261.    rsqr = dx*dx + dy*dy;
  262.    *r = sqrt(rsqr);
  263.    dx = xp - *xc;
  264.    dy = yp - *yc;
  265.    drsqr = dx*dx + dy*dy;
  266.    return((drsqr <= rsqr) ? TRUE : FALSE);
  267. }
  268. void CTriangulate::QSortVertexByX() //X增大排序
  269. {
  270. qsort((void *)pv_, (size_t)nv_, sizeof(XYZ), compare);
  271. }
  272. ///////////////////////////////////////////////////////////////////////
  273. /*
  274.    用成员变量m_szFileName指定的文件初始化pv_和nv_.
  275.    成功返回true,否则返回false
  276. */
  277. bool CTriangulate::Initial(char *szFileName) 
  278. {
  279. strcpy(szFileName_, szFileName); // 初始化成员变量,该文件保存了顶点信息
  280. char *buf = NULL;
  281. if ( this->szFileName_ == NULL ) return false;
  282. // 使用内存映像文件来读取文件数据
  283. HANDLE hFile = CreateFile( szFileName_,
  284.    GENERIC_READ,
  285.    FILE_SHARE_READ,
  286.    NULL, //security attributes
  287.    OPEN_EXISTING,
  288.    FILE_FLAG_SEQUENTIAL_SCAN,
  289.    NULL); //template file
  290. if ( hFile == INVALID_HANDLE_VALUE) return false; //因错误返回
  291. HANDLE hFileMapping = CreateFileMapping(hFile, 
  292. NULL,  // Security attributes
  293. PAGE_READONLY, 
  294. 0,   //内存映射的最大大小,这位64位中的高位
  295. 0, //64位中的低位,0为匹配文件的实际长度
  296. NULL); //给内存映射命名
  297. if ( hFileMapping == NULL ) return false;
  298. LPVOID pMem =  MapViewOfFile(hFileMapping,
  299.   FILE_MAP_READ,
  300.   0, //视图在映射文件的起始位置,64位中的高位
  301.   0, // 64位中的低位,这是从文件头开始映射
  302.   0); //映射长度
  303. if (pMem == NULL) return false;
  304. buf = (char *)pMem;
  305. ////////////////////////////////////////////////////////////////
  306. // TODO: Add your process in here
  307. //
  308. char linebuf[1024];
  309. char *pos;
  310. XYZ *pTemp;
  311. long MAXVERTEX = 1000;
  312. //pv_  = (XYZ *)malloc( MAXVERTEX * sizeof(XYZ) );
  313. if ((pv_ = new XYZ[MAXVERTEX]) == NULL )  return false;
  314. istrstream is(buf, GetFileSize(hFile, NULL));
  315. while ( ! is.eof() )
  316. {
  317. is.getline(linebuf, 1024);
  318. pos = strchr(linebuf, '#'); // 符号#后为注释
  319. if ( pos != NULL ) *pos = ''; //remove comment
  320. if ( sscanf(linebuf, "%le %le %le", &pv_[nv_].x, &pv_[nv_].y, &pv_[nv_].z ) != 3)
  321. continue; // error! continue to read next line
  322. else
  323. {
  324. nv_++;
  325. if ( nv_ >= MAXVERTEX)
  326. {
  327. if ((pTemp = new XYZ[MAXVERTEX + 1000]) == NULL ) return false;
  328. memcpy(pTemp, pv_, sizeof(XYZ) * MAXVERTEX);
  329. delete []pv_;
  330. pv_ = pTemp;
  331. MAXVERTEX += 1000;
  332. }
  333. }
  334. }
  335. //
  336. // end your process
  337. //////////////////////////////////////////////////////////////////
  338. CloseHandle(hFile);
  339. CloseHandle(hFileMapping);
  340. UnmapViewOfFile(pMem);
  341. // set RBvertex_ and LTvertex_
  342. LTvertex_ = pv_[0];
  343. RBvertex_ = LTvertex_;
  344. for ( int i = 1; i < nv_; i++ )
  345. {
  346. if ( pv_[i].x > LTvertex_.x ) LTvertex_.x = pv_[i].x;
  347. if ( pv_[i].x < RBvertex_.x ) RBvertex_.x = pv_[i].x;
  348. if ( pv_[i].y > LTvertex_.y ) LTvertex_.y = pv_[i].y;
  349. if ( pv_[i].y < RBvertex_.y ) RBvertex_.y = pv_[i].y;
  350. if ( pv_[i].z > LTvertex_.z ) LTvertex_.z = pv_[i].z;
  351. if ( pv_[i].z < RBvertex_.z ) RBvertex_.z = pv_[i].z;
  352. }
  353. return true; //正常返回为0
  354. }
  355. //////////////////////////////////////////////////////////////////////
  356. /*
  357.    根据nv_和pv_创建三角形,创建的三角形保存在ptri_中
  358.    三角形的个数保存在ntri_中;
  359.    其中需要调用三角形的剖分算法Triangulate()
  360.    注意:
  361.        有很多种三角剖分算法,Triangulate()是一种增量算法。
  362. */
  363. bool CTriangulate::CreateTriangle()
  364. {
  365. SortAndRemoveRepeatPoints(); // 根据x的大小对pv_进行排序,并且删掉重复的点
  366. // Triangulate()函数需要已经排序过的pv_
  367. AfxMessageBox("排序和删除重复点结束。",0,0);
  368. if ((ptri_ = new TRIANGLE[4 * nv_]) == NULL)
  369. return false; //三角形的最多个数是顶点个数的4倍
  370. Triangulate(nv_, pv_, &ntri_, ptri_);
  371. AfxMessageBox("三角剖分结束。",0,0);
  372. MeshedTris();
  373. AfxMessageBox("建立三角形之间的关系结束。",0,0);
  374. return true;
  375. }
  376. XYZ CTriangulate::GetLTvertex() // 获得散点的xyz的最大值
  377. {
  378. return LTvertex_;
  379. }
  380. XYZ CTriangulate::GetRBvertex() // 获得散点的xyz的最小值
  381. {
  382. return RBvertex_;
  383. }
  384. // 为TRIANGLE的T1,T2,T3设定值。即建立三角形的邻接关系
  385. void CTriangulate::MeshedTris() //对各个独立的三角形建立网络联系
  386. {
  387. int i, j;
  388. for (i = 0; i < ntri_; i++) // remove 不规范的点, need it?
  389. {
  390. if (ptri_[i].p1 == ptri_[i].p2 || ptri_[i].p1 == ptri_[i].p3 || ptri_[i].p2 == ptri_[i].p3 )
  391. {
  392. ptri_[i] = ptri_[ntri_ - 1];
  393. ntri_--;
  394. }
  395. }
  396. for (i = 0; i < ntri_; i++)
  397. {
  398. if (ptri_[i].t3 == NEIGHBOR_UNKNOWN)
  399. for ( j = i + 1; j < ntri_; j++)
  400. {
  401. if (   (ptri_[i].p1 == ptri_[j].p1 || ptri_[i].p1 == ptri_[j].p2 || ptri_[i].p1 == ptri_[j].p3 )
  402. && (ptri_[i].p2 == ptri_[j].p1 || ptri_[i].p2 == ptri_[j].p2 || ptri_[i].p2 == ptri_[j].p3 ) )
  403. {
  404. ptri_[i].t3 = j; // 设置第i个三角形的边p1p2的邻接三角形
  405. // 由于两个邻接三角形是相互邻接的,所以同时设置“邻接三角形j”的邻接三角形为i
  406. if ( ptri_[j].p1 + ptri_[j].p2 == ptri_[i].p1 + ptri_[i].p2 ) 
  407. ptri_[j].t3 = i; 
  408. else if ( ptri_[j].p1 + ptri_[j].p3 == ptri_[i].p1 + ptri_[i].p2 ) 
  409. ptri_[j].t2 = i;
  410. else //( ptri_[j].p3 + ptri_[j].p2 == ptri_[i].p1 + ptri_[i].p2 ) 
  411. ptri_[j].t1 = i;
  412. break;
  413. }
  414. }
  415. if (ptri_[i].t2 == NEIGHBOR_UNKNOWN)
  416. for ( j = i + 1; j < ntri_; j++)
  417. {
  418. if (   (ptri_[i].p1 == ptri_[j].p1 || ptri_[i].p1 == ptri_[j].p2 || ptri_[i].p1 == ptri_[j].p3 )
  419. && (ptri_[i].p3 == ptri_[j].p1 || ptri_[i].p3 == ptri_[j].p2 || ptri_[i].p3 == ptri_[j].p3 ) )
  420. {
  421. ptri_[i].t2 = j; // 设置第i个三角形的边p1p2的邻接三角形
  422. // 由于两个邻接三角形是相互邻接的,所以同时设置“邻接三角形j”的邻接三角形为i
  423. if ( ptri_[j].p1 + ptri_[j].p2 == ptri_[i].p1 + ptri_[i].p3 ) 
  424. ptri_[j].t3 = i; 
  425. else if ( ptri_[j].p1 + ptri_[j].p3 == ptri_[i].p1 + ptri_[i].p3 ) 
  426. ptri_[j].t2 = i;
  427. else //if ( ptri_[j].p3 + ptri_[j].p2 == ptri_[i].p1 + ptri_[i].p3 ) 
  428. ptri_[j].t1 = i;
  429. break;
  430. }
  431. }
  432. if (ptri_[i].t1 == NEIGHBOR_UNKNOWN)
  433. for ( j = i + 1; j < ntri_; j++)
  434. {
  435. if (   (ptri_[i].p3 == ptri_[j].p1 || ptri_[i].p3 == ptri_[j].p2 || ptri_[i].p3 == ptri_[j].p3 )
  436. && (ptri_[i].p2 == ptri_[j].p1 || ptri_[i].p2 == ptri_[j].p2 || ptri_[i].p2 == ptri_[j].p3 ) )
  437. {
  438. ptri_[i].t1 = j; // 设置第i个三角形的边p1p2的邻接三角形
  439. // 由于两个邻接三角形是相互邻接的,所以同时设置“邻接三角形j”的邻接三角形为i
  440. if ( ptri_[j].p1 + ptri_[j].p2 == ptri_[i].p3 + ptri_[i].p2 ) 
  441. ptri_[j].t3 = i; 
  442. else if ( ptri_[j].p1 + ptri_[j].p3 == ptri_[i].p3 + ptri_[i].p2 ) 
  443. ptri_[j].t2 = i;
  444. else //if ( ptri_[j].p3 + ptri_[j].p2 == ptri_[i].p3 + ptri_[i].p2 ) 
  445. ptri_[j].t1 = i;
  446. break;
  447. }
  448. }
  449. } // end i
  450. }
  451. void CTriangulate::SortAndRemoveRepeatPoints()
  452. {
  453. int i, j;
  454. int pos(0), pos2(0);
  455. int readpos(0), writepos(0);
  456. QSortVertexByX(); // 按X增大排序
  457. bool *flagkilled = new bool[nv_];
  458. for ( i = 0; i < nv_; i++)
  459. flagkilled[i] = false;
  460. while( pos < nv_)
  461. {
  462. while( pv_[++pos2].x == pv_[pos].x );
  463. for(i = pos; i < pos2; i++)
  464. {
  465. if(flagkilled[i]) continue;
  466. for (j = i + 1; j < pos2; j++)
  467. if(pv_[j].y == pv_[i].y) 
  468. flagkilled[j] = true;
  469. }
  470. pos = pos2;
  471. }
  472. while(readpos < nv_)
  473. {
  474. while(flagkilled[readpos]) // skip killed points
  475. readpos++;
  476. if (writepos != readpos)
  477. pv_[writepos] = pv_[readpos];
  478. writepos++;
  479. readpos++;
  480. }
  481. nv_ = writepos;
  482. delete []flagkilled;
  483. //TRACE("output norepeat points: nv=%dn", nv_);
  484. //for (i=0; i<nv_; i++)
  485. // TRACE("%lf  %lf  %lfn", pv_[i].x, pv_[i].y, pv_[i].z);
  486. //TRACE("End outputn");
  487. }