How to cluster and visualize 3D data in python
The following steps is one method to achieve your result. I used Wolfram Language but the method can be applied by any language with the right libraries.

FindClusters
for category A data (dataA),
calculate the
ConvexHullMesh
for each of these clusters,
for each point in category B (dataB)
calculate the
RegionDistance
to each of the category A hulls,
and
Pick the
dataB points by their nearest category A hull.

We can collect related 3D example data from &quot;AdministrativeDivision&quot; Entity object properties.
dataA =
  Select[FreeQ[_Missing]]@
   EntityValue[
    EntityClass[&quot;AdministrativeDivision&quot;, {&quot;ParentRegion&quot; -&gt; Entity[&quot;Country&quot;, &quot;UnitedStates&quot;]}]
    , {&quot;GiniIndex&quot;, &quot;TotalVotingRate&quot;, &quot;HomeOwnershipRate&quot;}];
First@dataA


{0.4776, 56.3712%, 70.7%}


I used FindClusters with the &quot;MeanShift&quot; method to cluster. Two clusters were found.
clusters = FindClusters[dataA, Method -&gt; &quot;MeanShift&quot;];
Length@clusters


2


The list of ConvexHullMesh for each cluster is obtained by
hulls = ConvexHullMesh /@ clusters




These can be visualised with their internal points by combining aListPointPlot3D of clusters with a Graphics3D of hulls (with low Opacity to make them transparent) with Show.
cp =
 Show[
  ListPointPlot3D[
   clusters
   , PlotStyle -&gt; ColorData[110]
   , PlotTheme -&gt; {&quot;Web&quot;, &quot;FrameGrid&quot;}
   , BoxRatios -&gt; Automatic]
  , Graphics3D[
     {Opacity[.1]
     , MapIndexed[
       {ColorData[110] @@ #2, EdgeForm[{Thin, Opacity[.1], ColorData[110] @@ #2}], #1} &amp;
       , hulls]}]
  ]




For category B example data we need points outside of the hulls of the clusters. We can create a Cuboid around the RegionUnion of hulls and hollow out the volume of hulls by taking the RegionDifference. This region can be visualised with RegionPlot3D.
With[
  {ru = RegionUnion[hulls]}
  , rd =
   RegionDifference[
    Cuboid @@ Transpose[
      MapAt[Ceiling[#, 0.01] &amp;, {All, 2}]@
       MapAt[Floor[#, 0.01] &amp;, {All, 1}]@
        RegionBounds@ru]
    , ru]
  ];
RegionPlot3D[rd
 , PlotStyle -&gt; Opacity[.1]
 , Axes -&gt; True]




Then we can generate RandomPoints inside this region for dataB.
SeedRandom[19283745]
dataB = RandomPoint[DiscretizeRegion@rd, 20];

The dataB points can be combined with the dataA cluster plot with Show.  All of the dataB points are outside of the dataA hulls.
Show[
 cp
 , ListPointPlot3D[dataB
  , PlotStyle -&gt; Black]
 ]




Now that we have example category B data (dataB) we can calculate the RegionDistance of each point to each of category A's hulls. Then by Ordering these distances the First entry gives the hull the point is closest to.
nc =
 First /@
  Ordering /@
   Transpose@
    Through[
     Function[r, RegionDistance[r, #] &amp;, Listable][hulls][dataB]
     ]


{2, 1, 2, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1}


Lastly we Pick the dataB points by their closest hull and combine their plot with the dataA cluster plot with Show. dataB points have been coloured to indicate their closest dataA cluster.
pncB = Pick[dataB, nc, #] &amp; /@ Range@Length@hulls;

Show[
 cp
 , ListPointPlot3D[
  pncB
  , PlotStyle -&gt; ColorData[104]
  , BoxRatios -&gt; Automatic
  ]
 ]




Hope this helps.