Ir para conteúdo
3DFinder
Entrar

Você está no 3DFinder

Buscamos em Thingiverse, MakerWorld e Printables ao mesmo tempo para te dar o melhor de cada uma.

Buscar mais como este
Modelo 3D pBox por m. alperen şener no Printables

Descrição

pBox

A simple script for creating basic, functional boxes with lids.

If you need to build straightforward, utilitarian boxes rather than fancy ones, this is for you. I originally created this to make a tiny set of boxes for storing my SMD components.

Just edit the parameters in the JSON configuration file to generate multiple boxes with custom lid text.

How to?

You can grep the script file and check how to run, in brief for a bit more info please visit the repository I keep the parametric design scripts.

pDesign pBox

Main Box Dimensions

All dimensions are in millimeters.

  • width: The dimension along the X-axis.

  • length: The dimension along the Y-axis.

  • height: The dimension along the Z-axis.

  • wall_thickness: The thickness of the box walls.

  • N and M: These define how many box compartments are populated along the X and Y axes, respectively. The final assembly size will be (width × N) by (length × M) mm.

Lid Parameters

Lid assembly holes and dimensions are adjusted using the following parameters:

  • lid_thickness: The thickness of the lid; this also determines the size of the hinge holes.

  • lid_handle_length, lid_handle_height, and lid_handle_width: These define the size of the small handle centered on the edge of the lid.

  • lid_margin_top: Sets the vertical position of the lid from the top and defines the size of the snap-fit mechanism on the box.

  • lid_margin_sides: Defines the clearance between the lid and the inner walls of the box. 0.2mm is usually sufficient; use caution if you set this value lower.

Lid Text

  • font_name: This pulls from your system fonts, so ensure the font is installed on your OS.

  • font_kind: Specify the font style (e.g., 'bold', 'italic', etc.).

  • font_size and font_height: Used to scale your text. The ideal values depend on the box size and font type; some trial and error may be required.

  • engraved: If set to True, the text will be engraved into the lid. If False, the text will be embossed (raised).

  • text_list: Enter the strings to be placed on each lid. Regardless of the N and M values, lids will only be created for the entries provided in this list. You can use \n for multiline text.

    • Note: The script may fail if the number of items in the list exceeds the total compartments (N × M).

  • vertical_text: If set to true, the text will be oriented vertically.

Example Parameters

{
    "height": 30,
    "width": 60,
    "length": 30,
    "wall_thickness": 1.2,
    "N": 1,
    "M": 3,
    "lid_thickness": 2,
    "lid_handle_length": 10,
    "lid_handle_height": 4,
    "lid_handle_width": 3,
    "lid_margin_top": 1.8,
    "lid_margin_sides": 0.2,
    "font_name": "DejaVu Sans",
    "font_kind": "bold",
    "font_size": 6.4,
    "font_height": 0.2,
    "engraved": true,
    "vertical_text": true,
    "text_list": [
        "#1\npBox",
        "#2\npBox",
        "#3\npBox"
    ],
    "file_format": ".stl"
}

The script

# Copyright 2026 M. Alperen Sener (m.alperensener@gmail.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os import sys import json import logging import cadquery as cq from pathvalidate import sanitize_filename

_________________ BOX PARAMETERS ________________

""" All dimentions are in mm Please modify only the following dimentions, all other parameteres are only tested in print so be cautious if you play with them.

Well please use values that make sense, I have put no value check :D

""" height = 30 # in z width = 60 # in x length = 30 # in y wall_thickness = 1.2 # adjustend box wall will be 2 times of this value

following sizes are to define how many cells we want to have in both size

keep in mind that the resulting box size will be deepending on unit width

and length. Nxwidth, Mxlength

N = 1 M = 3

overall thickness of the lid. This value is also used to calculate the

assembly holes for the lid.

lid_thickness = 2 lid_handle_length = 10 lid_handle_height = 4 lid_handle_width = 3 lid_margin_top = 1.8 # Distance of the lid from top, also used for the latch lid_margin_sides = 0.2 # Distance of the lid from internal walls of the box

Text paramaters and text list

font_name = 'DejaVu Sans' # System font name font_kind = 'bold' # Set to None if innvalid font_size = 6.4 font_height = 0.8 engraved = False vertical_text = False

