Blog

Publikujeme praktické texty z výroby našich filamentů v ČR i z praxe zakázkového 3D tisku a 3D skenování. Vysvětlujeme nastavení pro spolehlivý FDM tisk, přilnavost a stabilitu procesu, sdílíme testy teplotní a chemické odolnosti filamentů a ukazujeme postupy 3D modelování a reverse inženýringu od mesh k CADu. Cílem je, aby každý článek pomohl rychle zvolit vhodný filament, správně nastavit tisk a dodat technicky spolehlivý díl.

Výpis článků

Sušení filamentů

Sušení filamentů

from PIL import Image, ImageDraw, ImageFont
import os, math

out_dir="/mnt/data"

def get_font(size=40, bold=False):
candidates = [
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf" if bold else "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf" if bold else "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
]
for p in candidates:
if os.path.exists(p):
return ImageFont.truetype(p, size=size)
return ImageFont.load_default()

def rounded_rect(draw, xy, r, fill, outline=None, width=2):
draw.rounded_rectangle(list(xy), radius=r, fill=fill, outline=outline, width=width)

def arrow(draw, start, end, color, width=6, head=18):
x0,y0=start; x1,y1=end
draw.line([x0,y0,x1,y1], fill=color, width=width)
ang=math.atan2(y1-y0,x1-x0)
hx=x1-head*math.cos(ang)
hy=y1-head*math.sin(ang)
left=(hx + head*0.6*math.cos(ang+math.pi/2), hy + head*0.6*math.sin(ang+math.pi/2))
right=(hx + head*0.6*math.cos(ang-math.pi/2), hy + head*0.6*math.sin(ang-math.pi/2))
draw.polygon([end,left,right], fill=color)

def text_bbox(draw, text, font):
return draw.textbbox((0,0), text, font=font)

def wrap_text(draw, text, font, max_width):
words=text.split()
lines=[]
cur=""
for w in words:
test=(cur+" "+w).strip()
if draw.textlength(test, font=font) <= max_width:
cur=test
else:
if cur:
lines.append(cur)
cur=w
if cur:
lines.append(cur)
return lines

def draw_wrapped(draw, box, text, font, fill=(0,0,0), align="left", line_spacing=1.25):
x0,y0,x1,y1=box
max_w=x1-x0
lines=wrap_text(draw, text, font, max_w)
line_h = (text_bbox(draw, "Ag", font)[3]-text_bbox(draw,"Ag",font)[1])
total_h = int(len(lines)*line_h*line_spacing)
y = y0
for ln in lines:
w = draw.textlength(ln, font=font)
if align=="center":
x = x0 + (max_w - w)/2
elif align=="right":
x = x1 - w
else:
x = x0
draw.text((x,y), ln, font=font, fill=fill)
y += int(line_h*line_spacing)
if y > y1: # safety: stop drawing if overflow
break
return total_h

def fit_font_to_box(draw, text, box, max_size, bold=False, min_size=14, line_spacing=1.25):
x0,y0,x1,y1=box
max_w=x1-x0
max_h=y1-y0
lo=min_size
hi=max_size
best=lo
while lo<=hi:
mid=(lo+hi)//2
f=get_font(mid, bold)
lines=wrap_text(draw, text, f, max_w)
line_h=text_bbox(draw,"Ag",f)[3]-text_bbox(draw,"Ag",f)[1]
total_h=int(len(lines)*line_h*line_spacing)
if total_h <= max_h:
best=mid
lo=mid+1
else:
hi=mid-1
return get_font(best, bold)

def create_moisture_hero_v3(path):
W,H=1600,900
img=Image.new("RGB",(W,H),(245,247,250))
d=ImageDraw.Draw(img)
margin=60

# Title and subtitle boxes with auto-fit
title_box=(margin, 28, W-margin, 94)
title_text="Vlhký vs. suchý filament"
title_font=fit_font_to_box(d, title_text, title_box, max_size=60, bold=True, min_size=34)
draw_wrapped(d, title_box, title_text, title_font, fill=(20,25,30))

