void GeometryTerrain::addTerrain(const int& size_, const float& octaves_, const float& height_, float* RGBFloats_, const float& scale2_, const float& persistance_)
{
	for (int z = 0; z < size_; ++z)
	{
		for (int x = 0; x < size_; ++x)
		{
			glm::vec4 colourBottom(RGBFloats_[0], RGBFloats_[1], RGBFloats_[2], 1.0f);
			glm::vec4 colourTop(RGBFloats_[3], RGBFloats_[4], RGBFloats_[5], 1.0f);
			
			float temp_height = octave_noise_2d(octaves_, persistance_, scale2_, x, z);
			points[x][z] = glm::vec3(x, height_ * temp_height, z);

			glm::vec4 newcolour = glm::lerp(colourBottom, colourTop, temp_height);
			//gen colour based on Y height
			colours[x][z] = newcolour;
		}		
	}
	//create the triangles from the points
	for (int z = 0; z < size_ - 1; ++z)
	{
		for (int x = 0; x < size_ - 1; ++x)
		{
			addTri(TriType::TRI_TERRAIN, points[x][z], points[x][z+1], points[x+1][z+1], colours[x][z], 0);
			addTri(TriType::TRI_TERRAIN, points[x][z], points[x + 1][z + 1], points[x + 1][z], colours[x][z], 1);
		}
	}
}
Exemple #2
0
void Patch::addQuad(const QVector3D &a, const QVector3D &b,  const QVector3D &c, const QVector3D &d)
{
    QVector3D norm = QVector3D::normal(a, b, c);

    if (sm == Smooth) {
        addTri(a, b, c, norm);
        addTri(a, c, d, norm);
    } else {
        // If faceted share the two common vertices
        addTri(a, b, c, norm);
        int k = geom->vertices.count();
        geom->appendSmooth(a, norm, k);
        geom->appendSmooth(c, norm, k);
        geom->appendFaceted(d, norm);
        count += 3;
    }
}
void GeometryTerrain::addCube(glm::vec3& position_, const float& size_)
{
	glm::vec3 pos2 = position_;
	glm::vec3 pos3 = position_;
	glm::vec4 colour = glm::vec4(1,1,1,1);
	pos2.y += 1;
	pos3.x += 1;
	addTri(TRI_PLAIN, position_, pos2, pos3, colour, 0);
}
Exemple #4
0
void Mesh::addFace(VertexList<Vertex>* vertexList, const Face& face) {
  if (face.type == Quad) 
    addQuad(vertexList, face);
  else 
    addTri(vertexList, face);
}
NxF32 computeConcavityVolume(NxU32 vcount_hull,
						     const NxF32 *vertices_hull,
						     NxU32 tcount_hull,
						     const NxU32 *indices_hull,
						     NxU32 vcount_mesh,
						     const NxF32 *vertices_mesh,
						     NxU32 tcount_mesh,
						     const NxU32 *indices_mesh)
{
	NxF32 total_volume = 0;

#if SHOW_DEBUG
	NVSHARE::gRenderDebug->pushRenderState();
	NVSHARE::gRenderDebug->setCurrentDisplayTime(150.0f);
#endif

	iRayCast *cast_hull = createRayCast(vertices_hull,tcount_hull,indices_hull);
	iRayCast *cast_mesh = createRayCast(vertices_mesh,tcount_mesh,indices_mesh);


	const NxU32 *indices = indices_mesh;
#if 0
	static NxU32 index = 0;
	NxU32 i = index++;
	indices = &indices[i*3];
#else
	for (NxU32 i=0; i<tcount_mesh; i++)
#endif
	{
		NxU32 i1 = indices[0];
		NxU32 i2 = indices[1];
		NxU32 i3 = indices[2];

		const NxF32 *p1 = &vertices_mesh[i1*3];
		const NxF32 *p2 = &vertices_mesh[i2*3];
		const NxF32 *p3 = &vertices_mesh[i3*3];

		NxF32 normal[3];
		NxF32 d = fm_computePlane(p3,p2,p1,normal);

		NxF32  vertices[6*3];

		vertices[0] = p1[0];
		vertices[1] = p1[1];
		vertices[2] = p1[2];

		vertices[3] = p2[0];
		vertices[4] = p2[1];
		vertices[5] = p2[2];

		vertices[6] = p3[0];
		vertices[7] = p3[1];
		vertices[8] = p3[2];

		NxF32 midPoint[3];
		midPoint[0] = (p1[0]+p2[0]+p3[0])/3;
		midPoint[1] = (p1[1]+p2[1]+p3[1])/3;
		midPoint[2] = (p1[2]+p2[2]+p3[2])/3;

		fm_lerp(midPoint,p1,&vertices[0],0.9999f);
		fm_lerp(midPoint,p2,&vertices[3],0.9999f);
		fm_lerp(midPoint,p3,&vertices[6],0.9999f);

		NxF32 *_p1 = &vertices[3*3];
		NxF32 *_p2 = &vertices[4*3];
		NxF32 *_p3 = &vertices[5*3];

		NxU32 hitCount = 0;

		if ( raycast(&vertices[0],normal, _p1,cast_hull,cast_mesh) ) hitCount++;
		if ( raycast(&vertices[3],normal, _p2,cast_hull,cast_mesh) ) hitCount++;
		if ( raycast(&vertices[6],normal, _p3,cast_hull,cast_mesh) ) hitCount++;

		// form triangle mesh!
		if ( hitCount == 3 )
		{
			NxU32 tcount = 0;
			NxU32 tindices[8*3];

			addTri(tindices,2,1,0,tcount);
			addTri(tindices,3,4,5,tcount);

			addTri(tindices,0,3,2,tcount);
			addTri(tindices,2,3,5,tcount);

			addTri(tindices,1,3,0,tcount);
			addTri(tindices,4,3,1,tcount);

			addTri(tindices,5,4,1,tcount);
			addTri(tindices,2,5,1,tcount);

			NxF32 volume = fm_computeMeshVolume(vertices,tcount,tindices);
			total_volume+=volume;
#if SHOW_DEBUG
			NVSHARE::gRenderDebug->setCurrentColor(0x0000FF,0xFFFFFF);
			NVSHARE::gRenderDebug->addToCurrentState(NVSHARE::DebugRenderState::SolidWireShaded);

			for (NxU32 i=0; i<tcount; i++)
			{
				NxU32 i1 = tindices[i*3+0];
				NxU32 i2 = tindices[i*3+1];
				NxU32 i3 = tindices[i*3+2];

				const NxF32 *p1 = &vertices[i1*3];
				const NxF32 *p2 = &vertices[i2*3];
				const NxF32 *p3 = &vertices[i3*3];

				NVSHARE::gRenderDebug->DebugTri(p1,p2,p3);
			}
#endif
		}
		indices+=3;
	}
#if SHOW_DEBUG
	NVSHARE::gRenderDebug->popRenderState();
#endif

	releaseRayCast(cast_hull);
	releaseRayCast(cast_mesh);

	return total_volume;
}
Exemple #6
0
bool createBox(NxVec3	&dimensions,NxuGeometry &g,const NxMat34 *localPose, float shrink,unsigned int maxV)
{

	g.reset();

	g.mVertices	=	new	float[8	*3];
	g.mVcount	=	8;
	g.mTcount	=	12;
	g.mIndices = new unsigned	int[12 *3];

	float	bmin[3];
	float	bmax[3];

	bmin[0]	=	 -dimensions.x*shrink;
	bmin[1]	=	 -dimensions.y*shrink;
	bmin[2]	=	 -dimensions.z*shrink;

	bmax[0]	=	dimensions.x*shrink;
	bmax[1]	=	dimensions.y*shrink;
	bmax[2]	=	dimensions.z*shrink;



	set(g.mVertices, 0,	bmin[0], bmin[1],	bmin[2], localPose);
	set(g.mVertices, 1,	bmax[0], bmin[1],	bmin[2], localPose);
	set(g.mVertices, 2,	bmax[0], bmax[1],	bmin[2], localPose);
	set(g.mVertices, 3,	bmin[0], bmax[1],	bmin[2], localPose);
	set(g.mVertices, 4,	bmin[0], bmin[1],	bmax[2], localPose);
	set(g.mVertices, 5,	bmax[0], bmin[1],	bmax[2], localPose);
	set(g.mVertices, 6,	bmax[0], bmax[1],	bmax[2], localPose);
	set(g.mVertices, 7,	bmin[0], bmax[1],	bmax[2], localPose);

	unsigned int *indices	=	g.mIndices;

	indices	=	addTri(0,	3, 2,	indices);
	indices	=	addTri(0,	2, 1,	indices);
	indices	=	addTri(2,	6, 5,	indices);
	indices	=	addTri(1,	2, 5,	indices);
	indices	=	addTri(6,	7, 4,	indices);
	indices	=	addTri(5,	6, 4,	indices);
	indices	=	addTri(4,	7, 3,	indices);
	indices	=	addTri(4,	3, 0,	indices);
	indices	=	addTri(5,	4, 0,	indices);
	indices	=	addTri(5,	0, 1,	indices);
	indices	=	addTri(3,	7, 6,	indices);
	indices	=	addTri(2,	3, 6,	indices);

	return true;
}
Exemple #7
0
void calcConvexDecomposition(unsigned int           vcount,
                                const float           *vertices,
                                unsigned int           tcount,
                                const unsigned int    *indices,
                                ConvexDecompInterface *callback,
                                float                  masterVolume,
                                unsigned int           depth)

