import numpy as np
from dataclasses import dataclass
from collections import defaultdict

input_points = np.array([
    [20., 20., 60.],
    [20., 30., 65.],
    [55., 30., 80.],
    [80., 10., 60.],
    [20., 10., 55.],
    [60., 30., 70.],
    [70., 15., 20.],
])

planes_defined_by_points = [
    np.array([[50., 5., 5.], [50., 45., 5.], [70., 45., 95.]]),
    np.array([[30., 5., 95.], [30., 45., 95.], [60., 5., 5.]]),
]

@dataclass
class PlaneNormalForm:
    """The plane of all points p with np.dot(self.ortho, p) == self.scalar"""
    ortho: np.array
    scalar: float

planes_in_normal_form = []
for points in planes_defined_by_points:
    ortho = np.cross(points[1] - points[0],
                     points[2] - points[0])
    planes_in_normal_form.append(PlaneNormalForm(
            ortho=ortho,
            scalar=np.dot(ortho, points[0])))

points_by_relative_position = defaultdict(list)
for point in input_points:
	key = tuple(np.dot(plane.ortho, point) > plane.scalar
	            for plane in planes_in_normal_form)
	points_by_relative_position[key].append(point)

for key, points in points_by_relative_position.items():
    print(key)
    for point in points:
    	print("  {:5.0f}, {:5.0f}, {:5.0f}".format(*point))