sub_box=(margin, 95, W-margin, 140)
sub_text="Jak to vypadá při extruzi z trysky (bublinky, pára, rozdíl v povrchu extruze)"
sub_font=fit_font_to_box(d, sub_text, sub_box, max_size=30, bold=False, min_size=18)
draw_wrapped(d, sub_box, sub_text, sub_font, fill=(70,80,90))

# Panels
panel_top=160
panel_h=665
gap=40
panel_w=(W-2*margin-gap)//2
left=(margin,panel_top,margin+panel_w,panel_top+panel_h)
right=(margin+panel_w+gap,panel_top,margin+panel_w+gap+panel_w,panel_top+panel_h)
rounded_rect(d,left,32,fill=(255,255,255), outline=(220,225,232), width=3)
rounded_rect(d,right,32,fill=(255,255,255), outline=(220,225,232), width=3)

head_font=get_font(42, True)
d.text((left[0]+38,left[1]+28),"SUCHÝ", font=head_font, fill=(25,120,70))
d.text((right[0]+38,right[1]+28),"VLHKÝ", font=head_font, fill=(180,70,60))

def draw_nozzle(panel, wet=False):
x0,y0,x1,y1=panel
cx=(x0+x1)//2

# Hotend block
block_w=420; block_h=120
bx0=cx-block_w//2; by0=y0+100
rounded_rect(d,(bx0,by0,bx0+block_w,by0+block_h),24,fill=(232,236,242), outline=(200,205,212), width=3)
label="Hotend"
lf=fit_font_to_box(d,label,(bx0+18,by0+18,bx0+block_w-18,by0+block_h-18),max_size=30,bold=True,min_size=18)
draw_wrapped(d,(bx0+18,by0+34,bx0+block_w-18,by0+block_h-18),label,lf,fill=(60,70,80),align="left")

