Advanced Mesh Generation

Advanced Mesh Generation

Standard Delaunay mesh generation inside polygons has already been introduced in the post example6-mesh-generation. The present article describes advanced mesh generation for users who need more control over the mesh generation process. Advanced meshing is demonstrated together with Fade2.5D here but exists also in Fade2D.

The initial zone

The source code snippet below creates a Zone2 object. It defines an area in a triangulation that we will later fill with triangles. The used helper functions createSimpleZone(..) and highlightTriangles(..) are printed at the end of this article.

void initialZone()
{
	Fade_2D dt;
	Zone2* pZone=createSimpleZone(dt);
	highlightTriangles(dt,pZone,"initialZone.ps");
}
Initial zone without mesh generation

Initial zone


The polygon above will be remeshed in different ways now.

Mesh generator with default parameters

The mesh generation algorithm uses the class MeshGenParams as container for its parameters. These parameters have default values which are useful for the average case. These can (but do not need to) be changed. First, let’s use the class with all default values:

void strategy_default()
{
	Fade_2D dt;
	Zone2* pZone=createSimpleZone(dt);
	MeshGenParams params(pZone);
	dt.refineAdvanced(&params);
	highlightTriangles(dt,pZone,"default.ps");
}

Mesh generation inside a polygon with the preset parameters

Polygon meshing with default parameters

The Parameter growFactor

One parameter in the MeshGenParams class is growFactor. It is used to limit the growth of adjacent triangles in a mesh. More precisely, for any two adjacent triangles t0 and t1, where t0 is the larger one, area(t0)/area(t1)<growFactor. The default value is DBL_MAX (meaning the growth is not restricted). Below we set the growFactor to 3.0 to get a smoother transition from small to large triangles.

void strategy_growFactor()
{
	Fade_2D dt;
	Zone2* pZone=createSimpleZone(dt);

	MeshGenParams params(pZone);
	params.growFactor=3.0;
	dt.refineAdvanced(&params);
	highlightTriangles(dt,pZone,"growFactor.ps");
}

Mesh generation with limited growth

Mesh generation with limited growth

Parameter maxEdgeLength

Out of the several properties that can be controlled via MeshGenParams, the maximum edge length of triangles is important. Use the maxEdgeLength parameter, default: DBL_MAX (no restriction), to limit the length of the edges in the generated mesh:

void strategy_maxLength()
{
	Fade_2D dt;
	Zone2* pZone=createSimpleZone(dt);
	MeshGenParams params(pZone);
	params.maxEdgeLength=10.0;
	dt.refineAdvanced(&params);
	highlightTriangles(dt,pZone,"maxLength.ps");
}

Mesh generation with limited edge length

Mesh generation with limited edge length

Parameters gridLength and gridVector

Grid Meshing is a hybrid approach: Large areas are meshed with grid points while border areas and narrow strips are meshed using classic Delaunay techniques. To activate Grid Meshing set the gridLength parameter to a positive value. This value will then automatically be adapted such that the grid fits the shape better. The grid is by default axis aligned. You can change the alignment using the parameter gridVector.

void strategy_gridMeshing()
{
        Fade_2D dt;
        Zone2* pZone=createSimpleZone(dt);
        MeshGenParams params(pZone);
        params.gridLength=3.0;
        params.gridVector=Vector2(1.0,0.0,0.0);
        // params.gridVector=Vector2(1.0,0.3,0.0);

        dt.refineAdvanced(&params);
        highlightTriangles(dt,pZone,"gridMeshing.ps");
}
Grid Meshing

Grid Meshing with an axis aligned grid


Grid Meshing Angle

Grid Mesh aligned to the Vector2(1.0,0.3)

Callback methods – create a custom parameters class

It is sometimes desirable that your program can directly control the local mesh density. For this purpose derive a class from MeshGenParams and override double getMaxTriangleArea(Triangle* pT) or double getMaxEdgeLength(Triangle* pT) with your own code. The example code below derives a class CustomParameters and overrides getMaxTriangleArea(..) to enforce small triangles for all coordinates where x<20 and y<40:

class CustomParameters:public MeshGenParams
{
public:
        CustomParameters(Zone2* pZone):MeshGenParams(pZone)
        {
        }
        double getMaxTriangleArea(Triangle2* pT)
        {
                Point2 barycenter(pT->getBarycenter());
                if(barycenter.x()<20 && barycenter.y()<40)
                {
                        // Dense meshing in the lower left corner
                        return 0.5;
                }
                else
                {
                        // No density restriction otherwise
                        return DBL_MAX;
                }
        }
};

