I realize this isn’t a trivial issue, mainly due to how ResourceFunction["RoundedPolygon"] works.
While with the Rectangle[] you can use "MaxBoundaryCellMeausure" to set you discretization:
bMeshRec = ToBoundaryMesh[rec, "MaxBoundaryCellMeasure" -> carLength/2];
Length[bMeshRec["Coordinates"]]
52
or by dividing carLength
by 10:
bMeshRec = ToBoundaryMesh[rec, "MaxBoundaryCellMeasure" -> carLength/10];
Length[bMeshRec["Coordinates"]]
260
The issue is that ResourceFunction["RoundedPolygon"]
returns a predefined, discretized geometry, so ToBoundaryMesh
ends up using those fixed coordinates. That’s why it appears not to work properly with ToElementMesh
. However, here’s a workaround I found, it’s a bit tricky, but it not only solves the problem, it also gives better insight into how these functions behave.
Solution A is to build the car geometry using a combination of pure Region functions, such as Disk[]
and Rectangle[]
, which gives you more control over the cells size once you pass it to ToElementMesh
.
Solution B is to modify the existing boundary mesh to match your desired resolution. For example, you can create two separate BoundaryElementMesh
objects with your custom discretization, then join them together and fill in the interior elements afterward.
External rectangle: this is straightforward, as shown earlier, you can set your desired "MaxBoundaryCellMeasure
" to control the discretization. Note that you can (and will need to for the next step) extract both the coordinates and the connectivity. Since this is a boundary mesh, the connectivity simply defines line elements between consecutive points.
rec = Rectangle[{0, 0}, {recLength, recHeight}];
bMeshRec = ToBoundaryMesh[rec, "MaxBoundaryCellMeasure" -> carLength/10];
coordsRec = bMeshRec["Coordinates"];
(* [[1,1]] take the first, in this case the singile one, from the list, and then all the connectivity inside LineElement *)
connRec = bMeshRec["BoundaryElements"][[1, 1]];
You can apply the same approach to the car geometry, but keep in mind that "MaxBoundaryCellMeasure" has no effect in this case. My solution is to manually insert additional points between each pair of existing points, so that each segment is discretized according to your desired resolution. Note that the spacing between points is not uniform, corner segments are shorter than the longer sides (see figure).
bMeshCar = ToBoundaryMesh[car, "MaxBoundaryCellMeasure" -> 1];
coordsCar = bMeshCar["Coordinates"];
connCar = bMeshCar["BoundaryElements"][[1, 1]];
To visualize the points distance:
Graphics[{Point[coordsCar],
{If[Norm[Differences[coordsCar[[#]]]] < carHeight, Red, Blue],
Line[coordsCar[[#]]]} & /@ connCar
}, PlotRange -> {{carx, carx + carLength/2}, {cary + carHeight/2, cary + carHeight}}]

So you’ll need to compute the ideal number of subdivisions for each segment individually. Note that I used Max[ xxx , 2]
in the computation to avoid division by zero during points placement, for smaller spacing
you won't need it.
Once you understand the logic, you can easily tweak it to suit your needs. And you can do it with:
finerCoords = {};
spacing = carLength/50;
sortingIdx = FindShortestTour[coordsCar][[2]];
sortedCoords = coordsCar[[sortingIdx]];
Do[
pt0 = sortedCoords[[i]];
pt1 = sortedCoords[[i + 1]];
n = Max[Ceiling[Norm[pt1 - pt0]/spacing], 2];
pts = Table[pt0 + k ( pt1 - pt0)/(n - 1), {k, 0, n - 1}];
AppendTo[finerCoords, #] & /@ pts;
, {i, 1, Length[sortedCoords] - 1}];
finerCoordsLen = Length[finerCoords];
newConnectivity = Join[Table[{i, i + 1}, {i, finerCoordsLen - 1}], {{finerCoordsLen, 1}}];
And then you need to join the two boundary mesh information togheter:
updatedConnectivity = newConnectivity + Length[coordsRec];
bmesh = ToBoundaryMesh["Coordinates" -> Join[coordsRec, "BoundaryElements" ->{LineElement[connRec], LineElement[updatedConnectivity]}];
bmesh["Wireframe"]

At this point, you can mesh the interior region and specify "MaxCellMeasure" to control the element size inside. Just keep in mind that this setting will not affect the boundary discretization. You need to specifiy also the Hole coordinates, you can simply use the center of the car.
mesh = ToElementMesh[bmesh, "RegionHoles" -> Mean[coordsCar], "MaxCellMeasure" -> .1];
mesh["Wireframe"];

Note that although the result may look quite similar at first glance, if you zoom in on the bottom side of the car, you’ll see that the discretization is now much finer.
Show[mesh["Wireframe"], PlotRange -> {{0.9 carx, 1.1 carx + carLength}, {0, cary + carHeight}}]

You can adjust the spacing
variable and the boundary discretization as needed to control the resolution more precisely.