Here's a fully generic way with ImplicitRegion
.
First, we might want to simply use scaled
, or we might instead want to convert to a BoundaryMeshRegion
via
bscaled = BoundaryDiscretizeRegion[scaled]
(As we'll see, this seems to improve performance.)
Second, with surface
being your function of $u$ and $v$, we might want to use ImplicitRegion[surface[u,v] \[Element] reg, {{u, 0, 2}, {v, 0, 2}}]
.
(There is also InverseTransformedRegion[
$reg,f,n$]
instead of ImplicitRegion
, which gives the region $\{p \in \mathbb{R}^n \mid f(p) \in reg\}$—in other words, exactly what you want, minus the bounds restrictions! However, as we'll see, there are computational problems with this option.)
Finally, if we discretize the result, we might want to discretize it via DiscretizeRegion
or via BoundaryDiscretizeRegion
.
Though, that part might depend on your application: if you don't need to discretize the resulting region, don't. Discretization of these regions takes some time! You might be able to use the region numerically even without discretizing it. some functions will work directly (and numerically) with the returned InverseTransformedRegion
or ImplicitRegion
anyway, so you might not need to discretize at all. However, if you're going to be doing a lot of different things with it, and if those computations are a bit slow, you might get better performance overall by discretizing from the outset.
But if you do need to discretize the resulting region...
I wrote a test to time all the different combinations:
scaled
vs. bscaled
ImplicitRegion
vs. InverseTransformedRegion
DiscretizeRegion
vs. BoundaryDiscretizeRegion
.
The best was BoundaryDiscretizeRegion
on an ImplicitRegion
that referred to bscaled
, which clocked in at around 44 seconds.
(* Best performance: *)
surface[u_, v_] := {(u^2 + v^2)/3, (u^2 - v^2)/3}
bscaled = BoundaryDiscretizeRegion[scaled];
BoundaryDiscretizeRegion[
ImplicitRegion[surface[u, v] \[Element] bscaled,
{{u, 0, 2}, {v, 0, 2}}]
]
Contrast with using scaled
instead, which took almost 3 minutes. It performed about the same as using DiscretizeRegion
on the outer level, but since BoundaryDiscretizeRegion
seems to work better as an input, you might want to use BoundaryDiscretizeRegion
anyway.
When I tried to discretize InverseTransformedRegion
, it made my CPU temperature shoot up to 100ºC and wasn't any quicker. So if you're going to discretize it, I would recommend using ImplicitRegion
instead of InverseTransformedRegion
. However, there's always the chance that it will perform better with other operations; it all depends on how you'll be using this.
Maybe someone can suggest good option values for BoundaryDiscretizeRegion
or DiscretizeRegion
that would speed things up, or a tweak to this approach. I do think that an approach like this at least has the advantage of giving you "the right kind of thing" as a result—namely, a region. But I'm sure there are improvements that can be made.
For reference, here's the test I used. I wound up evaluating some individually when I wanted to skip some. I don't recommend running the test.
ClearAll[scaled, bscaled, method, reg, surface, uvImplicit, uvInverseTransformed, inputregiontype]
scaled =
TransformedRegion[
RegionResize[
DiscretizeRegion[
GeoGridPosition[Entity["Country", "Portugal"]["Polygon"],
"Mercator"]], 1/2], TranslationTransform[{9.5, -43.4}]];
bscaled = BoundaryDiscretizeRegion[scaled];
surface[u_, v_] := {(u^2 + v^2)/3, (u^2 - v^2)/3}
(* Example of both methods, here using bscaled *)
uvImplicit = ImplicitRegion[surface[u, v] \[Element] bscaled, {{u, 0, 2}, {v, 0, 2}}]
uvInverseTransformed = InverseTransformedRegion[bscaled, surface, 2]
(* Discretization test: *)
method["Implicit"] = ImplicitRegion[surface[u, v] \[Element] #1, {{u, 0, 2}, {v, 0, 2}}] &;
method["InverseTransformed"] = InverseTransformedRegion[#1, surface, 2] &;
inputregiontype["Mesh"] = scaled;
inputregiontype["BoundaryMesh"] = bscaled;
Table[
Echo@AbsoluteTiming[{ (* Label: *) {disc, m, reg},
(* Output: *) disc[method[m][inputregiontype[reg]]]}
],
{m, {"Implicit", "InverseTransformed"}}
{disc, {DiscretizeRegion, BoundaryDiscretizeRegion}},
{reg, {"Mesh", "BoundaryMesh"}}
]
ImplicitRegion
somehow? $\endgroup$