Circle
Let's create circle3D
that is something you would expect from Circle
but with an extra argument for its normal vector.
With
circle3D[centre_: {0, 0, 0}, radius_: 1, normal_: {0, 0, 1}, angle_: {0, 2 Pi}] :=
Composition[
Line,
Map[RotationTransform[{{0, 0, 1}, normal}, centre], #] &,
Map[Append[#, Last@centre] &, #] &,
Append[DeleteDuplicates[Most@#], Last@#] &,
Level[#, {-2}] &,
MeshPrimitives[#, 1] &,
DiscretizeRegion,
If
][
First@Differences@angle >= 2 Pi,
Circle[Most@centre, radius],
Circle[Most@centre, radius, angle]
]
we can produce, for example, the following.
A unit circle centred at the origin with the z-axis as its normal:
Graphics3D[circle3D[]]
A unit circle centred at {2, 3, 4}
with the z-axis as its normal:
Graphics3D[circle3D[{2, 3, 4}, 2]]
A circle centred at {2, 3, 4}
with radius 2
and the z-axis as its normal:
Graphics3D[circle3D[{2, 3, 4}, 2]]
A circle centred at {2, 3, 4}
with radius 2
and normal vector pointing in the direction of $\hat\imath - \hat\jmath + \hat{k}$:
Graphics3D[circle3D[{2, 3, 4}, 2, {1, -1, 1}]]
An arc, drawn from 0 to 180 degrees, of a circle whose origin is centred at {2, 3, 4}
, radius is 2
, and normal vector points in the direction of $\hat\imath - \hat\jmath + \hat{k}$:
Graphics3D[circle3D[{2, 3, 4}, 2, {1, -1, 1}, {0, 180 Degree}]]
Neat Examples
tocartesian = CoordinateTransformData["Spherical" -> "Cartesian", "Mapping"];
circles = MapThread[
circle3D[{0, 0, 0}, #1, tocartesian[{#1, #2, 0}]] &,
{Range[37], Range[0 Degree, 360 Degree, 10 Degree]}
];
ListAnimate@Table[
Graphics3D[
Rotate[#, n Degree, {0, 1, 0}] & /@ circles,
Boxed -> False,
PlotRange -> 37 {{-1, 1}, {-1, 1}, {-1, 1}}
],
{n, 180}
]
tocartesian = CoordinateTransformData["Spherical" -> "Cartesian", "Mapping"];
spherecentre = RandomReal[{-1, 1}, 3];
sphereradius = RandomReal[{1, 2}];
dotsize = sphereradius/20;
randcirc := Module[
{circleradius, randompoint},
circleradius = RandomReal[{dotsize, sphereradius}];
randompoint = TranslationTransform[spherecentre][
tocartesian[{sphereradius, RandomReal[{0, Pi}],
RandomReal[{0, 2 Pi}]}]
];
{
RandomColor[],
Sphere[randompoint, dotsize],
circle3D[
spherecentre +
Sqrt[sphereradius^2 - circleradius^2] Normalize[randompoint - spherecentre],
circleradius,
randompoint - spherecentre
]
}
];
Graphics3D[
{
{Opacity[0.3, LightGray], Sphere[spherecentre, sphereradius]},
Thick,
Table[randcirc, {10}]
},
Boxed -> False
]
Extras
Disk
Likewise, we can construct disk3D
that behaves like Disk
but with an extra argument for its normal vector.
disk3D[centre_: {0, 0, 0}, radius_: 1, normal_: {0, 0, 1}, angle_: {0, 2 Pi}] :=
Polygon[
Map[RotationTransform[{{0, 0, 1}, normal}, centre]][
If[First@Differences@angle >= 2 Pi, #, Append[#, centre]] &[
Map[Append[#, Last@centre] &][
SortBy[#, sortf[#, Most@centre] &] &[
MeshCoordinates[DiscretizeRegion[
Circle[Most@centre, radius, angle]
]]]]]]]
sortf := Composition[
If[Negative[#], # + 2 Pi, #] &,
N[ArcTan @@ (#1 - #2)] &
]
The sorting of points is adapted from nikie's answer in #48091
Examples:
Graphics3D[disk3D[]]
Graphics3D[disk3D[{2, 3, 4}, 2, {1, -1, 1}, {30 Degree, 180 Degree}]]
It's a Polygon
after all, so it behaves just like any other region object in Mathematica. You can execute, for example,
RegionMeasure[disk3D[{2, 3, 4}, 2, {1, -1, 1}, {30 Degree, 180 Degree}]]
and get the area:
5.2232
or style it like
disk = disk3D[{2, 3, 4}, 2, {1, -1, 1}, {30 Degree, 180 Degree}];
Graphics3D[{EdgeForm[], Red, disk}]
Ellipse
After circle3D
, why not ellipse3D
as well?
ellipse3D[centre_: {0, 0, 0}, radii_: {1, 1}, normal_: {0, 0, 1}] :=
Polygon[
RotationTransform[{{0, 0, 1}, normal}, centre][
Map[Append[#, Last@centre] &][
SortBy[#, N[ArcTan @@ (# - Most@centre)] &] &[
MeshCoordinates[BoundaryDiscretizeRegion[
Ellipsoid[Most@centre, radii]
]]]]]]
Graphics3D[ellipse3D[]]
is equivalent to Graphics3D[circle3D[]]
:
Graphics3D[ellipse3D[{2, 3, 4}, {1, 2}, {1, -1, 1}]]
RegionMeasure[ellipse3D[{2, 3, 4}, {1, 2}, {1, -1, 1}]]
6.25978
which is a little bit off from that of the same ellipse in 2D:
RegionMeasure[Ellipsoid[{2, 3}, {1, 2}]]
2π
due to the discretisation.
Read@Mind[{}]
is not for everyone. Isn't there a badge for achieving the Beginner's Mind? $\endgroup$