medicationforall / skirmishbunker

Apache License 2.0
7 stars 2 forks source link

[FR] Add variable to control depth of window/gun slit frame? #2

Closed mlewis-everley closed 1 year ago

mlewis-everley commented 1 year ago

Hi, me again!

I have been playing around with this today and got some pretty good results. I am trying to make something with a greater pitch on the walls than the default and am hitting an issue with the default settings.

It appears the the window_width is set using the inset, but as the inset gets greater, the windows also get a lot greater (to the point they would need supports to print. As an example:

bunker-outside

bunker-inside

Ideally I would like to get the inside of the gun slits so the project from the wall like 1-2mm. Maybe if there was a way of setting a custom window_width, and if that is not sat, fall back to the default setting?

medicationforall commented 1 year ago

I'm game, give me a moment to grok what you need added. I am also open to pull requests. The file we are interested in is bunkerWindows.py

One helpful note is if the preset method for the making the windows and the cut_windows will not behave you can completely replace them with your own window making callback methods.

Check out the code for this offshoot project. https://github.com/medicationforall/gothicpedastal

This example outright replaces the preset window generation. gothic_pedastal_roof_arch.py

import cadquery as cq
from skirmishbunker import Bunker
from cadqueryhelper import shape

def custom_cut_window(self):
    cut_width = self.inset+self.wall_width
    if self.inset < 0:
        cut_width= (-1*(self.inset))+20

    height = self.height
    p_length = self.window_length+10
    padding = self.panel_padding
    p_height = height - self.panel_padding

    inner_inner_arch = (
        shape.arch_pointed(
            p_length + self.arch_padding_sides - self.inner_arch_sides-3,
            cut_width ,
            height - padding + self.arch_padding_top - self.inner_arch_top-9,
            ((height - padding)/2) + self.arch_inner_height - self.inner_arch_sides
        )
        .translate((0,0,1*(p_height/2)+2.75))
        .rotate((0,0,1),(0,0,0),180)
        .rotate((1,0,0),(0,0,0),self.angle-90)
        .translate((0,0,-1*(height/2)))
    )

    return inner_inner_arch

def custom_window(self):
    window = cq.Workplane("XY").box(10,10,10)

    height = self.height
    p_length = self.window_length-2
    padding = self.panel_padding
    p_height = height - self.panel_padding

    arch = shape.arch_pointed(
        18,
        3,
        117,
        37
    )

    cut_arch =  shape.arch_pointed(
        9,
        4,
        90,
        34
    )

    arch = arch.cut(cut_arch.translate((0,0,-2)))

    arches = (
        cq.Workplane("XY")
        .union(arch.translate((-6.4,3,-2)))
        .union(arch.translate((6.4,3,-2)))
        #.translate((0,10,1*(p_height/2)+2.75))
        .rotate((1,0,0),(0,0,0),self.angle-90)
        .translate((0,0,-9))
    )
    return arches

bp = Bunker()
bp.length = 200
bp.width = 200
bp.height = 140
bp.base_height=10
bp.inset=10
bp.render_floor_tiles = True
bp.render_ladders = False
bp.render_roof = True
bp.render_doors = False
bp.render_interior = True
bp.render_windows = True
bp.render_pips = True
bp.render_magnets = True
bp.wall_width = 7
bp.skip_windows = []
bp.custom_cut_window = custom_cut_window
bp.custom_cut_window_padding = -3
bp.custom_window = custom_window
bp.custom_window_padding = -8
bp.window_height = 90

bp.make()
body = bp.build_body()
roof = bp.build_roof()

#show_object(body)
cq.exporters.export(body, 'stl/gothic_pedastal_arch.stl')
#cq.exporters.export(roof, 'stl/gothic_pedastal_roof.stl')

gothic_pedastal_11_arch


Meanwhile: You need to control the window width independent of the bunker inset.

Try to reproduce, I'm going to make an extreme example:

import cadquery as cq
from skirmishbunker import Bunker

bp = Bunker()
bp.inset=50
bp.width=150
bp.length=150
bp.height=65

bp.render_panel_details=True
bp.panel_length=28
bp.panel_width = 6
bp.panel_padding = 4

bp.render_windows=True
bp.skip_windows = []
bp.window_length = 15
bp.window_height = 8
#bp.window_width = 
bp.window_frame_chamfer = 1.6
bp.window_frame_chamfer_select = "<Z"

bp.render_doors=False
bp.door_panels = [0, 5]

bp.render_ladders=False
bp.ladder_panels = [8]

bp.render_floor_tiles=False
bp.render_roof=False

bp.make()
rec = bp.build_body()

show_object(rec)

window_inset_test

medicationforall commented 1 year ago

@mlewis-everley I Put in changes and cut a new release 1.1.4. Let me know if this works for what you need. Should be able to do an install and get the new parameter.

Example test case:

import cadquery as cq
from skirmishbunker import Bunker

bp = Bunker()
bp.inset=50
bp.width=150
bp.length=150
bp.height=65

bp.render_panel_details=True
bp.panel_length=28
bp.panel_width = 6
bp.panel_padding = 4

bp.render_windows=True
bp.skip_windows = []
bp.window_length = 15
bp.window_width = 32
bp.window_width_offset = -1
bp.window_translate = 3
bp.window_height = 8
bp.window_frame_chamfer = 1.6
bp.window_frame_chamfer_select = "<Z"

bp.render_doors=False
bp.door_panels = [0, 5]

bp.render_ladders=False
bp.ladder_panels = [8]

bp.render_floor_tiles=False
bp.render_roof=False

bp.make()
rec = bp.build_body()

#show_object(rec)
cq.exporters.export(rec,'stl/bunker4_large_inset.stl')

window_inset_test_2

window_width

I added a new parameter called to the definition called window_width which defaults to None. When set to None the code relies in inset. When window_width is set to a number that is truthy the code uses that in place of inset.

    # inset override
    if self.window_width:
        window_width = self.window_width

In the example test case I set the window_width to:

bp.window_width = 32

window_width_offset

Also of note, keep in mind the existing parameter window_width_offset which defaults to -2. That parameter controls the window distance inset from the interior wall. When set the 0 the windows will be flush will the interior wall.

In the example test case I set the window_width_offset to:

bp.window_width_offset = -1
mlewis-everley commented 1 year ago

Nice! I will try this in a bit and see how it turns out 🙂

mlewis-everley commented 1 year ago

OK, so this works perfectly, thanks:

bunker-lg

Quick question, can you swap out the functions for generating the floors and doors in the same fashion as the windows?

medicationforall commented 1 year ago

Awesome, glad it worked!


Floor Tiles

The floor you can totally change out, see this project: https://miniforall.com/gothictower.html

The code for placing the floor tiles lives in this file bunkerFloor.py To override the floor tile generator set a function to custom_floor_tile

Here is an example that does swap out the floor tiles bunker_med.py

In this example I have two different custom tile methods, that you can swap out.

from cqterrain import tile
#... code stuff
def custom_star_tile(bunker):
    star_tile = tile.star(
        length = bunker.floor_tile_size,
        width = bunker.floor_tile_size,
        height = bunker.floor_tile_height,
        points = 4,
        outer_radius = bunker.floor_tile_size/2,
        inner_radius = 2,
        padding = .5
    )
    return star_tile

def custom_windmill_tile(bunker):
    windmill_tile = tile.windmill(
        tile_size = bunker.floor_tile_size,
        height = bunker.floor_tile_height,
        padding = .5
    )
    return windmill_tile
# code stuff ...
bp.custom_floor_tile = custom_windmill_tile

Note from cqterrain import tile

To see what pre-made tiles I have check out this documentation: cqterrain tiles


Overriding The Door

I don't have as many good examples, but code is in place for swapping out the door generator. Code for the door placement is this file bunkerDoors.py

The custom parameters are:

Those will need functions set to them. I believe the code is just copy paste from the custom window parameters.

Turns out I was good dude and actually have an example of setting a custom tile and custom door: bunker_small_custom_door.py

from skirmishbunker import Bunker, SplitDoor
from cqterrain import tile
from cadqueryhelper import shape

# code stuff ...

def custom_windmill_tile(bunker):
    windmill_tile = tile.windmill(
        tile_size = bunker.floor_tile_size,
        height = bunker.floor_tile_height,
        padding = .5
    )
    return windmill_tile

def custom_cut_door(bunker):
    height = bunker.height
    p_length = bunker.panel_length
    p_width = bunker.panel_width
    padding = bunker.panel_padding
    door_cut_width = bunker.inset+bunker.wall_width

    padding_top = 3.2

    if bunker.inset<0:
        door_cut_width = -1*(bunker.inset)+bunker.wall_width

    cut = (
        shape.arch_pointed(24, door_cut_width, 49, 27.3)
        .translate((0,-0,-3))
    )

    cut = shape.arch_pointed(
        p_length  - bunker.inner_arch_sides,
        door_cut_width,
        height - padding - bunker.inner_arch_top - bunker.wall_width+1 -padding_top,
        ((height - padding)/2) + bunker.arch_inner_height - bunker.inner_arch_sides - bunker.wall_width+1 - padding_top
    ).translate((0,0,-4 + bunker.wall_width /2 - padding_top / 2))

    return cut

def custom_door(bunker):
    height = bunker.height
    p_length = bunker.panel_length
    padding = bunker.panel_padding
    padding_top = 3.2

    bp = SplitDoor()
    bp.length = p_length  - bunker.inner_arch_sides
    bp.height = height - padding - bunker.inner_arch_top - bunker.wall_width+1 -padding_top
    bp.width = 1
    bp.base_height = ((height - padding)/2) + bunker.arch_inner_height - bunker.inner_arch_sides - bunker.wall_width+1 - padding_top
    bp.open = 6
    bp.make()
    door = bp.build()
    #return door.translate((0,0,0))
    return door.translate((0,-1,-4 + bunker.wall_width /2 - padding_top / 2))

# code stuff ...
bp.custom_floor_tile = custom_windmill_tile

bp.custom_cut_door = custom_cut_door
bp.custom_cut_door_padding = -.5

bp.custom_door = custom_door
bp.custom_door_padding = -.5

Coincidently SplitDoor was the code that broke the pip install, because it's using the wave function. Anyhow on that example you get something like this.

custom


Of course all of this should be properly documented. On a good note I can use this response as a rough draft of what that documentation would be.

@mlewis-everley let me know if you have any other questions or bugs. I appreciate you going through this stuff. I realize There's a barrier of entry, but for me at least there is also an exciting level of potential.