{

  float plane[4];

  bool split = false;


  if ( depth < MAXDEPTH )
  {

		float volume;
		float c = computeConcavity( vcount, vertices, tcount, indices, callback, plane, volume );

    if ( depth == 0 )
    {
      masterVolume = volume;
    }

		float percent = (c*100.0f)/masterVolume;

		if ( percent > CONCAVE_PERCENT ) // if great than 5% of the total volume is concave, go ahead and keep splitting.
		{
      split = true;
    }

  }

  if ( depth >= MAXDEPTH || !split )
  {

#if 1

    HullResult result;
    HullLibrary hl;
    HullDesc   desc;

  	desc.SetHullFlag(QF_TRIANGLES);

    desc.mVcount       = vcount;
    desc.mVertices     = vertices;
    desc.mVertexStride = sizeof(float)*3;

    HullError ret = hl.CreateConvexHull(desc,result);

    if ( ret == QE_OK )
    {

			ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);


			callback->ConvexDecompResult(r);
    }


#else

		static unsigned int colors[8] =
		{
			0xFF0000,
		  0x00FF00,
			0x0000FF,
			0xFFFF00,
			0x00FFFF,
			0xFF00FF,
			0xFFFFFF,
			0xFF8040
		};

		static int count = 0;

		count++;

		if ( count == 8 ) count = 0;

		assert( count >= 0 && count < 8 );

		unsigned int color = colors[count];

    const unsigned int *source = indices;

    for (unsigned int i=0; i<tcount; i++)
    {

      unsigned int i1 = *source++;
      unsigned int i2 = *source++;
      unsigned int i3 = *source++;

			FaceTri t(vertices, i1, i2, i3 );

      callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color );

    }