text_list = [ '#1\npBox', '#2\npBox', '#3\npBox']

exported file extention

file_format = '.stl'

#_________ Be careful changing following ____________

internal clearens and margins

those values are chosen with trial according to 3D printer presision and quality

latch_width = 6 latch_pitch = 0.8 lid_support_size = 6 # height and extrude size lid_support_pitch = 1.2

#_____________________ WORKFLOW _____________________

logging.basicConfig( level=logging.INFO, format='%(levelname)s: %(message)s', force=True )

file_path = None if len(sys.argv) > 1: file_path = sys.argv[1]

if file_path is not None and os.path.exists(file_path): logging.info(f"Using file: {file_path}") with open(file_path, 'r') as f: data = json.load(f) height = data.get('height', height) width = data.get('width', width) length = data.get('length', length) wall_thickness = data.get('wall_thickness', wall_thickness) N = data.get('N', N) M = data.get('M', M) lid_thickness = data.get('lid_thickness', lid_thickness) lid_margin_top = data.get('lid_margin_top', lid_margin_top) lid_margin_sides = data.get('lid_margin_sides', lid_margin_sides) font_name = data.get('font_name', font_name) font_kind = data.get('font_kind', font_kind) font_size = data.get('font_size', font_size) font_height = data.get('font_height', font_height) engraved = data.get('engraved', engraved) vertical_text = data.get('vertical_text', vertical_text) text_list = data.get('text_list', text_list) file_format = data.get('file_format', file_format) else: logging.info(f'Using parameters from script')

logging.info("Generating unit box with width:%.2fmm, length:%.2fmm, height:%.2fmm", width, length, height) logging.info("Wall thickness is %.2fmm", wall_thickness) logging.info("Compound box will be the size of %.2fx%.2fx%.2fmm", N * width, M * length, height)

folder = f'output_pbox_{N}_{M}' if not os.path.exists(folder): os.makedirs(folder)

To move the box in positive 3D space, well I don't like working in negative dimentions

easier for me to calculate things

x_offset = width / 2 y_offset = length / 2 z_offset = height / 2

logging.info("Creating box")

create the box

box = ( cq.Workplane('XY').box(width, length, height) .translate((x_offset, y_offset, z_offset)) )

calculated pocket dimentions

p_w = width - (2 * wall_thickness) p_l = length - (2 * wall_thickness) p_h = height - wall_thickness

create the box that is going to be cut out

pocket = ( cq.Workplane('XY') .box(p_w, p_l, p_h) .translate((x_offset, y_offset, wall_thickness + z_offset)) )

cut out the pocket

box = box.cut(pocket)

calculate the position of the lid assembly holes

hole_radius = lid_thickness / 2 hole_z_margin = height - (hole_radius + lid_margin_top) hole_x_margin = hole_radius + lid_margin_sides + wall_thickness

create the hole

hole = ( cq.Workplane('XZ').cylinder(length, hole_radius) .translate((hole_x_margin, length / 2, hole_z_margin)) )

cut out the hole

box = box.cut(hole)

create the latch, the thingy that holds the lid in place

translation = ( width - wall_thickness, (latch_width / 2) + y_offset, height - lid_margin_top )

latch_arc = ( cq.Workplane('XZ') .threePointArc((-latch_pitch, lid_margin_top / 2), (0, lid_margin_top)) .close() .extrude(latch_width) .translate(translation) )

box = box.union(latch_arc)

create the lid holder

Lid support is on XZ plane so the points are

lid_support_points = [ (0,0), (-lid_support_pitch, lid_support_size), (0, lid_support_size) ]

translation = ( width - wall_thickness, (lid_support_size / 2) + y_offset, height - (lid_margin_top + (hole_radius * 2) + lid_support_size), )

lid_support = ( cq.Workplane('XZ') .polyline(lid_support_points).close() .extrude(lid_support_size) .translate((translation)) )

box = box.union(lid_support)

Keep a copy of unit box

unit_box = box

populate the unit box in length and width

unit_box = box for i in range(N): box = box.union(unit_box.translate((width * i, 0,0)))

unit_array = box for i in range(M): box = box.union(unit_array.translate((0, length * i, 0)))

Create the lid base