# Nozzle
top_y=by0+block_h
bottom_y=top_y+155
top_w=170; bottom_w=76
poly=[(cx-top_w//2, top_y),(cx+top_w//2, top_y),(cx+bottom_w//2, bottom_y),(cx-bottom_w//2, bottom_y)]
d.polygon(poly, fill=(210,176,120), outline=(160,130,80))
d.ellipse((cx-10,bottom_y-12,cx+10,bottom_y+8), fill=(90,80,70))

# Extrusion
extr_y0=bottom_y+10
extr_len=330
d.line((cx,extr_y0,cx,extr_y0+extr_len), fill=(60,60,65), width=18)

if not wet:
d.line((cx-5,extr_y0+10,cx-5,extr_y0+extr_len-10), fill=(95,95,100), width=4)
# left texts box
tbox=(x0+48, y0+260, x1-48, y0+345)
txt="Bez praskání\nHladká extruze"
# manual with two lines; ensure fit
f=fit_font_to_box(d, "Bez praskání", (tbox[0],tbox[1],tbox[2],tbox[1]+40), max_size=30, bold=False, min_size=18)
d.text((tbox[0],tbox[1]),"Bez praskání", font=f, fill=(60,70,80))
d.text((tbox[0],tbox[1]+40),"Hladká extruze", font=f, fill=(60,70,80))
arrow(d,(cx+175,extr_y0+130),(cx+25,extr_y0+130),color=(25,120,70),width=5,head=20)
d.text((cx+185,extr_y0+104),"čistá extruze", font=get_font(22, True), fill=(25,120,70))
else:
# bubbles outlines
for i in range(10):
t=i/9
y=extr_y0+int(t*extr_len)
r=8+(i%3)*3
ox=(i%2)*12-6
d.ellipse((cx-r+ox,y-r,cx+r+ox,y+r), outline=(230,230,230), width=3)
# roughness marks
for i in range(12):
y=extr_y0+30+i*22
d.line((cx-14,y,cx+14,y+2), fill=(30,30,34), width=3)
# steam curls
sx=cx+110; sy=bottom_y-25
for k in range(3):
pts=[]
for j in range(58):
a=j/57*math.pi*1.6
x=sx+k*35+18*math.cos(a)
y=sy-j*3+10*math.sin(a)
pts.append((x,y))
d.line(pts, fill=(180,190,200), width=4)
# right texts
f=get_font(28, False)
d.text((x0+48,y0+260),"Praskání / pára", font=f, fill=(60,70,80))
d.text((x0+48,y0+300),"Bublinky v extruzi", font=f, fill=(60,70,80))
arrow(d,(cx+175,extr_y0+130),(cx+25,extr_y0+130),color=(180,70,60),width=5,head=20)
d.text((cx+185,extr_y0+104),"bubliny", font=get_font(22, True), fill=(180,70,60))

draw_nozzle(left, wet=False)
draw_nozzle(right, wet=True)

# Footer tip wrapped
tip_box=(margin, 830, W-margin, 888)
tip_text="Tip: Pokud slyšíte praskání a vidíte bublinky, začněte sušením (a tiskněte ideálně z dryboxu)."
tip_font=fit_font_to_box(d, tip_text, tip_box, max_size=26, bold=False, min_size=16)
draw_wrapped(d, tip_box, tip_text, tip_font, fill=(70,80,90))

img.save(path,"PNG")

def create_bubbles_closeup_v3(path):
W,H=1400,900
img=Image.new("RGB",(W,H),(245,247,250))
d=ImageDraw.Draw(img)
margin=60

title_box=(margin, 28, W-margin, 102)
title="Detail: bublinky při extruzi z trysky"
title_font=fit_font_to_box(d, title, title_box, max_size=54, bold=True, min_size=30)
draw_wrapped(d, title_box, title, title_font, fill=(20,25,30))

sub_box=(margin, 102, W-margin, 150)
sub="Vlhkost → pára v trysce → mikro-bubliny, hrubší povrch, vyšší pravděpodobnost stringingu"
sub_font=fit_font_to_box(d, sub, sub_box, max_size=28, bold=False, min_size=18)
draw_wrapped(d, sub_box, sub, sub_font, fill=(70,80,90))

panel=(margin,170,W-margin,H-70)
rounded_rect(d,panel,36,fill=(255,255,255), outline=(220,225,232), width=3)

cx=(panel[0]+panel[2])//2
top=panel[1]+80

# nozzle
top_w=360; bottom_w=160
top_y=top; bottom_y=top+330
poly=[(cx-top_w//2, top_y),(cx+top_w//2, top_y),(cx+bottom_w//2, bottom_y),(cx-bottom_w//2, bottom_y)]
d.polygon(poly, fill=(210,176,120), outline=(160,130,80))
d.ellipse((cx-18,bottom_y-20,cx+18,bottom_y+10), fill=(90,80,70))

# extrusion
extr_y0=bottom_y+10
extr_len=320
d.line((cx,extr_y0,cx,extr_y0+extr_len), fill=(60,60,65), width=26)

# bubbles
for i in range(18):
y=extr_y0+20+i*16
r=10+(i%4)*3
ox=((i%3)-1)*18
d.ellipse((cx-r+ox,y-r,cx+r+ox,y+r), outline=(210,215,222), width=3)

# steam
for side in [-1,1]:
sx=cx+side*210
sy=top+250
for k in range(2):
pts=[]
for j in range(70):
a=j/69*math.pi*1.9
x=sx + k*35*side + 22*math.cos(a)*side
y=sy - j*3 + 12*math.sin(a)
pts.append((x,y))
d.line(pts, fill=(180,190,200), width=5)

call_font=get_font(30, True)
small=get_font(24, False)

# Left box
bx,by=panel[0]+70,panel[1]+350
bw,bh=440,210
rounded_rect(d,(bx,by,bx+bw,by+bh),26,fill=(248,249,251), outline=(220,225,232), width=2)
d.text((bx+22,by+16),"Co uvidíte", font=call_font, fill=(20,25,30))
items=["Praskání z trysky","Bublinky v proudu","Hrubší povrch","Více stringingu"]
y=by+70
for it in items:
d.ellipse((bx+22,y+10,bx+36,y+24), fill=(180,70,60))
# wrap each item if needed
box=(bx+48,y, bx+bw-18, y+44)
f=fit_font_to_box(d, it, box, max_size=24, bold=False, min_size=18)
draw_wrapped(d, box, it, f, fill=(70,80,90))
y+=38

arrow(d,(bx+bw, by+110),(cx-40, extr_y0+120), color=(180,70,60), width=6, head=22)

# Right box
fx,fy=panel[2]-70-bw,panel[1]+350
rounded_rect(d,(fx,fy,fx+bw,fy+bh),26,fill=(248,249,251), outline=(220,225,232), width=2)
d.text((fx+22,fy+16),"První kroky", font=call_font, fill=(20,25,30))
items2=["Usušit filament","Snížit teplotu o 5–10 °C","Zkontrolovat retrakci","Tisk z dryboxu"]
y=fy+70
for it in items2:
d.rectangle((fx+22,y+10,fx+36,y+24), fill=(25,120,70))
box=(fx+48,y, fx+bw-18, y+52)
f=fit_font_to_box(d, it, box, max_size=24, bold=False, min_size=16)
draw_wrapped(d, box, it, f, fill=(70,80,90))
y+=38

arrow(d,(fx, fy+110),(cx+40, extr_y0+160), color=(25,120,70), width=6, head=22)

img.save(path,"PNG")

def create_stringing_infographic_v2(path):
W,H=1600,900
img=Image.new("RGB",(W,H),(245,247,250))
d=ImageDraw.Draw(img)
margin=60

# Title + subtitle with wrapping
title_box=(margin, 28, W-margin, 108)
title="Stringing (strunování): jak vypadá a jak rychle najít příčinu"
title_font=fit_font_to_box(d, title, title_box, max_size=54, bold=True, min_size=28)
draw_wrapped(d, title_box, title, title_font, fill=(20,25,30))

sub_box=(margin, 108, W-margin, 155)
sub="Vlásečnice mezi prvky modelu. Nejčastěji kombinace: vlhkost + teplota + retrakce."
sub_font=fit_font_to_box(d, sub, sub_box, max_size=28, bold=False, min_size=18)
draw_wrapped(d, sub_box, sub, sub_font, fill=(70,80,90))

panel=(margin,170,W-margin,H-70)
rounded_rect(d,panel,36,fill=(255,255,255), outline=(220,225,232), width=3)

# Left illustration area
left_area=(panel[0]+60,panel[1]+70,panel[0]+800,panel[3]-60)
gy=left_area[3]-60
d.line((left_area[0],gy,left_area[2],gy), fill=(200,205,212), width=5)

tower_w=170; tower_h=420
tx1=left_area[0]+140
tx2=left_area[0]+470
ty=gy-tower_h
rounded_rect(d,(tx1,ty,tx1+tower_w,gy),28,fill=(232,236,242), outline=(200,205,212), width=3)
rounded_rect(d,(tx2,ty+50,tx2+tower_w,gy),28,fill=(232,236,242), outline=(200,205,212), width=3)

# strings
for i in range(22):
x_start=tx1+tower_w-10
y_start=ty+40+i*14
x_end=tx2+10
y_end=ty+90+i*12
pts=[]
for j in range(9):
t=j/8
x=x_start+(x_end-x_start)*t
y=y_start+(y_end-y_start)*t+math.sin(t*math.pi*2)*4
pts.append((x,y))
d.line(pts, fill=(110,110,115), width=2)

# nozzle
cx=(tx1+tx2+tower_w)//2
noz_y=left_area[1]+40
d.polygon([(cx-70,noz_y),(cx+70,noz_y),(cx+30,noz_y+120),(cx-30,noz_y+120)], fill=(210,176,120), outline=(160,130,80))
d.ellipse((cx-10,noz_y+112,cx+10,noz_y+138), fill=(90,80,70))

# label for left area
la_title_box=(left_area[0], left_area[1]-10, left_area[2], left_area[1]+30)
f=fit_font_to_box(d, "Ukázka: dvě věže", la_title_box, max_size=30, bold=True, min_size=18)
draw_wrapped(d, la_title_box, "Ukázka: dvě věže", f, fill=(20,25,30))

arrow(d,(cx+120,noz_y+160),(tx2+40,ty+120),color=(180,70,60),width=5,head=20)
d.text((cx+130,noz_y+132),"vlásečnice", font=get_font(24, True), fill=(180,70,60))

# Right diagnostic box
right_area=(panel[0]+850,panel[1]+70,panel[2]-60,panel[3]-60)
rounded_rect(d,right_area,28,fill=(248,249,251), outline=(220,225,232), width=2)

header_box=(right_area[0]+24,right_area[1]+18,right_area[2]-24,right_area[1]+62)
header="Rychlá diagnostika (pořadí)"
hf=fit_font_to_box(d, header, header_box, max_size=34, bold=True, min_size=18)
draw_wrapped(d, header_box, header, hf, fill=(20,25,30))

items=[
("1) Vlhkost filamentu", "praskání/bublinky → nejdřív usušit"),
("2) Teplota trysky", "snížit o 5–15 °C, test"),
("3) Retrakce", "vzdálenost + rychlost, test po 1 změně"),
("4) Travel pohyby", "zvýšit rychlost přejezdů, wipe/coast dle sliceru"),
("5) Chlazení", "u PCTG/PETG často pomůže víc ofuku"),
]

y=right_area[1]+80
bullet=(25,120,70)
title_f=get_font(26, True)
desc_color=(70,80,90)

for t,desc in items:
# bullet
d.rectangle((right_area[0]+24,y+10,right_area[0]+38,y+24), fill=bullet)
# title wrapped to box
tbox=(right_area[0]+50,y,right_area[2]-24,y+38)
tf=fit_font_to_box(d, t, tbox, max_size=26, bold=True, min_size=18)
draw_wrapped(d, tbox, t, tf, fill=(20,25,30))
y += 34

# desc wrapped
desc_box=(right_area[0]+50,y,right_area[2]-24,y+70)
df=fit_font_to_box(d, desc, desc_box, max_size=22, bold=False, min_size=16)
# compute lines to adjust y
lines=wrap_text(d, desc, df, (desc_box[2]-desc_box[0]))
line_h=text_bbox(d,"Ag",df)[3]-text_bbox(d,"Ag",df)[1]
for ln in lines:
d.text((desc_box[0], y), ln, font=df, fill=desc_color)
y += int(line_h*1.25)
y += 10 # spacing

# Note wrapped at bottom
note="Pozn.: Stringing často není jen retrakce. Vlhkost + vysoká teplota bývají nejčastější dvojice."
note_box=(right_area[0]+24, right_area[3]-70, right_area[2]-24, right_area[3]-18)
nf=fit_font_to_box(d, note, note_box, max_size=20, bold=False, min_size=14)
draw_wrapped(d, note_box, note, nf, fill=(90,100,110))

img.save(path,"PNG")

paths={
"hero_v3": os.path.join(out_dir,"3dsphynx_infografika_vlhkost_hero_v3.png"),
"bubbles_v3": os.path.join(out_dir,"3dsphynx_infografika_bublinky_tryska_v3.png"),
"stringing_v2": os.path.join(out_dir,"3dsphynx_infografika_stringing_v2.png"),
}
create_moisture_hero_v3(paths["hero_v3"])
create_bubbles_closeup_v3(paths["bubbles_v3"])
create_stringing_infographic_v2(paths["stringing_v2"])
paths

Vítejte na blogu 3D Sphynx

Publikujeme praktické texty z výroby našich filamentů a z praxe zakázkového 3D tisku a 3D skenování. Najdete zde testy, návody a případové studie.

Témata

  • Filamenty průvodce: testy, sušení, proces.
  • Návody k 3D tisku: první vrstva, kalibrace, slicer.
  • 3D skenování: technologie, workflow, post-process.
  • 3D modelování: parametrika, tolerance, exporty.
  • Reverse inženýring: mesh → CAD, validace.
  • Praxe a udržitelnost: případové studie, EKO.

Jak píšeme

  • Ověřitelně: zveřejňujeme nastavení a měření.
  • Replikovatelně: postupy krok za krokem.
  • Transparentně: uvádíme stroje, trysky a profily.
  • Stručně: krátké odstavce a checklisty.
  • Aktualizovaně: pravidelné revize a datum změny.

Kontakt

Tip na téma? Napište na info@3dsphynx.cz

Ovládací prvky výpisu

2 položek celkem