4
$\begingroup$

Let's say I have some composite 3D graphics of various shapes. For simplicity, let's say these are just two capsules, like below:

myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 2.997], 
 CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 
    0.946586}}, 2.997]}

Graphics3D[myShapes, ViewPoint -> Front, 
 ViewProjection -> "Orthographic"]

enter image description here

Now, from that orthographic projection, I'd like to get a binary image of the "foreground" pixels visible from the projection, so that I can get 2D ComponentMeasurements[] (like area, circularity, etc.)

We can use Jen's function from this answer to get a black "shadow", which seems promising, but such shadow is still a Graphics3D[] object, so it does not seem very useful (but it's cool!):

enter image description here

How could I go about this?

Thanks!

Note: Ideally, the projection should respect the dimensions of the original graphics (say, the diameter/shape of the capsules), but I'm assuming the orthographic projection would take care of that(?)

$\endgroup$

1 Answer 1

7
$\begingroup$

Edit

If we only need to image,we can use

Clear[plot, img]; 
myShapes = {CapsuleShape[{{-0.002997, 0., 
     0.}, {0.002997, 0., 0.}}, 2.997], 
  CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 
     0.946586}}, 2.997]}; 
plot = 
 Graphics3D[{Black, myShapes}, ViewProjection -> "Orthographic", 
  ViewPoint -> {0, -1, 0}, Boxed -> False, PlotRangePadding -> 0, 
  PlotRange -> Full];
 img = ImportString[ExportString[plot, "PNG"]]

enter image description here

Original

  • CapsuleShape is the BSplineSurface. It it not easy to handle.
Needs["OpenCascadeLink`"];
Needs["NDSolve`FEM`"];
myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 
    2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 
      0.956034, 0.946586}}, 2.997]};
shape1 = OpenCascadeShape[myShapes[[1]]];
shape2 = OpenCascadeShape[myShapes[[2]]];
mesh1 = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape1, 
   "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.05}];
mesh2 = OpenCascadeShapeSurfaceMeshToBoundaryMesh[shape2, 
   "ShapeSurfaceMeshOptions" -> {"AngularDeflection" -> 0.05}];
mg1 = TransformedRegion[MeshRegion[mesh1], 
    ScalingTransform[0, {0, 1, 0}]] // Quiet;
mg2 = TransformedRegion[MeshRegion[mesh2], 
    ScalingTransform[0, {0, 1, 0}]] // Quiet;
mg = RegionUnion[mg1, mg2];
dist = RegionDistance[mg];
projection = 
 ImplicitRegion[dist@{x, 0, z} <= .02, {x, z}] // DiscretizeRegion
projection // Area

55.6183

enter image description here

  • Compare with the 3D graphics.
myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 
   2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 
     0.956034, 0.946586}}, 2.997]}; 
Graphics3D[
 GeometricTransformation[myShapes, ScalingTransform[0, {0, 1, 0}]]]

enter image description here

$\endgroup$
4
  • $\begingroup$ Wow, that's pretty cool. I wonder if there's a simple way to convert the "flat" 3D shapes into a binary image. In my case, I'd be using other shapes in addition to capsules (often combined in the same graphics object). But this approach is a great start, thanks! $\endgroup$ Jul 17, 2022 at 3:04
  • 1
    $\begingroup$ @TumbiSapichu image is relatively easy. For example Clear[plot, img]; myShapes = {CapsuleShape[{{-0.002997, 0., 0.}, {0.002997, 0., 0.}}, 2.997], CapsuleShape[{{5.22693, 0.954974, 0.945536}, {5.23274, 0.956034, 0.946586}}, 2.997]}; plot = Graphics3D[{Black, myShapes}, ViewProjection -> "Orthographic", ViewPoint -> {0, 1, 0}, Boxed -> False, PlotRangePadding -> 1.2, PlotRange -> Full]; img = ImportString[ExportString[plot, "PNG"]] $\endgroup$
    – cvgmt
    Jul 17, 2022 at 3:10
  • $\begingroup$ Oh, cool, that's exactly what I was trying to get at. If you write it as a response I'll accept it. $\endgroup$ Jul 17, 2022 at 3:17
  • 1
    $\begingroup$ @TumbiSapichu updated. $\endgroup$
    – cvgmt
    Jul 17, 2022 at 3:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.