#endif

    return;

  }

  UintVector ifront;
  UintVector iback;

  VertexLookup vfront = Vl_createVertexLookup();
  VertexLookup vback  = Vl_createVertexLookup();


	bool showmesh = false;
  #if SHOW_MESH
  showmesh = true;
  #endif

	if ( 0 )
	{
		showmesh = true;
	  for (float x=-1; x<1; x+=0.10f)
		{
		  for (float y=0; y<1; y+=0.10f)
			{
			  for (float z=-1; z<1; z+=0.04f)
				{
				  float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
					Vector3d p(x,y,z);
				  if ( d >= 0 )
					  callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00);
				  else
					  callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000);
				}
			}
		}
	}

	if ( 1 )
	{
		// ok..now we are going to 'split' all of the input triangles against this plane!
		const unsigned int *source = indices;
		for (unsigned int i=0; i<tcount; i++)
		{
			unsigned int i1 = *source++;
			unsigned int i2 = *source++;
			unsigned int i3 = *source++;

			FaceTri t(vertices, i1, i2, i3 );

			Vector3d front[4];
			Vector3d back[4];

			unsigned int fcount=0;
			unsigned int bcount=0;

			PlaneTriResult result;

		  result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );

			if( fcount > 4 || bcount > 4 )
			{
		    result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
			}

			switch ( result )
			{
				case PTR_FRONT:

					assert( fcount == 3 );

          if ( showmesh )
            callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00 );

          #if MAKE_MESH

          addTri( vfront, ifront, front[0], front[1], front[2] );


          #endif

					break;
				case PTR_BACK:
					assert( bcount == 3 );

          if ( showmesh )
  					callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00 );

          #if MAKE_MESH

          addTri( vback, iback, back[0], back[1], back[2] );

          #endif

					break;
				case PTR_SPLIT:

					assert( fcount >= 3 && fcount <= 4);
					assert( bcount >= 3 && bcount <= 4);

          #if MAKE_MESH

          addTri( vfront, ifront, front[0], front[1], front[2] );
          addTri( vback, iback, back[0], back[1], back[2] );


          if ( fcount == 4 )
          {
            addTri( vfront, ifront, front[0], front[2], front[3] );
          }

          if ( bcount == 4  )
          {
            addTri( vback, iback, back[0], back[2], back[3] );
          }

          #endif

          if ( showmesh )
          {
  					callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000 );
  					callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000 );

  					if ( fcount == 4 )
  					{
  						callback->ConvexDebugTri( front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000 );
  					}
  					if ( bcount == 4 )
  					{
  						callback->ConvexDebugTri( back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000 );
  					}
  				}

					break;
			}
		}

		unsigned int fsize = ifront.size()/3;
		unsigned int bsize = iback.size()/3;

    // ok... here we recursively call
    if ( ifront.size() )
    {
      unsigned int vcount   = Vl_getVcount(vfront);
      const float *vertices = Vl_getVertices(vfront);
      unsigned int tcount   = ifront.size()/3;

      calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1);

    }

    ifront.clear();

    Vl_releaseVertexLookup(vfront);

    if ( iback.size() )
    {
      unsigned int vcount   = Vl_getVcount(vback);
      const float *vertices = Vl_getVertices(vback);
      unsigned int tcount   = iback.size()/3;

      calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1);

    }

    iback.clear();
    Vl_releaseVertexLookup(vback);

	}
}
Exemple #8
0
	float getVolume(ConvexDecompInterface *callback) const
	{
		unsigned int indices[8*3];


    unsigned int tcount = 0;

    addTri(indices,0,1,2,tcount);
    addTri(indices,3,4,5,tcount);

    addTri(indices,0,3,4,tcount);
    addTri(indices,0,4,1,tcount);

    addTri(indices,1,4,5,tcount);
    addTri(indices,1,5,2,tcount);

    addTri(indices,0,3,5,tcount);
    addTri(indices,0,5,2,tcount);

    const float *vertices = mP1.Ptr();

		if ( callback )
		{
			unsigned int color = getDebugColor();

#if 0
  		Vector3d d1 = mNear1;
  		Vector3d d2 = mNear2;
	  	Vector3d d3 = mNear3;

  		callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
  		callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
  		callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
  		callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
  		callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
  		callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);

  		callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(),  d1.Ptr(),0x00FF00);
  		callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(),  d2.Ptr(),0x00FF00);
  		callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(),  d3.Ptr(),0x00FF00);

#else
			for (unsigned int i=0; i<tcount; i++)
			{
				unsigned int i1 = indices[i*3+0];
				unsigned int i2 = indices[i*3+1];
				unsigned int i3 = indices[i*3+2];

				const float *p1 = &vertices[ i1*3 ];
				const float *p2 = &vertices[ i2*3 ];
				const float *p3 = &vertices[ i3*3 ];

				callback->ConvexDebugTri(p1,p2,p3,color);

			}
#endif
		}

		float v = computeMeshVolume(mP1.Ptr(), tcount, indices );

		return v;

	}
