#---------------------------------------------------------------------- # Program to support simple orthographic 3D projection # # Copyright (C) October 2018 -- Dr. William T. Verts #---------------------------------------------------------------------- Sine = 0.5 # 30 degrees Cosine= sqrt(3) / 2.0 # 30 degrees Scale2D = 10.0 Origin2D = [0,0] def Project3D (P3D): # P3D is 3D point, list [X,Y,Z] global Scale2D,Origin2D X = Origin2D[0] + (P3D[0] + P3D[2] * Cosine) * Scale2D Y = Origin2D[1] - (P3D[1] + P3D[2] * Sine) * Scale2D Result = [X,Y] return Result # Result is a 2D point, list [X,Y] def SetOrigin2D(P2D): global Origin2D Origin2D = P2D return def SetScale2D(NewScale): global Scale2D Scale2D = NewScale return #---------------------------------------------------------------------- def INT(N): return int(round(N)) def addLine3D(Canvas, P0, P1, NewColor=black): # P0 and P1 are 3D points [X,Y,Z] P0_2D = Project3D(P0) P1_2D = Project3D(P1) addLine(Canvas, INT(P0_2D[0]), INT(P0_2D[1]), INT(P1_2D[0]), INT(P1_2D[1]), NewColor) return #---------------------------------------------------------------------- # Add two points together (originally add two 3D points together) # # addPoint was originally defined as: # # def addPoint(Q0,Q1): # X = Q0[0] + Q1[0] # Y = Q0[1] + Q1[1] # Z = Q0[2] + Q1[2] # return [X,Y,Z] # # It can then be defined with a loop as: # # def addPoint(Q0,Q1): # Result = [] # for I in range(3): Result = Result + [Q0[I] + Q1[I]] # return Result # # To make the function handle any number of dimensions: # # def addPoint(Q0,Q1): # Result = [] # for I in range(min(len(Q0),len(Q1))): Result = Result + [Q0[I] + Q1[I]] # return Result # # Now, to make the function even more efficient, use a # list comprehension: #---------------------------------------------------------------------- def addPoint(Q0,Q1): return [Q0[I] + Q1[I] for I in range(min(len(Q0),len(Q1)))] #---------------------------------------------------------------------- # Multiply all dimensions of a point by a scale factor. #---------------------------------------------------------------------- def scalePoint(Q, Scale=1.0): # Q is a 3D point return [Q[I] * Scale for I in range(len(Q))] #---------------------------------------------------------------------- # Plot a house where HouseOrigin is the front left corner, scaled # by a multiplier to set the size, and with the given color. # Notice the function Line is defined as local to AddHouse. # As far as Line is concerned, variables Canvas, HouseOrigin, Scale, # and NewColor are treated as global, even though they are local to # addHouse. #---------------------------------------------------------------------- def addHouse(Canvas, HouseOrigin, Scale, NewColor): # HouseOrigin = [X,Y,Z] 3D point def Line (P0,P1): addLine3D(Canvas, addPoint(HouseOrigin, scalePoint(P0,Scale)), addPoint(HouseOrigin, scalePoint(P1,Scale)), NewColor) return LLF = [0,0,0] LRF = [6,0,0] ULF = [0,3,0] URF = [6,3,0] MF = [3,6,0] LLB = [0,0,8] LRB = [6,0,8] ULB = [0,3,8] URB = [6,3,8] MB = [3,6,8] Line(LLF, LRF) Line(LLF, ULF) Line(LRF, URF) Line(ULF, MF ) Line(MF , URF) # Line(LLB, LRB) # Line(LLB, ULB) Line(LRB, URB) # Line(ULB, MB ) Line(MB , URB) # Line(LLF, LLB) # Line(ULF, ULB) Line(MF , MB ) Line(URF, URB) Line(LRF, LRB) return #---------------------------------------------------------------------- # Draw a neighborhood! #---------------------------------------------------------------------- def Main(): Canvas = makeEmptyPicture(800,600) SetOrigin2D([400,300]) SetScale2D(20.0) addLine3D(Canvas, [10,0,0], [-10,0,0], red) addLine3D(Canvas, [0,10,0], [0,-10,0], green) addLine3D(Canvas, [0,0,10], [0,0,-10], blue) for X in range(-100,+100, 10): for Z in range(-100, +100, 10): addHouse(Canvas, [X,0,Z], 1.0, black) show(Canvas) return