// Uses CustomParameters with a custom getMaxTriangleArea method
void strategy_customParameters()
{
	Fade_2D dt;
	Zone2* pZone=createSimpleZone(dt);

	CustomParameters params(pZone);
	dt.refineAdvanced(&params);
	highlightTriangles(dt,pZone,"customParameters.ps");
}

Controlling the local mesh density

Controlling the local mesh density

Height guide triangulations in 2.5D

When a 2.5D triangulation is refined, which z-values shall be assigned for the heights of the new points? By default the z-values are computed from the existing triangles that will be subdivided. Alternatively you might be in a situation where a more accurate height is known because a triangulation with a higher resolution is available. In this case set this triangulation as height guide to determine the new z-values. The code below creates a simple zone (with all z-values 0) like before. Then it creates a second triangulation called dt_guide which covers (at least) the same area. Its heights are partly different from 0. Then, when the zone is remeshed, all newly created points retrieve their z-values from the height guide triangulation.

void strategy_heightGuide()
{
Fade_2D dt;
Zone2* pZoneSimple=createSimpleZone(dt);

// Another triangulation is used as height guide
Fade_2D dt_guide;
createHeightGuide(dt_guide);

MeshGenParams params(pZoneSimple);
params.maxTriangleArea=10.0;
params.pHeightGuideTriangulation=&amp;dt_guide;
dt.refineAdvanced(&amp;params);
dt.writeWebScene("mesh_with_height");
}

.

Drag mouse to rotate, use SHIFT to
zoom and CTRL to translate

Support functions

At the end, as promised, the functions which create the simple zone, the height guide triangulation and the visualizations:

Zone2* createSimpleZone(Fade_2D& dt)
{
	// Create a shape
	std::vector<Point2> vConstraintPoints;
	vConstraintPoints.push_back(Point2(30,0,0));
	vConstraintPoints.push_back(Point2(80,0,0));
	vConstraintPoints.push_back(Point2(55,20,0));
	vConstraintPoints.push_back(Point2(100,20,0));
	vConstraintPoints.push_back(Point2(100,100,0));
	vConstraintPoints.push_back(Point2(54.5,22,0));
	vConstraintPoints.push_back(Point2(0,100,0));
	vConstraintPoints.push_back(Point2(0,20,0));
	vConstraintPoints.push_back(Point2(54,20,0));

	std::vector<Segment2> vSegments;
	for(size_t i=0;i<vConstraintPoints.size();++i)
	{
		Point2& p0(vConstraintPoints[i]);
		Point2& p1(vConstraintPoints[(i+1)%vConstraintPoints.size()]);
		vSegments.push_back(Segment2(p0,p1));
	}

	ConstraintGraph2* pCG(NULL);
	pCG=dt.createConstraint(vSegments,CIS_CONSTRAINED_DELAUNAY);
	dt.applyConstraintsAndZones();
	Zone2* pZone(dt.createZone(pCG,ZL_INSIDE));
	return pZone;

}



void createHeightGuide(Fade_2D& dt_guide)
{
	// We use createSimpleZone in order to insert the same
	// constraints but we are actually not interested in 
	// the zone created by this method.
	createSimpleZone(dt_guide); 	
	
	// We insert a few more constraint edges. Their height
	// is different from 0. 
	Point2 p0(15,30,20);
	Point2 p1(30,30,20);
	Point2 p2(30,45,20);
	Point2 p3(15,45,20);
	std::vector<Segment2> vSegments;
	vSegments.push_back(Segment2(p0,p1));
	vSegments.push_back(Segment2(p1,p2));
	vSegments.push_back(Segment2(p2,p3));
	vSegments.push_back(Segment2(p3,p0));
	dt_guide.createConstraint(vSegments,CIS_CONSTRAINED_DELAUNAY);
	dt_guide.applyConstraintsAndZones();
	dt_guide.writeWebScene("heightGuide");	
		
}

// Retrieves the triangles of pZone and highlights them in the triangulation.
void highlightTriangles(Fade_2D& dt,Zone2* pZone,const std::string& filename)
{
        // 1) Show the full triangulation
        Visualizer2 vis(filename);
        dt.show(&vis);

        // 2) Fetch the triangles from the zone
        vector<Triangle2*> vZoneT;
        pZone->getTriangles(vZoneT);

        // 3) Highlight them in red
        Color colorRed(1,0,0,0.01,true); // The true parameter means 'fill'
        for(size_t i=0;i<vZoneT.size();++i)
        {
                vis.addObject(*vZoneT[i],colorRed);
        }
        vis.writeFile();
}

Leave A Reply

Your email address will not be published. Required fields are marked *

*

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close