Since this is a stackoverflow question, I'm assuming you're interested in using Blender's Python API to recreate one of Henry Sagerman's stereographic projection geometries.

Doing a quick search reveals https://github.com/macbuse/Stereographic-projection.
For reference, here are relevant scripts:
grid.py
#makes a pair of meshes with lots of holes
import bpy, bmesh
import numpy as np
from bpy_extras import object_utils
def apply_boolean(obj_A, obj_B, bool_type='INTERSECT'):
print('+++',obj_A, obj_B)
bpy.ops.object.select_all(action='DESELECT')
obj_A.select= True
bpy.context.scene.objects.active = obj_A
bpy.ops.object.modifier_add(type='BOOLEAN')
mod = obj_A.modifiers
mod[0].name = obj_A.name + bool_type
mod[0].object = obj_B
mod[0].operation = bool_type
bpy.ops.object.modifier_apply(apply_as='DATA',
modifier=mod[0].name)
def chessboard(npts=24,
size = 2):
me = bpy.data.meshes.new("Chess")
ob = bpy.data.objects.new("Chess", me)
bpy.context.scene.objects.link(ob)
ob.location = [0,0,0]
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
xs = np.linspace(-size,size,npts)
ys = xs[:]
tt = []
for x in xs:
tt.append([])
for y in ys:
tt[-1].append(bm.verts.new((x,y,0)))
for i,row in enumerate(tt[:-1]):
for j,elt in enumerate(row[:-1]):
#skip every fourth face
if i*j % 2 == 1: continue
bm.faces.new([tt[i][j],tt[i][j+1],tt[i+1][j+1],tt[i+1][j]])
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free() # free and prevent further access
#be polite: make active and return a reference
bpy.context.scene.objects.active = ob
return ob
def cube_slicer(cube_scale=.85,
z_offset=1):
'''splits selected mesh into two parts
using boolean operations'''
def clean_up(cut_off=.1):
'''cleans up after boolean operations
deleting any extraneous vertices out of
the xy-plane
'''
ob = bpy.context.object
bpy.ops.object.mode_set(mode = 'EDIT')
me = ob.data
bm = bmesh.from_edit_mesh(me)
verts = [v for v in bm.verts
if abs(v.co[2]) > cut_off]
bmesh.ops.delete(bm, geom=verts, context=1)
bmesh.update_edit_mesh(me)
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
xx = bpy.context.active_object
xx.select= True
bpy.ops.object.duplicate()
yy = bpy.context.scene.objects.active
yy.location = [0,0,z_offset]
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.mesh.primitive_cube_add(location=[0,0,0])
cc = bpy.context.scene.objects.active
cc.scale = [cube_scale,cube_scale,1]
bpy.ops.object.duplicate()
dd = bpy.context.scene.objects.active
dd.location = [0,0,z_offset]
apply_boolean(xx, cc, bool_type='INTERSECT')
clean_up()
apply_boolean(yy, dd, bool_type='DIFFERENCE')
clean_up()
#get rid of the cubes
bpy.ops.object.select_all(action='DESELECT')
for x in [cc,dd]:
x.select = True
bpy.ops.object.delete()
chessboard()
cube_slicer(cube_scale=.85)
and stereo_proj.py
import bpy, bmesh
from mathutils import Vector
###################got this from mesh_looptools.py#################
# input: bmesh, output: dict with the edge-key as key and face-index as value
def dict_edge_faces(bm):
edge_faces = dict([[edgekey(edge), []] for edge in bm.edges
if not edge.hide])
for face in bm.faces:
if face.hide:
continue
for key in face_edgekeys(face):
edge_faces[key].append(face.index)
return(edge_faces)
# return the edgekey ([v1.index, v2.index]) of a bmesh edge
def edgekey(edge):
return(tuple(sorted([edge.verts[0].index, edge.verts[1].index])))
# returns the edgekeys of a bmesh face
def face_edgekeys(face):
return([tuple(sorted([edge.verts[0].index, edge.verts[1].index])) for \
edge in face.edges])
###################################################################
def stereo_proj(scale_factor=.9):
# Get the active mesh
me = bpy.context.object.data
# Get a BMesh representation
bm = bmesh.new()
bm.from_mesh(me)
#this gets border edges which should be extruded to make a solid
borders = [ x for x,y in dict_edge_faces(bm).items()
if len(y) < 2 ]
borders.sort()
for v in bm.verts:
x,y,z = v.co[:]
r2 = x*x + y*y
nv = 1./(r2 + 1) * Vector((2*x, 2*y, (r2 - 1)))
v.co = nv
offset = len(bm.verts)
#take a copy as we are adding to bm.verts
#otherwise hangs with an infinite loop
copy_verts = bm.verts[:]
for pt in copy_verts:
bm.verts.new( scale_factor*pt.co )
#hash this to make clearer
vvs = bm.verts
vvs.ensure_lookup_table()
#new layer of faces concentric to original faces
new_faces = [ ( vvs[vv.index + offset] for vv in ff.verts[:] )
for ff in bm.faces]
#add faces that go between the two layers
extruded_edge_faces = [ (vvs[a], vvs[b], vvs[ b + offset ], vvs[a + offset])
for a,b in borders ]
#add the new faces to the mesh
new_faces.extend(extruded_edge_faces)
for ff in new_faces:
bm.faces.new(ff)
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free()
stereo_proj()
(Bare in mind the source code is 6 years old, so if you're using a newer version of Blender where the API changed, you might need to few tweaks (e.g. swapping bpy.context.scene.objects.link(ob) for bpy.context.collection.objects.link(ob))
You might also find the Blender Stackexhange helpful (for example this post) , as well as this article.