logging.info("Creatinf lid") lw = width - (2 * (lid_margin_sides + wall_thickness)) ll = length - (2 * (lid_margin_sides + wall_thickness))

translation = (x_offset, y_offset, (height - lid_margin_top - (lid_thickness / 2)))

lid = ( cq.Workplane('XY') .box(lw, ll, lid_thickness) .faces('<X') .edges('not |Z') .fillet(hole_radius - 0.0001) .faces('>X') .edges('not |Z') .fillet(0.5) .translate(translation) )

add lid pins

lid_pin = ( cq.Workplane('XZ').cylinder(p_l + 2, hole_radius) .translate((hole_x_margin, length / 2, hole_z_margin)) .edges('>Y or <Y') .fillet(hole_radius) )

lid = lid.union(lid_pin)

add lid handle

translation = (width - wall_thickness - lid_margin_sides - 1, y_offset + lid_handle_length / 2, height - lid_margin_top)

lid_handle = ( cq.Workplane('XZ') .lineTo(-lid_handle_width, 0) .lineTo(-lid_handle_width, lid_handle_height) .lineTo(0, lid_handle_height) .threePointArc((-0.6, lid_handle_height / 2), (0, 0)) .close()
.extrude(lid_handle_length) .translate(translation) )

lid = lid.union(lid_handle) empty_lid = lid

populate the lid with given texts and export them as individual files

z_offset_text = height - lid_margin_top - font_height if engraved else height - lid_margin_top

For each text export the lid models and show

lid_pos = [(i, j) for i in range(N) for j in range(M)] lids = [lid] * len(text_list) for i, t in enumerate(text_list): logging.info("Adding lid with text: \n%s\n%s\n%s", "" * 10, t, "" * 10) x, y = lid_pos[i] translation = ((width * x) + x_offset - (lid_handle_width / 2), (length * y) + y_offset, z_offset_text)

if vertical_text:
    degree &#61; 90
else:
    degree &#61; 0

text &#61; (
    cq.Workplane(&#039;XY&#039;)
    .text(t, font_size, font_height, font&#61;font_name, kind&#61;font_kind)
    .rotate((0,0,0), (0,0,1), degree)
    .translate(translation)
    )

lids[i] &#61; lids[i].translate((width * x, length * y, 0))
if engraved:
    lids[i] &#61; lids[i].cut(text)
else:
    lids[i] &#61; lids[i].union(text)

name &#61; sanitize_filename(f&#039;{t}_{width}_{length}{file_format}&#039;)
file &#61; f&#039;{folder}/{name}&#039;
logging.info(&#34;Exporting lid file %s&#34;, file)
cq.exporters.export(lids[i], file)
if &#039;show_object&#039; in globals():
    show_object(lids[i])

Export model files

name = f'unit_box_{width}{length}{height}{file_format}' file = f'{folder}/{name}' logging.info("Exporting unit box file %s", file) cq.exporters.export(unit_box, file)

name = f'box_{N}x{M}{N * width}{M * length}_{height}{file_format}' file = f'{folder}/{name}' logging.info("Exporting box file %s", file) cq.exporters.export(box, file)

name = f'emppty_lid_{width}{length}{height}{file_format}' file = f'{folder}/{name}' logging.info("Exporting empty lid file %s", file) cq.exporters.export(empty_lid, file)

if 'show_object' in globals(): show_object(unit_box) show_object(box) show_object(empty_lid)

Printables

pBox

Publicado em 18 de jan de 2026

12
Curtidas
19
Downloads
Categoria Organizers
Tags
parametric box case storage storagebox orginizer parameterized
Licença Creative Commons — Attribution — Share Alike
Arquivos (8)
box_1x3_60_90_30.stl 139.1 KB
unit_box_60_30_30.stl 63.4 KB
#2pBox_60_30.stl 813.6 KB
emppty_lid_60_30_30.stl 470.9 KB
#3pBox_60_30.stl 892.2 KB
#1pBox_60_30.stl 761.4 KB
smd_box-box_8x8.stl 2.6 MB
smd_box-lid.stl 32 KB
Ver no Printables (abre em nova aba)

Gostou deste modelo? Crie uma conta grátis para salvar seus favoritos e voltar a eles depois.

Criar conta