Exemple #9
0
//
// Refine a grid into a TIN_TILgE with error < e
//
void refineTile(TIN_TILE *tt, double e, short delaunay, short useNodata) {  
  BOOL complete;    // is maxE < e
  complete = 0;
  TRIANGLE *t1, *t2, *t3, *s;

  int refineCount = 0;

  // Read points for initial two triangles into a file
  initTilePoints(tt,e,useNodata);
  
  // While there still is a triangle with max error > e
  while(PQ_extractMin(tt->pq, &s)){

    // Triangles should no longer be marked for deletion since they
    // are being deleted from the PQ
    if(s->p1p2 == NULL && s->p1p3 == NULL && s->p2p3 == NULL){
      printf(strcat("skipping deleted triangle: err=",ELEV_TYPE_PRINT_CHAR),
	     s->maxErrorValue);
      fflush(stdout);
      assert(0);
      removeTri(s);
    }

    assert(s); 
    refineCount++;

    // malloc the point with max error as it will become a corner
    R_POINT* maxError = (R_POINT*)malloc(sizeof(R_POINT));
    assert(maxError);	
    maxError->x = s->maxE->x;
    maxError->y = s->maxE->y;
    maxError->z = s->maxE->z;

    // Add point to the correct point pointer array
    assert(tt->bPointsCount < tt->ncols && 
	   tt->rPointsCount < tt->nrows && 
	   tt->bPointsCount < (tt->ncols * tt->nrows)-(tt->ncols + tt->nrows));
    if(maxError->x == (tt->iOffset + tt->nrows-1) ){
      tt->bPoints[tt->bPointsCount]=maxError;
      tt->bPointsCount++;
    }
    else if(maxError->y == (tt->jOffset + tt->ncols-1) ){
      tt->rPoints[tt->rPointsCount]=maxError;
      tt->rPointsCount++;
    }
    else{
      tt->points[tt->pointsCount]=maxError;
      tt->pointsCount++;
    }

    // Debug - print the point being added
#ifdef REFINE_DEBUG 
    {
      TRIANGLE *snext;
      R_POINT err = findError(s->maxE->x, s->maxE->y, s->maxE->z, s); 
      printf("Point (%6d,%6d,%6d) error=%10ld \t", 
	     s->maxE->x, s->maxE->y, s->maxE->z, err );
      printTriangleCoords(s);
      fflush(stdout);

      if(err != s->maxErrorValue){
	printf("Died err= %ld maxE= %ld \n",err,s->maxErrorValue);
	exit(1);
      }

      PQ_min(tt->pq, &snext); 
      assert(s->maxErrorValue >= snext->maxErrorValue); 
    }
#endif
    // Check for collinear points. We make the valid assumption that
    // MaxE cannot be collinear with > 1 tri
    int area12,area13,area23;

    area12 = areaSign(s->p1, s->p2, maxError);
    area13 = areaSign(s->p1, maxError, s->p3);
    area23 = areaSign(maxError, s->p2, s->p3);

    // If p1 p2 is collinear with MaxE
    if (!area12){
      fixCollinear(s->p1,s->p2,s->p3,s,e,maxError,tt,delaunay);
      tt->numTris++;
    }
    else if (!area13){
      fixCollinear(s->p1,s->p3,s->p2,s,e,maxError,tt,delaunay);
      tt->numTris++;
    }
    else if (!area23){
      fixCollinear(s->p2,s->p3,s->p1,s,e,maxError,tt,delaunay);
      tt->numTris++;
    }
    else {
      // add three new triangles
      t1 = addTri(tt,s->p1, s->p2, maxError,s->p1p2,NULL,NULL);
      t2 = addTri(tt,s->p1, maxError, s->p3,t1,s->p1p3,NULL);
      t3 = addTri(tt,maxError, s->p2, s->p3,t1,t2,s->p2p3);
      DEBUG{triangleCheck(s,t1,t2,t3);}

      tt->numTris += 2;

      // create poinlists from the original tri (this will yeild the max error)
      distrPoints(t1,t2,t3,s,NULL,e,tt);
      DEBUG{checkPointList(t1);checkPointList(t2);checkPointList(t3);}  

      // Enforce delaunay on three new edges of the new triangles if
      // specified
      if(delaunay){
	// we enforce on the edge that does not have maxE as an
	// endpoint, so the 4th argument to enforceDelaunay should
	// always be the maxE point to s for that particular tri
	enforceDelaunay(t1,t1->p1,t1->p2,t1->p3,e,tt);
	enforceDelaunay(t2,t2->p1,t2->p3,t2->p2,e,tt);
	enforceDelaunay(t3,t3->p2,t3->p3,t3->p1,e,tt);
      }
    }
    
    // remove original tri
    removeTri(s);
    //DEBUG{printTin(tt);}

    extern int displayValid;
    displayValid = 0;

  } 
  s = tt->t;
 
  // The number of points added is equal to the number of refine loops
  tt->numPoints += refineCount;
  
  /* The number of points should be equal to the sum of all points
     arrays (one center and possible 4 boundary). Since the arrays
     have overlap of corner points we subtract the overlaps */
  int pts = 0;
  pts = tt->pointsCount + tt->rPointsCount + tt->bPointsCount - 1;
  if(tt->top != NULL)
    pts += tt->top->bPointsCount - 2;
  if(tt->left != NULL)
    pts += tt->left->rPointsCount - 2;
  //assert(tt->numPoints == pts); fix

  // Sort the point arrays for future use and binary searching
  qsort(tt->rPoints,tt->rPointsCount,sizeof(R_POINT*),(void *)QS_compPoints);
  qsort(tt->bPoints,tt->bPointsCount,sizeof(R_POINT*),(void *)QS_compPoints);
  qsort(tt->points,tt->pointsCount,sizeof(R_POINT*),(void *)QS_compPoints);

  // We are done with the pq
  PQ_free(tt->pq);

}
Exemple #10
0
//
// Swap the common edge between two triangles t1 and t2. The common
// edge should always be edge ac, abc are part of t1 and acd are part
// of t2.
//
void edgeSwap(TRIANGLE *t1, TRIANGLE *t2, 
	      R_POINT *a, R_POINT *b, R_POINT *c, R_POINT *d,
	      double e, TIN_TILE *tt){

  // Common edge must be ac
  assert(isEndPoint(t1,a) && isEndPoint(t1,b) && isEndPoint(t1,c) && 
	 isEndPoint(t2,a) && isEndPoint(t2,c) && isEndPoint(t2,d));

  assert(a != b && a != c && a != d && b != c && b != d && c != d);

  assert(t1 != t2);
  
  // Add the two new triangles with the swapped edge 
  TRIANGLE *tn1, *tn2;
  tn1 = addTri(tt,a, b, d,whichTri(t1,a,b,tt),whichTri(t2,a,d,tt),NULL);
  tn2 = addTri(tt,c, b, d,whichTri(t1,c,b,tt),whichTri(t2,c,d,tt),tn1);
  
  assert(isEndPoint(tn1,a) && isEndPoint(tn1,b) && isEndPoint(tn1,d) && 
	 isEndPoint(tn2,b) && isEndPoint(tn2,c) && isEndPoint(tn2,d));

  assert(tn1->p2p3 == tn2 && tn2->p2p3 == tn1);

 
  if(tn1->p1p2 != NULL)
    assert(whichTri(tn1->p1p2,a,b,tt) == tn1);
  if(tn1->p1p3 != NULL)
    assert(whichTri(tn1->p1p3,a,d,tt) == tn1);
  if(tn2->p1p2 != NULL)
    assert(whichTri(tn2->p1p2,c,b,tt) == tn2);
  if(tn2->p1p3 != NULL)
    assert(whichTri(tn2->p1p3,c,d,tt) == tn2);

  // Debug
  DEBUG{
  printf("EdgeSwap: \n");
  printTriangle(t1);
  printTriangle(t2);
  printTriangle(tn1);
  printTriangle(tn2);
  } 

  // Distribute point list from t1 and t2 to tn1 and tn2. Distribute
  // points requires that the fourth argument (s) be a valid triangle
  // with a point list so we must check that t1 and t2 are not already
  // done and thus do not have a point list. If at least one does then
  // call distribute points with s = the trinagle with the valid point
  // list. If both are done then the newly created triangles are done
  // tooand need to be marked accordingly
  if(t1->maxE != DONE && t2->maxE != DONE)
    distrPoints(tn1,tn2,NULL,t1,t2,e,tt);
  else if(t1->maxE != DONE){
    distrPoints(tn1,tn2,NULL,t1,NULL,e,tt);
  }
  else if(t2->maxE != DONE){
    distrPoints(tn1,tn2,NULL,t2,NULL,e,tt);
  }
  else{
    tn1->maxE = tn2->maxE = DONE;
    tn1->points = tn2->points= NULL;
  }

  // Update the corner if the corner is being swapped. Distrpoints
  // will not always catch this so it must be done here
  if(t1 == tt->t || t2 == tt->t){
    updateTinTileCorner(tt,tn1,tn2,NULL);    
  }

  // mark triangles for deletion from the PQ
  t1->p1p2 = t1->p1p3 = t1->p2p3 = NULL;
  t2->p1p2 = t2->p1p3 = t2->p2p3 = NULL;
  PQ_delete(tt->pq,t1->pqIndex);
  PQ_delete(tt->pq,t2->pqIndex);
  removeTri(t1);
  removeTri(t2);

  DEBUG{checkPointList(tn1); checkPointList(tn2);}

  // We have created two different triangles, we need to check
  // delaunay on their 2 edges
  enforceDelaunay(tn1,a,d,b,e,tt);
  enforceDelaunay(tn2,c,d,b,e,tt);

}
Exemple #11
0
//
// Initialize TIN structure, returns a pointer to lower left tri. This
// will not initialize the points in the triangles, just the two
// staring triangles. Points will be added later in refinement.
//
TIN_TILE* initTinTile(TIN_TILE *tt,TIN_TILE *leftTile, TIN_TILE *topTile,
		      TRIANGLE *leftTri, TRIANGLE *topTri, 
		      R_POINT *nw, R_POINT *sw, R_POINT *ne, int iOffset, 
		      int jOffset, short useNodata, TIN *tin){

  // Create a pointer to the lower left tri in the tin
  TRIANGLE *first, *second;

  // Create a PQ of the error of the triangles. We want to give the PQ
  // an initial size which is the lowest power of 2 which will fit all
  // the triangles in a tile (3 * numPoints in tile) = (3 * tin->tl *tin->tl)
  //
  // If TL is larger than 4000 then we are probably running untiled
  // and we should start the pq small and just let it grow as needed
  unsigned int initPQSize = 1048576;
  if(tin->tl < 4000)
    initPQSize = (unsigned int)	pow(2,ceil(log10(3 * tin->tl * tin->tl)
					   /log10(2)));
  tt->pq = PQ_initialize( initPQSize );


  // Set Offset
  tt->iOffset = iOffset;
  tt->jOffset = jOffset;
  
  // Set neighbors
  tt->top = topTile;
  tt->left = leftTile;

  // Number of triangles and points
  tt->numTris = 2;
  tt->numPoints = 4;
  
  // Point neighbors to me
  pointNeighborTileTo(tt,DIR_BOTTOM,topTile);
  pointNeighborTileTo(tt,DIR_RIGHT,leftTile);

  // We need to create at least 1 and up to 4 corner points for the
  // intial triangulation. They have incorrect z value for now and
  // will be updated later
  if(nw == NULL){
    nw = (R_POINT*)malloc(sizeof(R_POINT));
    nw->x=iOffset;
    nw->y=jOffset;
    nw->z=0;
  }
  if(ne == NULL){
    ne = (R_POINT*)malloc(sizeof(R_POINT));
    ne->x=iOffset;
    ne->y=tt->ncols-1+jOffset;
    ne->z=0;
  }
  if(sw == NULL){
    sw = (R_POINT*)malloc(sizeof(R_POINT));
    sw->x=tt->nrows-1+iOffset;
    sw->y=jOffset;
    sw->z=0;
  }
  
  R_POINT *se = (R_POINT*)malloc(sizeof(R_POINT));
  se->x=tt->nrows-1+iOffset;
  se->y=tt->ncols-1+jOffset;
  se->z=0;

  // Store the 4 corner points for later reference
  tt->nw = nw;
  tt->ne = ne;
  tt->sw = sw;
  tt->se = se;

  assert(pointOnBoundary(nw,tt) && pointOnBoundary(ne,tt) &&
	 pointOnBoundary(sw,tt) && pointOnBoundary(se,tt) );


  // Create the first two triangles. 
  tt->t = first = addTri(tt,nw,sw,se,leftTri,NULL,NULL);
  second = addTri(tt,nw,ne,se,topTri,first,NULL);
  assert(tt->t);
  assert(first);
  assert(second);

  // Point the tins lower left corner to sw
  tt->v = sw;
  
  // Lower left edge nw-sw gets stored in tin
  tt->e.t1 = NULL;
  tt->e.t2 = NULL;
  tt->e.p1 = nw;
  tt->e.p2 = sw;
  tt->e.type = IN;

  return tt;
}
Exemple #12
0
//
// Add the points two the two initial triangles of a Tin tile from
// file. Also add points from neighbor boundary arrays to the
// triangulation to have boundary consistancy
//
TIN_TILE *initTilePoints(TIN_TILE *tt, double e, short useNodata){

  // First two tris
  TRIANGLE *first = tt->t;
  TRIANGLE *second = tt->t->p1p3;

  // Get back to the beginning of the tile data file
  rewind(tt->gridFile);

  // Now build list of points in the triangle
  // Create a dummy tail for both point lists
  first->points = Q_init();
  second->points = Q_init();
  first->maxE = DONE;
  second->maxE = DONE;
  
  // Build the two point lists
  register int row, col;
  ELEV_TYPE maxE_first=0;
  ELEV_TYPE maxE_second=0;
  ELEV_TYPE tempE = 0;
  
  R_POINT temp;
  
  // iterate through all points and distribute them to the 
  // two triangles
  for(row=0;row<tt->nrows;row++) {
    temp.x=row+tt->iOffset;
    for(col=0;col<tt->ncols;col++) {
      temp.y=col+tt->jOffset;
      fread(&temp.z,sizeof(ELEV_TYPE), 1, tt->gridFile);
      // Only set Z values for corner points since they already exist
      if(row==0 && col==0){
	tt->nw->z = temp.z;
	continue;
      }
      if(row==0 && col==tt->ncols-1){
	tt->ne->z = temp.z;
	continue;
      }
      if(row==tt->nrows-1 && col==tt->ncols-1){
	tt->se->z = temp.z;
	continue;
      } 
      if(row==tt->nrows-1 && col==0){
	tt->sw->z = temp.z;
	continue;
      }	
      //Ignore edge points if internal tile
      if(tt->iOffset != 0 && row == 0)
	continue;
      if(tt->jOffset != 0 && col == 0)
	continue;
      
      //Skip nodata or change it to min-1
      if(temp.z == tt->nodata){
	if(!useNodata)
      	  continue;
	else
	  temp.z = tt->min-1;
      }

      // Add to the first triangle's list
      if(inTri2D(first->p1, first->p2, first->p3, &temp)) {
	
	Q_insert_elem_head(first->points, temp);

	//Update max error
	tempE = findError(temp.x,temp.y,temp.z,first);
	if (tempE > maxE_first) {
	  maxE_first = tempE;
	  assert(Q_first(first->points));
	  // store pointer to triangle w/ max err
	  first->maxE = &Q_first(first->points)->e;
	  first->maxErrorValue = tempE;
	}
      }
      // Add to the second triangle's list
      else {

	assert(inTri2D(second->p1, second->p2, second->p3, &temp));

	Q_insert_elem_head(second->points, temp);

	//Update max error
	tempE = findError(temp.x,temp.y,temp.z,second);
	if (tempE > maxE_second) {
	  maxE_second = tempE;
	  assert(Q_first(second->points));
	  // store pointer to triangle w/ max err
	  second->maxE = &Q_first(second->points)->e; 
	  second->maxErrorValue = tempE;
	}

      }

    }//for col
  }//for row
  //end distribute points among initial triangles

  DEBUG {checkPointList(first); checkPointList(second);}

  // First triangle has no points with error > e, mark as done
  if (first->maxE == DONE){
    Q_free_queue(first->points);
    first->points = NULL;
    first->maxErrorValue = 0;
  }
  // Insert max error point into the PQ
  else
    PQ_insert(tt->pq,first);

  // Second triangle has no points with error > e, mark as done
  if (second->maxE == DONE){
    Q_free_queue(second->points);
    second->points = NULL;
    second->maxErrorValue = 0;
  }
  // Insert max error point into the PQ
  else
    PQ_insert(tt->pq,second);


  // Initialize point pointer arrays
  // At most points can have (tl*tl)-2*tl points in it
  // At most bPoints and rPoints can have tl points
  tt->points = (R_POINT **)malloc( ((tt->nrows * tt->ncols) - 
				  (tt->nrows + tt->ncols)) * 
				 sizeof(R_POINT*));
  tt->bPoints = (R_POINT **)malloc( tt->ncols * sizeof(R_POINT*));
  tt->rPoints = (R_POINT **)malloc( tt->nrows * sizeof(R_POINT*));  

  // Add points to point pointer array
  tt->points[0]=tt->nw;//nw
  tt->bPoints[0]=tt->sw;//sw
  tt->bPoints[1]=tt->se;//se
  tt->rPoints[0]=tt->ne;//ne
  tt->rPoints[1]=tt->se;//se
  tt->pointsCount = 1;
  tt->bPointsCount = 2;
  tt->rPointsCount = 2;

  //
  // Add boundary points to the triangulation
  //
  int i;
  COORD_TYPE prevX = 0,prevY = 0;
  TRIANGLE *t1,*t2, *s, *sp;
  s = tt->t;
  sp = tt->t->p1p3;

  if(tt->left != NULL){
    // The first & last point in this array are corner points for this
    // tile so we ignore them
 
    for(i = 1; i < tt->left->rPointsCount-1; i++){
      assert(s && tt->pq && tt->left->rPoints[i]);
      assert(prevX <=  tt->left->rPoints[i]->x &&
	     prevY <=  tt->left->rPoints[i]->y);
      assert(tt->left->rPoints[i] != tt->nw &&
	     tt->left->rPoints[i] != tt->ne &&
	     tt->left->rPoints[i] != tt->sw &&
	     tt->left->rPoints[i] != tt->se);
      
      // add 2 tris in s
      t1 = addTri(tt, s->p1, tt->left->rPoints[i], s->p3,
		  NULL,whichTri(s,s->p1,s->p3,tt),NULL);
      assert(t1);
      t2 = addTri(tt, tt->left->rPoints[i], s->p2, s->p3,
		  NULL,t1,whichTri(s,s->p2,s->p3,tt));
      assert(t2);
      // Verify that t1 and t2 are really inside s
      triangleCheck(s,t1,t2,NULL);
      // Distribute points in the 2 triangles
      if(s->maxE != DONE){
	s->p1p2 = s->p1p3 = s->p2p3 = NULL;
	distrPoints(t1,t2,NULL,s,NULL,e,tt);
	//Mark triangle s for deletion from pq before distrpoints so we
	//can include its maxE in the newly created triangle
	
	PQ_delete(tt->pq,s->pqIndex);
      }
      else{
	// Since distrpoints normally fixes corner we need to do it here
	if(s == tt->t){
	  updateTinTileCorner(tt,t1,t2,NULL);
	}
	t1->maxE = t2->maxE = DONE;
	t1->points = t2->points = NULL;
      }
      
      
      removeTri(s);
      tt->numTris++;
      tt->numPoints++;
      // Now split the next lowest boundary triangle
      s = t2;
      
      // Should we enforce Delaunay here?

      prevX = tt->left->rPoints[i]->x;
      prevY = tt->left->rPoints[i]->y;
    }
    
  }
  
  if(tt->top != NULL){
    // The first & last point in this array are corner points for this
    // tile so we ignore them
    s = sp;
    prevX = prevY = 0;
    for(i = 1; i < tt->top->bPointsCount-1; i++){
      assert(s && tt->pq && tt->top->bPoints[i]);
      assert(prevX <=  tt->top->bPoints[i]->x &&
	     prevY <=  tt->top->bPoints[i]->y);
      
      // add 2 tris in s
      t1 = addTri(tt, s->p1, tt->top->bPoints[i], s->p3,
		  NULL,whichTri(s,s->p1,s->p3,tt),NULL);
      assert(t1);
      t2 = addTri(tt, tt->top->bPoints[i], s->p2, s->p3,
		  NULL,t1,whichTri(s,s->p2,s->p3,tt));
      assert(t2);
      // Verify that t1 and t2 are really inside s
      triangleCheck(s,t1,t2,NULL);
      // Distribute points in the 2 triangles
      if(s->maxE != DONE){
	distrPoints(t1,t2,NULL,s,NULL,e,tt);
	//Mark triangle sp for deletion from pq before distrpoints so we
	//can include its maxE in the newly created triangle
	s->p1p2 = s->p1p3 = s->p2p3 = NULL;
	PQ_delete(tt->pq,s->pqIndex);

      }
      else{
	// Since distrpoints normally fixes corner we need to do it here
	if(s == tt->t){
	  updateTinTileCorner(tt,t1,t2,NULL);
	}
	t1->maxE = t2->maxE = DONE;
	t1->points = t2->points = NULL;
      }
      
      
      removeTri(s);
      tt->numTris++;
      tt->numPoints++;
      // Now split the next lowest boundary triangle
      s = t2;
      
      // Should we enforce Delaunay here?
      
      prevX = tt->top->bPoints[i]->x;
      prevY = tt->top->bPoints[i]->y;
    }
    
  }
  return tt;
}
Exemple #13
0
//
// Add triangles and distribute points when there are two collinear
// triangles. Assumes that maxE is on line pa pb
//
void fixCollinear(R_POINT *pa, R_POINT *pb, R_POINT *pc, TRIANGLE* s, double e,
		  R_POINT *maxError, TIN_TILE *tt, short delaunay){

  assert(s && tt->pq && maxError);
  TRIANGLE *sp, *t1, *t2, *t3, *t4;
  
  // add 2 tris in s
  t1 = addTri(tt,pa, maxError, pc,NULL,whichTri(s,pa,pc,tt),NULL);
  assert(t1);
  t2 = addTri(tt,maxError, pc, pb,t1,NULL,whichTri(s,pb,pc,tt));
  assert(t2);
  DEBUG{triangleCheck(s,t1,t2,NULL);}
  
  // Distribute points in the 2 triangles
  distrPoints(t1,t2,NULL,s,NULL,e,tt);

  DEBUG{checkPointList(t1); checkPointList(t2);}  

  // Find other triangle Note: there may not be another triangle if s
  // is on the edge
  sp = whichTri(s,pa,pb,tt);
  
  // If there is a triangle on the other side of the collinear edge
  // then we need to split that triangle into two
  if(sp != NULL){

    // Find the unknown point of the triangle on the other side of the line
    R_POINT *pd;
    pd = findThirdPoint(sp->p1,sp->p2,sp->p3,pa,pb);
    assert(pd);

    // If this triangle is in the other tile we need to make sure we
    // work with that tile
    TIN_TILE *ttn;
    ttn = whichTileTri(pa,pb,pd,tt);  
    assert(ttn);

    assert(pointInTile(pd,ttn));
    
    // add 2 tris adjacent to s on pa pb
    t3 = addTri(ttn,pa,maxError,pd,t1,whichTri(sp,pd,pa,ttn),NULL);
    assert(t3);
    t4 = addTri(ttn,pb,maxError,pd,t2,whichTri(sp,pd,pb,ttn),t3);
    assert(t4);
    DEBUG{triangleCheck(sp,t3,t4,NULL);}
    
    // 1 more tri 
    ttn->numTris++;


    //If this triangle was already "done" meaning it has no more
    //points in it's point list > MaxE then we don't distribute points
    //because sp has no point list
    if(sp->maxE != DONE){
      distrPoints(t3,t4,NULL,sp,NULL,e,ttn);
      //Mark triangle sp for deletion from pq before distrpoints so we
      //can include its maxE in the newly created triangle
      sp->p1p2 = sp->p1p3 = sp->p2p3 = NULL;
      PQ_delete(ttn->pq,sp->pqIndex);
    }
    else{
      // Since distrpoints normally fixes corner we need to do it here
      if(sp == tt->t){
	updateTinTileCorner(ttn,t3,t4,NULL);    
      }
      t3->maxE = t4->maxE = DONE;
      t3->points = t4->points = NULL;
    }
    DEBUG{checkPointList(t3); checkPointList(t4);}
    
    
    removeTri(sp);
    

    // Enforce delaunay on two new edges of the new triangles if
    // specified
    if(delaunay){
      // we enforce on the edge that does not have maxE as an
      // endpoint, so the 4th argument to enforceDelaunay should
      // always be the maxE point to s for that particular tri
      enforceDelaunay(t1,t1->p1,t1->p3,t1->p2,e,tt);
      enforceDelaunay(t2,t2->p2,t2->p3,t2->p1,e,tt);
      if(ttn == tt){
	enforceDelaunay(t3,t3->p1,t3->p3,t3->p2,e,ttn);
	enforceDelaunay(t4,t4->p1,t4->p3,t4->p2,e,ttn);
      }
    }
  }
/* mkPoly:
 * Construct simple polygon from shortest path from t to s in g.
 * dad gives the indices of the triangles on path.
 * sx used to store index of s in points.
 * index of t is always 0
 */
static tripoly_t *mkPoly(router_t * rtr, int *dad, int s, int t,
			 pointf p_s, pointf p_t, int *sx)
{
    tripoly_t *ps;
    int nxt;
    ipair p;
    int nt = 0;
    side_t *side1;
    side_t *side2;
    int i, idx;
    int cnt1 = 0;
    int cnt2 = 0;
    pointf *pts;
    pointf *pps;
    /* maps vertex index used in router_t to vertex index used in tripoly */
    Dt_t *vmap;
    tri **trim;

    /* count number of triangles in path */
    for (nxt = dad[t]; nxt != s; nxt = dad[nxt])
	nt++;

    side1 = N_NEW(nt + 4, side_t);
    side2 = N_NEW(nt + 4, side_t);

    nxt = dad[t];
    p = edgeToSeg(rtr->tg, nxt, t);
    side1[cnt1].ts = addTri(-1, p.j, NULL);
    side1[cnt1++].v = p.i;
    side2[cnt2].ts = addTri(-1, p.i, NULL);
    side2[cnt2++].v = p.j;

    t = nxt;
    for (nxt = dad[t]; nxt >= 0; nxt = dad[nxt]) {
	p = edgeToSeg(rtr->tg, t, nxt);
	if (p.i == side1[cnt1 - 1].v) {
	    side1[cnt1 - 1].ts =
		addTri(side2[cnt2 - 1].v, p.j, side1[cnt1 - 1].ts);
	    side2[cnt2 - 1].ts =
		addTri(side1[cnt1 - 1].v, p.j, side2[cnt2 - 1].ts);
	    side2[cnt2].ts =
		addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v, NULL);
	    side2[cnt2++].v = p.j;
	} else if (p.i == side2[cnt2 - 1].v) {
	    side1[cnt1 - 1].ts =
		addTri(side2[cnt2 - 1].v, p.j, side1[cnt1 - 1].ts);
	    side2[cnt2 - 1].ts =
		addTri(side1[cnt1 - 1].v, p.j, side2[cnt2 - 1].ts);
	    side1[cnt1].ts =
		addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v, NULL);
	    side1[cnt1++].v = p.j;
	} else if (p.j == side1[cnt1 - 1].v) {
	    side1[cnt1 - 1].ts =
		addTri(side2[cnt2 - 1].v, p.i, side1[cnt1 - 1].ts);
	    side2[cnt2 - 1].ts =
		addTri(side1[cnt1 - 1].v, p.i, side2[cnt2 - 1].ts);
	    side2[cnt2].ts =
		addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v, NULL);
	    side2[cnt2++].v = p.i;
	} else {
	    side1[cnt1 - 1].ts =
		addTri(side2[cnt2 - 1].v, p.i, side1[cnt1 - 1].ts);
	    side2[cnt2 - 1].ts =
		addTri(side1[cnt1 - 1].v, p.i, side2[cnt2 - 1].ts);
	    side1[cnt1].ts =
		addTri(side2[cnt2 - 1].v, side1[cnt1 - 1].v, NULL);
	    side1[cnt1++].v = p.i;
	}
	t = nxt;
    }
    side1[cnt1 - 1].ts = addTri(-2, side2[cnt2 - 1].v, side1[cnt1 - 1].ts);
    side2[cnt2 - 1].ts = addTri(-2, side1[cnt1 - 1].v, side2[cnt2 - 1].ts);

    /* store points in pts starting with t in 0, 
     * then side1, then s, then side2 
     */
    vmap = dtopen(&ipairdisc, Dtoset);
    vmapAdd(vmap, -1, 0);
    vmapAdd(vmap, -2, cnt1 + 1);
    pps = pts = N_GNEW(nt + 4, pointf);
    trim = N_NEW(nt + 4, tri *);
    *pps++ = p_t;
    idx = 1;
    for (i = 0; i < cnt1; i++) {
	vmapAdd(vmap, side1[i].v, idx);
	*pps++ = rtr->ps[side1[i].v];
	trim[idx++] = side1[i].ts;
    }
    *pps++ = p_s;
    idx++;
    for (i = cnt2 - 1; i >= 0; i--) {
	vmapAdd(vmap, side2[i].v, idx);
	*pps++ = rtr->ps[side2[i].v];
	trim[idx++] = side2[i].ts;
    }

    for (i = 0; i < nt + 4; i++) {
	mapTri(vmap, trim[i]);
    }

    ps = NEW(tripoly_t);
    ps->poly.pn = nt + 4;  /* nt triangles gives nt+2 points plus s and t */
    ps->poly.ps = pts;
    ps->triMap = trim;

    free (side1);
    free (side2);
    dtclose(vmap);
    *sx = cnt1 + 1;		/* index of s in ps */
    return ps;
}