1
0
Fork 0
mirror of https://github.com/HackerPoet/PySpace synced 2025-08-24 22:02:33 +02:00
fractals/pyspace/geo.py
2019-09-21 23:56:28 -07:00

270 lines
6 KiB
Python

import math
import numpy as np
from .util import *
class Sphere:
def __init__(self, r=1.0, c=(0,0,0), color=(1,1,1)):
self.r = set_global_float(r)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
c = get_global(self.c)
r = get_global(self.r)
return (np.linalg.norm(p[:3] - c) - r) / p[3]
def NP(self, p):
c = get_global(self.c)
r = get_global(self.r)
return normalize(p[:3] - c) * r + c
def glsl(self):
return 'de_sphere(p' + cond_offset(self.c) + ', ' + float_str(self.r) + ')'
def glsl_col(self):
return make_color(self)
class Box:
def __init__(self, s=(1,1,1), c=(0,0,0), color=(1,1,1)):
self.s = set_global_vec3(s)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
c = get_global(self.c)
s = get_global(self.s)
a = np.abs(p[:3] - c) - s;
return (min(max(a[0], a[1], a[2]), 0.0) + np.linalg.norm(np.maximum(a,0.0))) / p[3]
def NP(self, p):
c = get_global(self.c)
s = get_global(self.s)
return np.clip(p[:3] - c, -s, s) + c
def glsl(self):
return 'de_box(p' + cond_offset(self.c) + ', ' + vec3_str(self.s) + ')'
def glsl_col(self):
return make_color(self)
class Tetrahedron:
def __init__(self, r=1.0, c=(0,0,0), color=(1,1,1)):
self.r = set_global_float(r)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
c = get_global(self.c)
r = get_global(self.r)
a = p[:3] - c
md = max(-a[0] - a[1] - a[2], a[0] + a[1] - a[2], -a[0] + a[1] + a[2], a[0] - a[1] + a[2])
return (md - r) / (p[3] * math.sqrt(3.0));
def NP(self, p):
raise Exception("Not implemented")
def glsl(self):
return 'de_tetrahedron(p' + cond_offset(self.c) + ', ' + float_str(self.r) + ')'
def glsl_col(self):
return make_color(self)
class InfCross:
def __init__(self, r=1.0, c=(0,0,0), color=(1,1,1)):
self.r = set_global_float(r)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
r = get_global(self.r)
c = get_global(self.c)
sq = (p[:3] - c) * (p[:3] - c)
return (math.sqrt(min(min(sq[0] + sq[1], sq[0] + sq[2]), sq[1] + sq[2])) - r) / p[3]
def NP(self, p):
r = get_global(self.r)
c = get_global(self.c)
n = p[:3] - c
m_ix = np.argmax(np.abs(n))
n[m_ix] = 0.0
n = normalize(n) * r
n[m_ix] = p[m_ix] - c[m_ix]
return n + c
def glsl(self):
return 'de_inf_cross(p' + cond_offset(self.c) + ', ' + float_str(self.r) + ')'
def glsl_col(self):
return make_color(self)
class InfCrossXY:
def __init__(self, r=1.0, c=(0,0,0), color=(1,1,1)):
self.r = set_global_float(r)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
r = get_global(self.r)
c = get_global(self.c)
sq = (p[:3] - c) * (p[:3] - c)
return (math.sqrt(min(sq[0], sq[1]) + sq[2]) - r) / p[3]
def NP(self, p):
r = get_global(self.r)
c = get_global(self.c)
n = p[:3] - c
m_ix = (0 if abs(n[0]) > abs(n[1]) else 1)
n[m_ix] = 0.0
n = normalize(n) * r
n[m_ix] = p[m_ix] - c[m_ix]
return n + c
def glsl(self):
return 'de_inf_cross_xy(p' + cond_offset(self.c) + ', ' + float_str(self.r) + ')'
def glsl_col(self):
return make_color(self)
class InfLine:
def __init__(self, r=1.0, n=(1,0,0), c=(0,0,0), color=(1,1,1)):
self.r = set_global_float(r)
self.n = set_global_vec3(n)
self.c = set_global_vec3(c)
self.color = color
def DE(self, p):
r = get_global(self.r)
n = get_global(self.n)
c = get_global(self.c)
q = p[:3] - c
return (np.linalg.norm(q - n*np.dot(n,q)) - r) / p[3]
def NP(self, p):
r = get_global(self.r)
c = get_global(self.c)
n = p[:3] - c
m_ix = (0 if abs(n[0]) > abs(n[1]) else 1)
n[m_ix] = 0.0
n = normalize(n) * r
n[m_ix] = p[m_ix] - c[m_ix]
return n + c
def glsl(self):
return 'de_inf_line(p' + cond_offset(self.c) + ', ' + vec3_str(self.n) + ', ' + float_str(self.r) + ')'
def glsl_col(self):
return make_color(self)
class XPlane:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return abs(p[0] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([x, p[1], p[2]])
def glsl(self):
return 'abs(p.x' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)
class YPlane:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return abs(p[1] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([p[0], x, p[2]])
def glsl(self):
return 'abs(p.y' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)
class ZPlane:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return abs(p[2] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([p[0], p[1], x])
def glsl(self):
return 'abs(p.z' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)
class XHalfSpace:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return (p[0] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([x, p[1], p[2]])
def glsl(self):
return '(p.x' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)
class YHalfSpace:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return (p[1] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([p[0], x, p[2]])
def glsl(self):
return '(p.y' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)
class ZHalfSpace:
def __init__(self, x=0.0, color=(1,1,1)):
self.x = set_global_float(x)
self.color = color
def DE(self, p):
x = get_global(self.x)
return (p[2] - x) / p[3]
def NP(self, p):
x = get_global(self.x)
return np.array([p[0], p[1], x])
def glsl(self):
return '(p.z' + cond_subtract(self.x) + ') / p.w'
def glsl_col(self):
return make_color(self)