Newer
Older
[dims['e'] + row.EdgeOffset / r1 - edgrt, WallBoundaries]]
# Same as edgetop, but for the bottms of the rows
edgebtm = [[dims['s'] + row.EdgeOffset / r1 + edgrt, WallBoundaries],
[dims['e'] + row.EdgeOffset / r1 - edgrt, WallBoundaries]]
# set up some useful values for the top and bottom of the rows.
rowTop = row.z + row.h / 2
rowBtm = row.z - row.h / 2
for hole in Thesketch:
# check the top and bottom of the row, looking at the opening from the right
e = [hole.edgeS(rowTop, -1), hole.edgeS(rowBtm, -1)]
# If either one hit the opening, make split points for the left side of the opening.
if e[0] or e[1]:
e += [hole.edgeS(rowTop, 1), hole.edgeS(rowBtm, 1)]
# If one of them missed for some reason, set that value to
# the middle of the opening.
for i, pos in enumerate(e):
if pos is None:
e[i] = hole.x
# add the intersects to the list of edge points
edgetop.append([e[0], hole])
edgetop.append([e[2], hole])
edgebtm.append([e[1], hole])
edgebtm.append([e[3], hole])
# We want to make the walls in order, so sort the intersects.
# This is where you would want to remove edge points that are out of order
# so that you don't get the "oddity where overlapping openings
# create blocks inversely" problem
# Note: sort ended up comparing function pointers
# if both Openings and Slots were enabled with Repeats in one of them
try:
edgetop.sort(key=lambda x: x[0])
edgebtm.sort(key=lambda x: x[0])
except Exception as ex:
debug_prints(func="rowProcessing",
text="Sorting has failed", var=ex)
# these two loops trim the edges to the limits of the wall.
# This way openings extending outside the wall don't enlarge the wall.
while True:
try:
if ((edgetop[-1][0] > dims['e'] + row.EdgeOffset / r1) or
(edgebtm[-1][0] > dims['e'] + row.EdgeOffset / r1)):
edgetop[-2:] = []
edgebtm[-2:] = []
else:
break
except IndexError:
break
# still trimming the edges...
while True:
try:
if ((edgetop[0][0] < dims['s'] + row.EdgeOffset / r1) or
(edgebtm[0][0] < dims['s'] + row.EdgeOffset / r1)):
edgetop[:2] = []
edgebtm[:2] = []
else:
break
except IndexError:
break
# make those edge blocks and rows! Wooo!
# This loop goes through each section, (a pair of points in edgetop)
# and places the edge blocks and inbetween normal block zones into the row object
for OpnSplitNo in range(int(len(edgetop) / 2)):
# left edge is edge<x>[2*OpnSplitNo], right edge edgex[2*OpnSplitNo+1]
leftEdgeIndex = 2 * OpnSplitNo
rightEdgeIndex = 2 * OpnSplitNo + 1
# get the openings, to save time and confusion
leftOpening = edgetop[leftEdgeIndex][1]
rightOpening = edgetop[rightEdgeIndex][1]
# find the difference between the edge top and bottom on both sides
LTop = edgetop[leftEdgeIndex][0]
LBtm = edgebtm[leftEdgeIndex][0]
RTop = edgetop[rightEdgeIndex][0]
RBtm = edgebtm[rightEdgeIndex][0]
LDiff = LBtm - LTop
RDiff = RTop - RBtm
# which is further out on each side, top or bottom?
if LDiff > 0:
LNerEdge = LBtm # the nearer edge left
LEB = 1 # Left Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
else:
LNerEdge = LTop
LEB = -1
if RDiff > 0:
RNerEdge = RBtm # the nearer edge right
REB = 1 # Right Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
else:
RNerEdge = RTop
REB = -1 # Right Edge Boolean, set to 1 if furthest edge is top, -1 if it is bottom
# The space between the closest edges of the openings in this section of the row
InnerDiff = RNerEdge - LNerEdge
# The mid point between the nearest edges
InnerMid = (RNerEdge + LNerEdge) / 2
# maximum distance to span with one block
MaxWid = (settings['w'] + settings['wv']) / r1
AveWid = settings['w']
# check the left and right sides for wedge blocks
# Check and run the left edge first
# find the edge of the correct side, offset for minimum block height. The LEB decides top or bottom
ZPositionCheck = row.z + (row.h / 2 - settings['hm']) * LEB
# edgeS may return "None"
LeftWedgeEdge = leftOpening.edgeS(ZPositionCheck, 1)
if (abs(LDiff) > AveWid) or (not LeftWedgeEdge):
# make wedge blocks
if not LeftWedgeEdge:
LeftWedgeEdge = leftOpening.x
wedgeBlocks(row, leftOpening, LeftWedgeEdge, LNerEdge, LEB, r1)
# set the near and far edge settings to vertical, so the other edge blocks don't interfere
LTop, LBtm = LNerEdge, LNerEdge
LDiff = 0
# Now do the wedge blocks for the right, same drill... repeated code?
# find the edge of the correct side, offset for minimum block height. The REB decides top or bottom
ZPositionCheck = row.z + (row.h / 2 - settings['hm']) * REB
# edgeS may return "None"
RightWedgeEdge = rightOpening.edgeS(ZPositionCheck, -1)
if (abs(RDiff) > AveWid) or (not RightWedgeEdge):
# make wedge blocks
if not RightWedgeEdge:
RightWedgeEdge = rightOpening.x
wedgeBlocks(row, rightOpening, RNerEdge, RightWedgeEdge, REB, r1)
# set the near and far edge settings to vertical, so the other edge blocks don't interfere
RTop, RBtm = RNerEdge, RNerEdge
RDiff = 0
# Check to see if the edges are close enough toegther to warrant a single block filling it
if (InnerDiff < MaxWid):
# if this is true, then this row is just one block!
x = (LNerEdge + RNerEdge) / 2.
w = InnerDiff
ThisBlockDepth = rndd() * settings['dv'] + settings['d']
BtmOff = LBtm - LNerEdge
TopOff = LTop - LNerEdge
ThisBlockOffsets = [[BtmOff, 0, 0]] * 2 + [[TopOff, 0, 0]] * 2
BtmOff = RBtm - RNerEdge
TopOff = RTop - RNerEdge
ThisBlockOffsets += [[BtmOff, 0, 0]] * 2 + [[TopOff, 0, 0]] * 2
bevel = leftOpening.edgeBev(rowTop)
bevelBlockOffsets(ThisBlockOffsets, bevel, 1)
bevel = rightOpening.edgeBev(rowTop)
bevelBlockOffsets(ThisBlockOffsets, bevel, -1)
row.BlocksEdge.append([x, row.z, w, row.h, ThisBlockDepth, ThisBlockOffsets])
continue
# it's not one block, must be two or more
# set up the offsets for the left
BtmOff = LBtm - LNerEdge
TopOff = LTop - LNerEdge
leftOffsets = [[BtmOff, 0, 0]] * 2 + [[TopOff, 0, 0]] * 2 + [[0] * 3] * 4
bevelL = leftOpening.edgeBev(rowTop)
bevelBlockOffsets(leftOffsets, bevelL, 1)
# and now for the right
BtmOff = RBtm - RNerEdge
TopOff = RTop - RNerEdge
rightOffsets = [[0] * 3] * 4 + [[BtmOff, 0, 0]] * 2 + [[TopOff, 0, 0]] * 2
bevelR = rightOpening.edgeBev(rowTop)
bevelBlockOffsets(rightOffsets, bevelR, -1)
# check to see if it is only two blocks
if (InnerDiff < MaxWid * 2):
# this row is just two blocks! Left block, then right block
# div is the x position of the dividing point between the two bricks
div = InnerMid + (rndd() * settings['wv']) / r1
# set the grout distance, since we need grout separation between the blocks
grt = (settings['g'] + rndc() * settings['gv']) / r1
# set the x position and width for the left block
x = (div + LNerEdge) / 2 - grt / 4
w = (div - LNerEdge) - grt / 2
ThisBlockDepth = rndd() * settings['dv'] + settings['d']
# For reference: EdgeBlocks = [[x, z, w, h, d, [corner offset matrix]], [etc.]]
row.BlocksEdge.append([x, row.z, w, row.h, ThisBlockDepth, leftOffsets])
# Initialize for the block on the right side
x = (div + RNerEdge) / 2 + grt / 4
w = (RNerEdge - div) - grt / 2
ThisBlockDepth = rndd() * settings['dv'] + settings['d']
row.BlocksEdge.append([x, row.z, w, row.h, ThisBlockDepth, rightOffsets])
continue
# program should only get here if there are more than two blocks in the row, and no wedge blocks
# make Left edge block
# set the grout
grt = (settings['g'] + rndc() * settings['gv']) / r1
# set the x position and width for the left block
widOptions = [settings['w'], bevelL + settings['wm'], leftOpening.ts]
baseWid = max(widOptions)
w = (rndd() * settings['wv'] + baseWid + row. EdgeOffset)
widOptions[0] = settings['wm']
widOptions[2] = w
w = max(widOptions) / r1 - grt
x = w / 2 + LNerEdge + grt / 2
BlockRowL = x + w / 2
ThisBlockDepth = rndd() * settings['dv'] + settings['d']
row.BlocksEdge.append([x, row.z, w, row.h, ThisBlockDepth, leftOffsets])
# make Right edge block
# set the grout
grt = (settings['g'] + rndc() * settings['gv']) / r1
# set the x position and width for the left block
widOptions = [settings['w'], bevelR + settings['wm'], rightOpening.ts]
baseWid = max(widOptions)
w = (rndd() * settings['wv'] + baseWid + row.EdgeOffset)
widOptions[0] = settings['wm']
widOptions[2] = w
w = max(widOptions) / r1 - grt
x = RNerEdge - w / 2 - grt / 2
BlockRowR = x - w / 2
ThisBlockDepth = rndd() * settings['dv'] + settings['d']
row.BlocksEdge.append([x, row.z, w, row.h, ThisBlockDepth, rightOffsets])
row.RowSegments.append([BlockRowL, BlockRowR])
return None
def plan(Thesketch, oldrows=0):
__doc__ = """\
The 'plan' function takes the data generated by the sketch function and the global settings
and creates a list of blocks.
It passes out a list of row heights, edge positions, edge blocks, and rows of blocks.
"""
# if we were passed a list of rows already, use those; else make a list.
if oldrows:
rows = oldrows
else:
# rows holds the important information common to all rows
# rows = [list of row objects]
rows = []
# splits are places where we NEED a row division, to accomidate openings
# add a split for the bottom row
splits = [dims['b'] + settings['hb']]
# add a split for each critical point on each opening
for hole in Thesketch:
splits += hole.crits()
# and, a split for the top row
splits.append(dims['t'] - settings['ht'])
splits.sort()
# divs are the normal old row divisions, add them between the top and bottom split
divs = fill(splits[0], splits[-1], settings['h'], settings['hm'] + settings['g'], settings['hv'])[1: -1]
# remove the divisions that are too close to the splits, so we don't get tiny thin rows
for i in range(len(divs) - 1, -1, -1):
for j in range(len(splits)):
diff = abs(divs[i] - splits[j])
if diff < (settings['h'] - settings['hv'] + settings['g']):
del(divs[i])
break
# now merge the divs and splits lists
divs += splits
# add bottom and/or top points, if bottom and/or top row heights are more than zero
if settings['hb'] > 0:
divs.insert(0, dims['b'])
if settings['ht'] > 0:
divs.append(dims['t'])
divs.sort()
# trim the rows to the bottom and top of the wall
if divs[0] < dims['b']:
divs[:1] = []
if divs[-1] > dims['t']:
divs[-1:] = []
# now, make the data for each row
# rows = [[center height,row height,edge offset],[etc.]]
divCount = len(divs) - 1 # number of divs to check
divCheck = 0 # current div entry
while divCheck < divCount:
RowZ = (divs[divCheck] + divs[divCheck + 1]) / 2
RowHeight = divs[divCheck + 1] - divs[divCheck] - settings['g'] + rndc() * \
settings['rwhl'] * settings['gv']
EdgeOffset = settings['eoff'] * (fmod(divCheck, 2) - 0.5) + settings['eoffv'] * rndd()
# if row height is too shallow: delete next div entry, decrement total, and recheck current entry.
if RowHeight < settings['hm']:
del(divs[divCheck + 1])
divCount -= 1 # Adjust count for removed div entry.
continue
rows.append(rowOb(RowZ, RowHeight, EdgeOffset))
divCheck += 1 # on to next div entry
# set up a special opening object to handle the edges of the wall
x = (dims['s'] + dims['e']) / 2
z = (dims['t'] + dims['b']) / 2
w = (dims['e'] - dims['s'])
h = (dims['t'] - dims['b'])
WallBoundaries = openingInvert(x, z, w, h)
# Go over each row in the list, set up edge blocks and block sections
for rownum in range(len(rows)):
rowProcessing(rows[rownum], Thesketch, WallBoundaries)
# now return the things everyone needs
# return [rows,edgeBlocks,blockRows,Asketch]
return [rows, Thesketch]
def archGeneration(hole, vlist, flist, sideSign):
__doc__ = """\
Makes arches for the top and bottom, depending on sideSign
example, Lower arch:
archGeneration(hole, vlist, flist, -1)
example, Upper arch:
archGeneration(hole, vlist, flist, 1)
hole is the opening object that the arch is for
add the vertices to vlist
add the faces to flist
sideSign is + or - 1, for the top or bottom arch. Other values may cause errors.
"""
# working arrays for vectors and faces
avlist = []
aflist = []
# Top (1) or bottom (-1)
if sideSign == -1:
r = hole.rl # radius of the arch
rt = hole.rtl # thickness of the arch (stone height)
v = hole.vl # height of the arch
c = hole.cl
else:
r = hole.r # radius of the arch
rt = hole.rt # thickness of the arch (stone height)
v = hole.v # height of the arch
c = hole.c
ra = r + rt / 2 # average radius of the arch
x = hole.x
w = hole.w
h = hole.h
z = hole.z
bev = hole.b
sideSignInv = -sideSign
if v > w / 2: # two arcs, to make a pointed arch
# positioning
zpos = z + (h / 2) * sideSign
xoffset = r - w / 2
# left side top, right side bottom
# angles reference straight up, and are in radians
bevRad = r + bev
bevHt = sqrt(bevRad ** 2 - (bevRad - (w / 2 + bev)) ** 2)
midHalfAngle = atan(v / (r - w / 2))
midHalfAngleBevel = atan(bevHt / (r - w / 2))
bevelAngle = midHalfAngle - midHalfAngleBevel
anglebeg = (PI / 2) * (sideSignInv)
angleend = (PI / 2) * (sideSignInv) + midHalfAngle
avlist, aflist = arch(ra, rt, (xoffset) * (sideSign), zpos, anglebeg, angleend, bev, bevelAngle, len(vlist))
for i, vert in enumerate(avlist):
avlist[i] = [vert[0] + hole.x, vert[1], vert[2]]
vlist += avlist
flist += aflist
# right side top, left side bottom
# angles reference straight up, and are in radians
anglebeg = (PI / 2) * (sideSign) - midHalfAngle
angleend = (PI / 2) * (sideSign)
avlist, aflist = arch(ra, rt, (xoffset) * (sideSignInv), zpos, anglebeg, angleend, bev, bevelAngle, len(vlist))
for i, vert in enumerate(avlist):
avlist[i] = [vert[0] + hole.x, vert[1], vert[2]]
vlist += avlist
flist += aflist
# keystone
Dpth = settings['d'] + rndc() * settings['dv']
Grout = settings['g'] + rndc() * settings['gv']
angleBevel = (PI / 2) * (sideSign) - midHalfAngle
Wdth = (rt - Grout - bev) * 2 * sin(angleBevel) * sideSign # note, sin may be negative
MidZ = ((sideSign) * (bevHt + h / 2.0) + z) + (rt - Grout - bev) \
* cos(angleBevel) # note, cos may come out negative
nearCorner = sideSign * (MidZ - z) - v - h / 2
if sideSign == 1:
TopHt = hole.top() - MidZ - Grout
BtmHt = nearCorner
else:
BtmHt = - (hole.btm() - MidZ) - Grout
TopHt = nearCorner
# set the amount to bevel the keystone
keystoneBevel = (bevHt - v) * sideSign
if Wdth >= settings['hm']:
avlist, aflist = MakeAKeystone(x, Wdth, MidZ, TopHt, BtmHt, Dpth, keystoneBevel, len(vlist))
if radialized:
for i, vert in enumerate(avlist):
if slope:
r1 = dims['t'] * sin(vert[2] * PI / (dims['t'] * 2))
else:
r1 = vert[2]
avlist[i] = [((vert[0] - hole.x) / r1) + hole.x, vert[1], vert[2]]
vlist += avlist
flist += aflist
# remove "debug note" once bevel is finalized.
else:
debug_prints(func="archGeneration",
text="Keystone was too narrow - " + str(Wdth))
else: # only one arc - curve not peak.
# bottom (sideSign -1) arch has poorly sized blocks...
zpos = z + (sideSign * (h / 2 + v - r)) # single arc positioning
# angles reference straight up, and are in radians
if sideSign == -1:
angleOffset = PI
else:
angleOffset = 0.0
if v < w / 2:
halfangle = atan(w / (2 * (r - v)))
anglebeg = angleOffset - halfangle
angleend = angleOffset + halfangle
else:
anglebeg = angleOffset - PI / 2
angleend = angleOffset + PI / 2
avlist, aflist = arch(ra, rt, 0, zpos, anglebeg, angleend, bev, 0.0, len(vlist))
for i, vert in enumerate(avlist):
avlist[i] = [vert[0] + x, vert[1], vert[2]]
vlist += avlist
flist += aflist
# Make the Side Stones
grt = (settings['g'] + rndc() * settings['gv'])
width = sqrt(rt ** 2 - c ** 2) - grt
if c > settings['hm'] + grt and c < width + grt:
if radialized:
subdivision = settings['sdv'] * (zpos + (h / 2) * sideSign)
else:
subdivision = settings['sdv']
# set the height of the block, it should be as high as the max corner position, minus grout
height = c - grt * (0.5 + c / (width + grt))
# the vertical offset for the short side of the block
voff = sideSign * (settings['hm'] - height)
xstart = w / 2
zstart = z + sideSign * (h / 2 + grt / 2)
woffset = width * (settings['hm'] + grt / 2) / (c - grt / 2)
depth = rndd() * settings['dv'] + settings['d']
if sideSign == 1:
offsets = [[0] * 3] * 6 + [[0] * 2 + [voff]] * 2
topSide = zstart + height
btmSide = zstart
else:
offsets = [[0] * 3] * 4 + [[0] * 2 + [voff]] * 2 + [[0] * 3] * 2
topSide = zstart
# Do some stuff to incorporate bev here
bevelBlockOffsets(offsets, bev, -1)
avlist, aflist = MakeABlock(
[x - xstart - width, x - xstart - woffset, btmSide, topSide,
-depth / 2, depth / 2], subdivision, len(vlist),
Offsets=offsets, xBevScl=1
)
# top didn't use radialized in prev version;
# just noting for clarity - may need to revise for "sideSign == 1"
if radialized:
for i, vert in enumerate(avlist):
avlist[i] = [((vert[0] - x) / vert[2]) + x, vert[1], vert[2]]
vlist += avlist
flist += aflist
# keep sizing same - neat arches = master masons :)
# grt = (settings['g'] + rndc()*settings['gv'])
# height = c - grt*(0.5 + c/(width + grt))
# if grout varies may as well change width too... width = sqrt(rt**2 - c**2) - grt
# voff = sideSign * (settings['hm'] - height)
# woffset = width*(settings['hm'] + grt/2)/(c - grt/2)
if sideSign == 1:
offsets = [[0] * 3] * 2 + [[0] * 2 + [voff]] * 2 + [[0] * 3] * 4
topSide = zstart + height
btmSide = zstart
else:
offsets = [[0] * 2 + [voff]] * 2 + [[0] * 3] * 6
topSide = zstart
# Do some stuff to incorporate bev here
bevelBlockOffsets(offsets, bev, 1)
avlist, aflist = MakeABlock(
[x + xstart + woffset, x + xstart + width, btmSide, topSide,
-depth / 2, depth / 2], subdivision, len(vlist),
Offsets=offsets, xBevScl=1
)
# top didn't use radialized in prev version;
# just noting for clarity - may need to revise for "sideSign == 1"
if radialized:
for i, vert in enumerate(avlist):
avlist[i] = [((vert[0] - x) / vert[2]) + x, vert[1], vert[2]]
vlist += avlist
flist += aflist
return None
def build(Aplan):
__doc__ = """\
Build creates the geometry for the wall, based on the
"Aplan" object from the "plan" function. If physics is
enabled, then it make a number of individual blocks with
physics interaction enabled. Otherwise it creates
geometry for the blocks, arches, etc. of the wall.
"""
vlist = []
flist = []
rows = Aplan[0]
# all the edge blocks, redacted
# AllBlocks = [[x, z, w, h, d, [corner offset matrix]], [etc.]]
# loop through each row, adding the normal old blocks
for rowidx in range(len(rows)):
rows[rowidx].FillBlocks()
AllBlocks = []
# If the wall is set to merge blocks, check all the blocks to see if you can merge any
# seems to only merge vertical, should do horizontal too
if bigBlock:
for rowidx in range(len(rows) - 1):
if radialized:
if slope:
r1 = dims['t'] * sin(abs(rows[rowidx].z) * PI / (dims['t'] * 2))
else:
r1 = abs(rows[rowidx].z)
else:
r1 = 1
Tolerance = settings['g'] / r1
idxThis = len(rows[rowidx].BlocksNorm[:]) - 1
idxThat = len(rows[rowidx + 1].BlocksNorm[:]) - 1
while True:
# end loop when either array idx wraps
if idxThis < 0 or idxThat < 0:
break
blockThis = rows[rowidx].BlocksNorm[idxThis]
blockThat = rows[rowidx + 1].BlocksNorm[idxThat]
# seems to only merge vertical, should do horizontal too...
cx, cz, cw, ch, cd = blockThis[:5]
ox, oz, ow, oh, od = blockThat[:5]
if (abs(cw - ow) < Tolerance) and (abs(cx - ox) < Tolerance):
if cw > ow:
BlockW = ow
else:
BlockW = cw
AllBlocks.append([(cx + ox) / 2, (cz + oz + (oh - ch) / 2) / 2,
BlockW, abs(cz - oz) + (ch + oh) / 2, (cd + od) / 2, None])
rows[rowidx].BlocksNorm.pop(idxThis)
rows[rowidx + 1].BlocksNorm.pop(idxThat)
idxThis -= 1
idxThat -= 1
elif cx > ox:
idxThis -= 1
else:
idxThat -= 1
# Add blocks to create a "shelf/platform".
# Does not account for openings (crosses gaps - which is a good thing)
if shelfExt:
SetGrtOff = settings['g'] / 2 # half grout for block size modifier
# Use wall block settings for shelf
SetBW = settings['w']
SetBWVar = settings['wv']
SetBWMin = settings['wm']
SetBH = settings['h']
# Shelf area settings
ShelfLft = shelfSpecs['x']
ShelfBtm = shelfSpecs['z']
ShelfEnd = ShelfLft + shelfSpecs['w']
ShelfTop = ShelfBtm + shelfSpecs['h']
ShelfThk = shelfSpecs['d'] * 2 # use double-depth due to offsets to position at cursor.
# Use "corners" to adjust position so not centered on depth.
# Facing shelf, at cursor (middle of wall blocks)
# - this way no gaps between platform and wall face due to wall block depth.
wallDepth = settings['d'] / 2 # offset by wall depth so step depth matches UI setting :)
if shelfBack: # place blocks on backside of wall
ShelfOffsets = [
[0, ShelfThk / 2, 0], [0, wallDepth, 0],
[0, ShelfThk / 2, 0], [0, wallDepth, 0],
[0, ShelfThk / 2, 0], [0, wallDepth, 0],
[0, ShelfThk / 2, 0], [0, wallDepth, 0]
]
else:
ShelfOffsets = [
[0, -wallDepth, 0], [0, -ShelfThk / 2, 0],
[0, -wallDepth, 0], [0, -ShelfThk / 2, 0],
[0, -wallDepth, 0], [0, -ShelfThk / 2, 0],
[0, -wallDepth, 0], [0, -ShelfThk / 2, 0]
]
# Add blocks for each "shelf row" in area
while ShelfBtm < ShelfTop:
# Make blocks for each row - based on rowOb::fillblocks
# Does not vary grout.
divs = fill(ShelfLft, ShelfEnd, SetBW, SetBWMin, SetBWVar)
# loop through the row divisions, adding blocks for each one
for i in range(len(divs) - 1):
ThisBlockx = (divs[i] + divs[i + 1]) / 2
ThisBlockw = divs[i + 1] - divs[i] - SetGrtOff
AllBlocks.append([ThisBlockx, ShelfBtm, ThisBlockw, SetBH, ShelfThk, ShelfOffsets])
ShelfBtm += SetBH + SetGrtOff # moving up to next row...
# Add blocks to create "steps".
# Does not account for openings (crosses gaps - which is a good thing)
if stepMod:
SetGrtOff = settings['g'] / 2 # half grout for block size modifier
# Vary block width by wall block variations.
SetWidVar = settings['wv']
SetWidMin = settings['wm']
StepXMod = stepSpecs['t'] # width of step/tread, also sets basic block size.
StepZMod = stepSpecs['v']
StepLft = stepSpecs['x']
StepRt = stepSpecs['x'] + stepSpecs['w']
StepBtm = stepSpecs['z'] + StepZMod / 2 # Start offset for centered blocks
StepWide = stepSpecs['w']
StepTop = StepBtm + stepSpecs['h']
StepThk = stepSpecs['d'] * 2 # use double-depth due to offsets to position at cursor.
# Use "corners" to adjust steps so not centered on depth.
# Facing steps, at cursor (middle of wall blocks)
# - this way no gaps between steps and wall face due to wall block depth.
# Also, will work fine as stand-alone if not used with wall (try block depth 0 and see what happens).
wallDepth = settings['d'] / 2
if stepBack: # place blocks on backside of wall
StepOffsets = [
[0, StepThk / 2, 0], [0, wallDepth, 0],
[0, StepThk / 2, 0], [0, wallDepth, 0],
[0, StepThk / 2, 0], [0, wallDepth, 0],
[0, StepThk / 2, 0], [0, wallDepth, 0]
]
else:
StepOffsets = [
[0, -wallDepth, 0], [0, -StepThk / 2, 0],
[0, -wallDepth, 0], [0, -StepThk / 2, 0],
[0, -wallDepth, 0], [0, -StepThk / 2, 0],
[0, -wallDepth, 0], [0, -StepThk / 2, 0]
]
# Add steps for each "step row" in area (neg width is interesting but prevented)
while StepBtm < StepTop and StepWide > 0:
# Make blocks for each step row - based on rowOb::fillblocks
# Does not vary grout.
if stepOnly: # "cantilevered steps"
if stepLeft:
stepStart = StepRt - StepXMod
else:
stepStart = StepLft
AllBlocks.append([stepStart, StepBtm, StepXMod, StepZMod, StepThk, StepOffsets])
else:
divs = fill(StepLft, StepRt, StepXMod, SetWidMin, SetWidVar)
# loop through the row divisions, adding blocks for each one
for i in range(len(divs) - 1):
ThisBlockx = (divs[i] + divs[i + 1]) / 2
ThisBlockw = divs[i + 1] - divs[i] - SetGrtOff
AllBlocks.append([ThisBlockx, StepBtm, ThisBlockw, StepZMod, StepThk, StepOffsets])
StepBtm += StepZMod + SetGrtOff # moving up to next row...
StepWide -= StepXMod # reduce step width
# adjust side limit depending on direction of steps
if stepLeft:
StepRt -= StepXMod # move in from right
else:
StepLft += StepXMod # move in from left
# Copy all the blocks out of the rows
for row in rows:
AllBlocks += row.BlocksEdge
AllBlocks += row.BlocksNorm
# This loop makes individual blocks for each block specified in the plan
for block in AllBlocks:
x, z, w, h, d, corners = block
if radialized:
if slope:
r1 = dims['t'] * sin(z * PI / (dims['t'] * 2))
else:
r1 = z
else:
r1 = 1
geom = MakeABlock([x - w / 2, x + w / 2, z - h / 2, z + h / 2, -d / 2, d / 2],
settings['sdv'], len(vlist),
corners, None, settings['b'] + rndd() * settings['bv'], r1)
vlist += geom[0]
flist += geom[1]
# This loop makes Arches for every opening specified in the plan.
for hole in Aplan[1]:
# lower arch stones
if hole.vl > 0 and hole.rtl > (settings['g'] + settings['hm']): # make lower arch blocks
archGeneration(hole, vlist, flist, -1)
# top arch stones
if hole.v > 0 and hole.rt > (settings['g'] + settings['hm']): # make upper arch blocks
archGeneration(hole, vlist, flist, 1)
# Warp all the points for domed stonework
if slope:
for i, vert in enumerate(vlist):
vlist[i] = [vert[0], (dims['t'] + vert[1]) * cos(vert[2] * PI / (2 * dims['t'])),
(dims['t'] + vert[1]) * sin(vert[2] * PI / (2 * dims['t']))]
# Warp all the points for radial stonework
if radialized:
for i, vert in enumerate(vlist):
vlist[i] = [vert[2] * cos(vert[0]), vert[2] * sin(vert[0]), vert[1]]
return vlist, flist
def createWall(radial, curve, openings, mergeBlox, shelf, shelfSide,
steps, stepDir, stepBare, stepSide):
__doc__ = """\
Call all the functions you need to make a wall, return the verts and faces.
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
"""
global radialized
global slope
global openingSpecs
global bigBlock
global shelfExt
global stepMod
global stepLeft
global shelfBack
global stepOnly
global stepBack
# set all the working variables from passed parameters
radialized = radial
slope = curve
openingSpecs = openings
bigBlock = mergeBlox
shelfExt = shelf
stepMod = steps
stepLeft = stepDir
shelfBack = shelfSide
stepOnly = stepBare
stepBack = stepSide
asketch = sketch()
aplan = plan(asketch, 0)
return build(aplan)