Open mustbau opened 3 weeks ago
I'm afraid there is no easy way to directly refine a mesh around points or a line. Region pointers are exactly what the name says: a pointer to a region which is enclosed by a contour (i.e. a region has an area > 0). A simple point doesn't fit into that category, neither does a line.
A possible solution might be to post-process the mesh, setting the triangle area for all triangles connected to the borehole points (using the VertexCirculator
class) and then refining with triQuality.VariableArea = true
.
Here's an example:
using System.Collections.Generic;
using TriangleNet;
using TriangleNet.Geometry;
using TriangleNet.Meshing;
using TriangleNet.Meshing.Iterators;
public class Issue48
{
public static void Test()
{
var poly = new Polygon(6);
// Outer contour
poly.Add(new Contour([
new Vertex(0.0, 0.0, 1),
new Vertex(1.0, 0.0, 1),
new Vertex(1.0, 1.0, 1),
new Vertex(0.0, 1.0, 1)],
1, true));
var boreholepoints = new List<Vertex>()
{
new Vertex(0.4, 0.4, 2),
new Vertex(0.9, 0.9, 2)
};
poly.Points.AddRange(boreholepoints);
var options = new QualityOptions()
{
MinimumAngle = 30,
MaximumArea = 0.05
};
var m = poly.Triangulate(options);
var c = new VertexCirculator((Mesh)m);
// Set area constraint around borehole points
foreach (var p in boreholepoints)
{
foreach (var tri in c.EnumerateTriangles(p))
{
tri.Area = 0.002;
}
}
options.VariableArea = true;
m.Refine(options, true);
}
}
Another option: add extra points around borehole points before triangulation. Of course you must make sure that those extra points do not introduce any unwanted features. Additionally, you could subdivide the line segments before triangulation.
Example:
public static void Test()
{
var poly = new Polygon(6);
// Outer contour
poly.Add(new Contour([
new Vertex(0.0, 0.0, 1),
new Vertex(1.0, 0.0, 1),
new Vertex(1.0, 1.0, 1),
new Vertex(0.0, 1.0, 1)],
1, true));
var boreholepoints = new List<Vertex>()
{
new Vertex(0.4, 0.4, 2),
new Vertex(0.9, 0.9, 2)
};
poly.Points.AddRange(boreholepoints);
var options = new QualityOptions()
{
MinimumAngle = 30,
MaximumArea = 0.05
};
// Add extra points in vicinity of borehole points
foreach (var p in boreholepoints)
{
// Using negative of original label to identify extra points.
poly.Points.AddRange(Circle(6, p, 0.01, -p.Label));
}
var m = poly.Triangulate(options);
}
static IEnumerable<Vertex> Circle(int n, Vertex center, double radius, int label = 0)
{
double x = center.X;
double y = center.Y;
double dphi = 2 * Math.PI / n;
for (int i = 0; i < n; i++)
{
yield return new Vertex(x + radius * Math.Cos(i * dphi), y + radius * Math.Sin(i * dphi), label);
}
}
Hi Christian, Thanks for the examples, i found the first example to be suitable, i have tried the 2nd example before. it works when i add an ellipse or circle beforehand, but the refinement is only bound inside/adjecent to the ellipse/circle contours.
I would like to continue with the post refinement technique in your first example. i tried it but somehow the function "c.EnumerateTriangles(pt) " throws null exception. Although the mesh is full of triangles.
here the full post refinement code:
` var mesh = p.Triangulate(options, triQuality);//,triQuality TriangleNet.Mesh m = (TriangleNet.Mesh)mesh; var c = new TriangleNet.Meshing.Iterators.VertexCirculator(m);
// Set area constraint around borehole points
int indexer = 0;
foreach (var pt in boreholepts)
{
var vert = new Vertex(pt.X, pt.Y, indexer);
foreach (var tri in c.EnumerateTriangles(vert))
{
tri.Area = 0.5;
}
indexer++;
}
triQuality.VariableArea = true;
mesh.Refine(triQuality, true);`
Are there by any chance duplicate vertices in your input? Please check with PolygonValidator and also take a look at the log.
hi, thanks for fast reply. No, i tested it with a single internal point, still throwing: System.NullReferenceException: “The object reference was not set to an object instance.", ill try to check with Validator.
That's strange. Can you post the full stack trace and maybe a small, but complete (code and input data) test case that reproduces the error?
Ok, I see the problem. Take a look at the VertexCirculator. It relies on the internal Vertex.tri. This means you cannot do
var vert = new Vertex(pt.X, pt.Y, indexer);
foreach (var tri in c.EnumerateTriangles(vert))
//...
since that newly created vertex won't have the tri
field set (that's an implementation detail of the mesh topology you don't have access to).
To make this work with your original code example, you have to have access to the borehole vertices:
//Add borehole points
var boreholevertices = boreholepts.Select(qy => new Vertex(qy.X, qy.Y, 1));
p.Points.AddRange(boreholevertices);
//...
foreach (var p in boreholevertices)
{
foreach (var tri in c.EnumerateTriangles(p))
//...
Hi, i now tried to use the older vertices which were added to the polygon itself for post refinement, but i get the same System.NullReferenceException: “The object reference was not set to an object instance.",
Here the new try code (ill add the data together with error log after another try at it. ill try to use some other points first): ` var p = new TriangleNet.Geometry.Polygon();
//creat vertices from boreholpts
var bvert = new List<Vertex>();
foreach (XYZ pt in boreholepts)
{
Vertex vert = new Vertex(pt.X, pt.Y, 1);
bvert.Add(vert);
}
//first add the outer boundry points (taken from the modellines) to the polygon p
p.Add(new Contour(boundary.Select(px => new Vertex(px.X, px.Y, 1)), 1));
// now add internal vertices
p.Points.AddRange(bvert);
var options = new ConstraintOptions() { ConformingDelaunay = true };
var triQuality = new QualityOptions()
{
MinimumAngle = 30,
//VariableArea = true,
MaximumArea = MaxArea
};
var mesh = p.Triangulate(options, triQuality);//,triQuality
TriangleNet.Mesh m = (TriangleNet.Mesh)mesh;
var c = new TriangleNet.Meshing.Iterators.VertexCirculator(m);
// Set area constraint around borehole points
foreach (var pt in bvert)
{
foreach (var tri in c.EnumerateTriangles(pt))
{
tri.Area = 0.5;
}
}
triQuality.VariableArea = true;
mesh.Refine(triQuality, true);
`
Hi, i am struggling to achieve mesh refinement around a line segment and around some points inside a polygon. i used this code below to define the geometry for the PSLG for meshing, i have a n Ellipse and a line segment inside the Polygon and some points. i want to refine the mesh around all of them, here is my code:
`
var p = new TriangleNet.Geometry.Polygon();
the mesh does refine around the ellipse but not around the borehole points and the line segment. Any idea whats missing in the geometry description. Thanks in Advance.