Exemple #1
0
void Delaunay::removeBounding( TriangleVector inSet, 
	TriangleVector &outSet, const int &index )
{
	for (TriangleVector::iterator iter = inSet.begin(); 
		iter != inSet.end(); iter++)
	{
		if (iter->m_vertices[0].m_index >= 0 && 
			iter->m_vertices[1].m_index >= 0 && 
			iter->m_vertices[2].m_index >= 0 && 
			iter->isVertex(index) && 
			iter->angleCriterion(m_minAngle, m_maxAngle))
		{
			outSet.push_back(*iter);
		}
	}
}
Exemple #2
0
void Delaunay::addBounding( const VertexVector &verSet, 
	TriangleVector &triSet )
{
	double max_x = -100000, max_y = -100000;
	double min_x = 100000, min_y = 100000;
	for (int i = 0; i < verSet.size(); i++)
	{
		Vec3d v = verSet[i].m_xyz;
		max_x = max_x < v[0] ? v[0] : max_x;
		min_x = min_x > v[0] ? v[0] : min_x;
		max_y = max_y < v[1] ? v[1] : max_y;
		min_y = min_y > v[1] ? v[1] : min_y;
	}

	// 将矩形区域的外接三角形作为边界
	double dx = max_x - min_x;
	double dy = max_y - min_y;
	double mid_x = (min_x + max_x) / 2;
	double mid_y = (min_y + max_y) / 2;

	// 为了去除边界方便讲边界点的索引置为负数
	Vertex v0(Vec3d(mid_x, max_y + dy, 0.0f), -1);
	Vertex v1(Vec3d(mid_x - dx, min_y, 0.0f), -2);
	Vertex v2(Vec3d(mid_x + dx, min_y, 0.0f), -3);

	triSet.push_back(Triangle(v0, v1, v2));
}
Exemple #3
0
void Delaunay::saveTriangles( const TriangleVector &triSet, char* file )
{
	ofstream ofs(file);
	if (ofs)
	{
		ofs << triSet.size() << endl;
		for (int i = 0; i < triSet.size(); i++)
		{
			Triangle t = triSet[i];
			for (int j = 0; j < Triangle::Vertex_Size; j++)
			{
				ofs << t.m_vertices[j].m_xyz;
			}
			ofs << endl;
		}
	}
}
Exemple #4
0
void Delaunay::drawTrianglesOnPlane( const TriangleVector &triSet )
{
	int width = 1024, height = 768;
	Mat triangleImg(height, width, CV_8UC3, Scalar::all(0));
	if (triSet.size() == 0)
	{
		imshow("Triangle", triangleImg);
		waitKey();
		return;
	}

	double max_x = -100000, max_y = -100000;
	double min_x = 100000, min_y = 100000;
	for (int i = 0; i < triSet.size(); i++)
	{
		for (int j = 0; j < Triangle::Vertex_Size; j++)
		{
			Vec3d v = triSet[i].m_vertices[j].m_xyz;
			max_x = max_x < v[0] ? v[0] : max_x;
			min_x = min_x > v[0] ? v[0] : min_x;
			max_y = max_y < v[1] ? v[1] : max_y;
			min_y = min_y > v[1] ? v[1] : min_y;
		}
	}

	for (int i = 0; i < triSet.size(); i++)
	{
		Point ps[3];
		for (int j = 0; j < Triangle::Vertex_Size; j++)
		{
			double tmpx = triSet[i].m_vertices[j].m_xyz[0];
			double tmpy = triSet[i].m_vertices[j].m_xyz[1];

			double x = (tmpx - min_x) * 800 / (max_x - min_x) + 100;
			double y = (max_y - tmpy) * 600 / (max_y - min_y) + 100;

			ps[j].x = (int)x;
			ps[j].y = (int)y;
		}
		line(triangleImg, ps[0], ps[1], Scalar::all(255));
		line(triangleImg, ps[1], ps[2], Scalar::all(255));
		line(triangleImg, ps[2], ps[0], Scalar::all(255));
	}

	for (int i = 0; i < triSet.size(); i++)
	{
		for (int j = 0; j < 3; j++)
		{
			double tmpx = triSet[i].m_vertices[j].m_xyz[0];
			double tmpy = triSet[i].m_vertices[j].m_xyz[1];

			double fx = (tmpx - min_x) * 800 / (max_x - min_x) + 100;
			double fy = (max_y - tmpy) * 600 / (max_y - min_y) + 100;

			int x = (int)fx;
			int y = (int)fy;

			if (triSet[i].m_vertices[j].m_index < 0)
			{
				for (int m = -1; m <= 1; m++)
				{
					for (int n = -1; n <= 1; n++)
					{
						triangleImg.at<Vec3b>(y + m, x + n) = Vec3b(0, 255, 0);
					}
				}
			}
			else
			{
				for (int m = -1; m <= 1; m++)
				{
					for (int n = -1; n <= 1; n++)
					{
						triangleImg.at<Vec3b>(y + m, x + n) = Vec3b(255, 0, 255);
					}
				}
			}
		}
	}

	imshow("Triangle", triangleImg);
	waitKey();
}
Exemple #5
0
bool Delaunay::flipTest( TriangleVector &triSet, Triangle t )
{
	bool flipped = false;

	Vertex a = t.m_vertices[0];
	Vertex b = t.m_vertices[1];
	Vertex c = t.m_vertices[2]; 

	TriangleVector tSet;
	for (TriangleVector::iterator iter = triSet.begin(); 
		iter != triSet.end();)
	{
		Vertex d;
		d.m_index = -100;

		// 寻找拥有相同边ab的三角形
		int satisfy[3] = {0, 0, 0};
		for (int j = 0, k = 1; j < Triangle::Vertex_Size; j++, k *= 2)
		{
			if (iter->m_vertices[j].m_index == a.m_index || 
				iter->m_vertices[j].m_index == b.m_index)
			{
				satisfy[j] = k;
			}
		}
		switch (satisfy[0] | satisfy[1] | satisfy[2])
		{
		case 3:	// v2
			if (Vertex::cross(a, c, iter->m_vertices[2]) != 0 &&
				Vertex::cross(b, c, iter->m_vertices[2]) != 0)
			{
				d = iter->m_vertices[2];
			}
			break;
		case 5: // v1
			if (Vertex::cross(a, c, iter->m_vertices[1]) != 0 &&
				Vertex::cross(b, c, iter->m_vertices[1]) != 0)
			{
				d = iter->m_vertices[1];
			}
			break;
		case 6: // v0
			if (Vertex::cross(a, c, iter->m_vertices[0]) != 0 &&
				Vertex::cross(b, c, iter->m_vertices[0]) != 0)
			{
				d = iter->m_vertices[0];
			}
			break;
		default:
			break;
		}

		if (d.m_index != -100)
		{
			if (inCircle(a, b, c, d))	// 判断d是否在三角形abc的外接圆内
			{
				flipped = true;
				Triangle t0(a, d, c);
				Triangle t1(d, b, c);
				tSet.push_back(t0);
				tSet.push_back(t1);
				iter = triSet.erase(iter);
				break;
			}
			else
			{
				iter++;
			}
		}
		else
		{
			iter++;
		}
	}

	for (int i = 0; i < tSet.size(); i++)
	{
		if (!flipTest(triSet, tSet[i]))
		{
			triSet.push_back(tSet[i]);
		}
	}
	return flipped;
}
Exemple #6
0
void Delaunay::insertVertex( TriangleVector &triSet, const Vertex &v )
{
	TriangleVector tmp;
	for (TriangleVector::iterator iter = triSet.begin(); 
		iter != triSet.end();)
	{
		int r = iter->inTriangle(v);	// 判断点是否在三角形内
// 		cout << iter->m_vertices[0].m_xyz 
// 			<< iter->m_vertices[1].m_xyz 
// 			<< iter->m_vertices[2].m_xyz << endl;
		switch (r)
		{
		case 0:		// in
			{
				Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v);
				Triangle t1(iter->m_vertices[1], iter->m_vertices[2], v);
				Triangle t2(iter->m_vertices[2], iter->m_vertices[0], v);
				tmp.push_back(t0);
				tmp.push_back(t1);
				tmp.push_back(t2);
				iter = triSet.erase(iter);
			}
			break;
		case -1:	// on v0v1
			{
				Triangle t0(iter->m_vertices[1], iter->m_vertices[2], v);
				Triangle t1(iter->m_vertices[2], iter->m_vertices[0], v);
				tmp.push_back(t0);
				tmp.push_back(t1);
				iter = triSet.erase(iter);
			}
			break;
		case -2:	// on v1v2
			{
				Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v);
				Triangle t1(iter->m_vertices[2], iter->m_vertices[0], v);
				tmp.push_back(t0);
				tmp.push_back(t1);
				iter = triSet.erase(iter);
			}
			break;
		case -3:	// on v2v0
			{
				Triangle t0(iter->m_vertices[0], iter->m_vertices[1], v);
				Triangle t1(iter->m_vertices[1], iter->m_vertices[2], v);
				tmp.push_back(t0);
				tmp.push_back(t1);
				iter = triSet.erase(iter);
			}
			break;
		default:
			iter++;
			break;
		}
		if (r <= 0)
		{
			break;
		}
	}

	for (int i = 0; i < tmp.size(); i++)
	{
		if (!flipTest(triSet, tmp[i]))	// 优化delaunay三角
		{
			triSet.push_back(tmp[i]);
		}
/*		drawTrianglesOnPlane(triSet);*/
	}
}
Exemple #7
0
void Delaunay::computeDelaunay(Mesh &mesh)
{
	int size = (int)mesh.getVerticesSize();
	if (size == 0)
	{
		return;
	}
	mesh.computeVerticesNormals();
	m_preSize = mesh.m_curIndex;

	TriangleSet triSet;
	// 依次遍历每个点,寻找最近邻,进行三角化
	for (; mesh.m_curIndex < size; mesh.m_curIndex++)
	{
		Vertex v = mesh.getVertex(mesh.m_curIndex);
		if (v.m_isInner)
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		Vec3d normal = v.m_normal;
		int id = 2;
		// 判断法向量哪个不为0,z->y->x
		if (normal[2] != 0)		// z
		{
			id = 2;
		}
		else if (normal[1] != 0)// y
		{
			id = 1;
		}
		else if (normal[0] != 0)// x
		{
			id = 0;
		}
		else	// 法向量为(0, 0, 0),
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		double minDistance = -1;
		int cnt = v.m_neighbors[0];					// 最近邻数目
		double dists[k];
		for (int j = 1; j < cnt + 1; j++)
		{
			Vec3d dv = mesh.getVertex(v.m_neighbors[j]).m_xyz - v.m_xyz;
			dists[j] = dv.ddot(dv);
		}
		minDistance = dists[1];
		VertexVector vVector, tmpvVector;
		// 将最近邻点投射到该点的切平面上
		for (int j = 1; j < cnt + 1; j++)
		{
			Vertex tmpv = mesh.getVertex(v.m_neighbors[j]);
			if (dists[j] < u * minDistance ||		// 去除非常接近的点
				(tmpv.m_index < v.m_index && tmpv.m_index >= m_preSize) ||	// 去除已遍历过的点
				tmpv.m_isInner)						// 去除内点
			{
				continue;
			}
			
			Vec3d vv = tmpv.m_xyz - v.m_xyz;
			double dist2 = dists[j] * 0.75f;	// sqrt
			double alpha = vv.dot(normal);
			alpha = alpha * alpha;
			if (alpha > dist2)		// 去除与法向量夹角小于30度或大于150度的点
			{
				continue;
			}
			Vec3d proj = tmpv.m_xyz - alpha * normal;		// 投射到切平面
			tmpvVector.push_back(Vertex(proj, v.m_neighbors[j]));
		}
		if (tmpvVector.size() < 3)	// 少于3个不能构成三角形
		{
			mesh.pushTriBeginIndex((int)triSet.size());
			continue;
		}

		// 将切平面转换为x-y平面进行三角形计算
		vVector.push_back(Vertex(Vec3d(0, 0, 0), mesh.m_curIndex));	// 原点
		Vec3d vx = tmpvVector[0].m_xyz - v.m_xyz;		// x轴
		vx = normalize(vx);
		for (int j = 0; j < tmpvVector.size(); j++)
		{
			Vec3d vv = tmpvVector[j].m_xyz - v.m_xyz;
			double x = vv.dot(vx);
			double y = vx.cross(vv)[id] / normal[id];
			Vec3d proj(x, y, 0);
			vVector.push_back(Vertex(proj, tmpvVector[j].m_index));
		}

		TriangleVector tVector;
		computeDelaunay(vVector, tVector);
// 		cout << vVector.size() << " " << tVector.size() << endl; 
// 		drawTrianglesOnPlane(tVector);
		for (int j = 0; j < tVector.size(); j++)
		{
			Triangle t = tVector[j];
			t.m_vertices[0] = mesh.getVertex(t.m_vertices[0].m_index);
			t.m_vertices[1] = mesh.getVertex(t.m_vertices[1].m_index);
			t.m_vertices[2] = mesh.getVertex(t.m_vertices[2].m_index);
			triSet.insert(t);
		}
		mesh.pushTriBeginIndex((int)triSet.size());
	}

	for (TriangleSet::iterator iter = triSet.begin(); 
		iter != triSet.end(); iter++)
	{
		mesh.m_triangles.push_back(*iter);
	}
}
  virtual NxU32 * removeTjunctions(NxU32 vcount,
                                    const float *vertices,
                                    size_t tcount,
                                    const NxU32 *indices,
                                    size_t &tcount_out,
                                    const NxU32 * ids)
  {
    NxU32 *ret  = 0;

    release();

    mVcount   = vcount;
    mVertices = vertices;
    mTcount   = (NxU32)tcount;
    tcount_out = 0;

    mTcount         = (NxU32)tcount;
    mMaxTcount      = (NxU32)tcount*2;
    mInputTriangles = new Triangle[mMaxTcount];
    Triangle *t     = mInputTriangles;

    mEdges          = new RtEdge[mMaxTcount*3];
    mEdgeCount      = 0;

    NxU32 id = 0;

    RtEdge *e = mEdges;
    for (NxU32 i=0; i<tcount; i++)
    {
      if ( ids ) id = *ids++;
      e =init(t,indices,vertices,e,id);
      indices+=3;
      t++;
    }

    {
      TriangleVector test;
      for (EdgeMap::Iterator i = mEdgeMap.getIterator(); !i.done(); ++i)
      {
        RtEdge *e = (*i).second;
        if ( e->mNextEdge == 0 ) // open edge!
        {
          Triangle *t = e->mTriangle;
          if ( !t->mPending )
          {
            test.pushBack(t);
            t->mPending = true;
          }
        }
      }

      if ( !test.empty() )
      {
        TriangleVector::Iterator i;
        for (i=test.begin(); i!=test.end(); ++i)
        {
          Triangle *t = (*i);
          locateIntersection(t);
        }
      }

    }

    while ( !mSplit.empty() )
    {
      TriangleVector scan = mSplit;
      mSplit.clear();
      TriangleVector::Iterator i;
      for (i=scan.begin(); i!=scan.end(); ++i)
      {
        Triangle *t = (*i);
        locateIntersection(t);
      }
    }


    mIndices.clear();
    mIds.clear();

    t = mInputTriangles;
    for (NxU32 i=0; i<mTcount; i++)
    {
      mIndices.pushBack(t->mI1);
      mIndices.pushBack(t->mI2);
      mIndices.pushBack(t->mI3);
      mIds.pushBack(t->mId);
      t++;
    }


   mEdgeMap.clear();

   delete []mEdges;
   mEdges = 0;
   delete []mInputTriangles;
   mInputTriangles = 0;
   tcount_out = mIndices.size()/3;
   ret = tcount_out ? &mIndices[0] : 0;
#ifdef _DEBUG
   if ( ret )
   {
	   const NxU32 *scan = ret;
	   for (NxU32 i=0; i<tcount_out; i++)
	   {
		   NxU32 i1 = scan[0];
		   NxU32 i2 = scan[1];
		   NxU32 i3 = scan[2];
		   assert( i1 != i2 && i1 != i3 && i2 != i3 );
		   scan+=3;
	   }
   }
#endif
    return ret;
  }