1051 lines
No EOL
38 KiB
OpenSCAD
1051 lines
No EOL
38 KiB
OpenSCAD
/*
|
|
PARAMETRISK DEKORATIV INSEKT-GENERATOR v3
|
|
-----------------------------------------
|
|
For OpenSCAD (gerne Nightly, men uden eksterne biblioteker).
|
|
|
|
Formaal:
|
|
- 3D-print (STL / 3MF)
|
|
- laserskaering (SVG / DXF)
|
|
- folieskaering / vinyl
|
|
- gravering / relief
|
|
|
|
Nyheder i v3:
|
|
- Flere arts-/morfologi-presets inkl. Admiral, Paafugleoje, Blue_Morpho,
|
|
Kejserguldsmed og vandnymfe-varianter.
|
|
- Stencil/bridge-mode til laser og folie, saa indre oeer kan forbindes.
|
|
- Multi-layer output for separate krop/vinger/dekoration/pletter.
|
|
- Panel-/grid-generator til batch-produktion.
|
|
- Ornamental / Art Nouveau mode med ekstra dekorative kurver.
|
|
- Fortsat produktionsprofiler og robust 2D/3D-output.
|
|
*/
|
|
|
|
// ============================== //
|
|
// [00 - Art / output] //
|
|
// ============================== //
|
|
|
|
Artspreset = "Fri"; // [Fri,Monark,Admiral,Paafugleoje,Morpho,Blue_Morpho,Svalehale,Luna,Atlas,Guldsmed_Stor,Kejserguldsmed,Vandnymfe,Vandnymfe_Smal,Cikade,Mariehoene,Skarabee]
|
|
Bruger_Type = "Sommerfugl"; // [Sommerfugl,Natsvaermer,Guldsmed,Cikade,Bille,Fantasi]
|
|
Output = "3D_RELIEF"; // [2D_SILHOUET,2D_DEKORATION,2D_COMBINED,3D_FLAT,3D_RELIEF]
|
|
|
|
// Samlet vingefang. For guldsmed/cikade er det bredeste vingesaet.
|
|
Vingefang = 100; // [20:1:320]
|
|
// Samlet laengde fra hale til antennespids, omtrentligt.
|
|
Kropslaengde = 52; // [10:1:220]
|
|
// Global skalering i laengderetningen; 1.0 = naturligt preset-forhold.
|
|
Laengde_Skala = 1.00; // [0.50:0.01:2.20]
|
|
|
|
// ============================== //
|
|
// [01 - Produktionsprofil] //
|
|
// ============================== //
|
|
|
|
Produktionsprofil = "Brugerdefineret"; // [Brugerdefineret,3D_Print_Robust,Laser_Fin,Folie_Simpel,Gravering_Relief]
|
|
Automatisk_Produktionsoptimering = true;
|
|
|
|
// ============================== //
|
|
// [02 - Symmetri / stil] //
|
|
// ============================== //
|
|
|
|
// 0 = fuldstaendig spejlsymmetrisk. Smaa vaerdier giver organisk variation.
|
|
Asymmetri = 0.00; // [0.00:0.01:0.15]
|
|
// Giver blodere former med offset-runding.
|
|
Bloedgoering = 0.35; // [0:0.05:2]
|
|
// Minimum bredde paa tynde dekorative elementer.
|
|
Min_Feature = 0.80; // [0.20:0.05:5]
|
|
// Polygon-/kurveoploesning. Hoejere er glattere men langsommere.
|
|
Oploesning = 56; // [16:4:180]
|
|
|
|
// ============================== //
|
|
// [03 - Vinger generelt] //
|
|
// ============================== //
|
|
|
|
Vinge_Laengde = 1.00; // [0.60:0.01:1.60]
|
|
Vinge_Bredde = 1.00; // [0.50:0.01:1.80]
|
|
// Flytter vingespids frem (+) eller tilbage (-).
|
|
Vinge_Sweep = 0.00; // [-0.50:0.01:0.50]
|
|
// 0 = buttet/oval, 1 = spids.
|
|
Vingespids = 0.45; // [0.00:0.01:1.00]
|
|
// 0 = jaevn bredde, 1 = kraftigt smallere mod spidsen.
|
|
Vinge_Taper = 0.35; // [0.00:0.01:0.90]
|
|
// Rotation af hele vingeparret.
|
|
Vinge_Vinkel = 0; // [-35:1:35]
|
|
// Indtraek mellem krop og vingens geometriske start.
|
|
Vinge_Rod_Overlap = 1.5; // [0:0.25:10]
|
|
// Indhak i forvingens bagkant naer roden.
|
|
Forvinge_Indhak = 0.00; // [0.00:0.01:1.00]
|
|
// Bagvingens boelgede/scalloped bagkant.
|
|
Bagvinge_Skalop = 0.00; // [0.00:0.01:1.00]
|
|
|
|
// ============================== //
|
|
// [04 - Sommerfugl / natsvaermer]//
|
|
// ============================== //
|
|
|
|
Forvinge_Skala = 1.00; // [0.60:0.01:1.60]
|
|
Bagvinge_Skala = 0.88; // [0.50:0.01:1.60]
|
|
Bagvinge_Forskydning = -7; // [-30:0.5:20]
|
|
Bagvinge_Runding = 0.65; // [0.00:0.01:1.00]
|
|
// 0 = ingen hale; hoejere = svalehale-/luna-lignende hale.
|
|
Vinge_Hale = 0.00; // [0.00:0.01:1.00]
|
|
|
|
// ============================== //
|
|
// [05 - Guldsmed / cikade] //
|
|
// ============================== //
|
|
|
|
Langvinge_For_Skala = 1.00; // [0.60:0.01:1.30]
|
|
Langvinge_Bag_Skala = 0.92; // [0.60:0.01:1.30]
|
|
Langvinge_Separation = 8.0; // [2:0.5:30]
|
|
Langvinge_Rod_Bredde = 0.42; // [0.15:0.01:0.85]
|
|
Langvinge_Spids_Bredde = 0.55; // [0.15:0.01:1.00]
|
|
// Lille farvet / graferbar pterostigma-lignende markering naer spidsen.
|
|
Pterostigma = true;
|
|
Pterostigma_Skala = 1.00; // [0.40:0.05:2.50]
|
|
|
|
// ============================== //
|
|
// [06 - Krop] //
|
|
// ============================== //
|
|
|
|
Krop_Bredde = 7.0; // [1:0.25:30]
|
|
Bryst_Skala = 1.15; // [0.60:0.01:2.00]
|
|
Hoved_Skala = 0.90; // [0.50:0.01:2.00]
|
|
Bagkrop_Taper = 0.55; // [0.10:0.01:1.00]
|
|
Bagkrop_Segmenter = 6; // [0:1:18]
|
|
Talje = 0.15; // [0.00:0.01:0.80]
|
|
|
|
// ============================== //
|
|
// [07 - Antenner / ben] //
|
|
// ============================== //
|
|
|
|
Antenner = true;
|
|
Antenne_Laengde = 12; // [0:0.5:50]
|
|
Antenne_Spredning = 28; // [0:1:80]
|
|
Antenne_Krumning = 0.35; // [-1.00:0.05:1.00]
|
|
Antenne_Knop = 0.0; // [0:0.1:4]
|
|
// Simpel pseudo-fjering paa antenner, nyttig til natsvaermere.
|
|
Antenne_Fjering = 0.00; // [0.00:0.05:2.00]
|
|
|
|
Ben = false;
|
|
Ben_Laengde = 10; // [2:0.5:30]
|
|
Ben_Vinkel = 35; // [5:1:80]
|
|
|
|
// ============================== //
|
|
// [08 - Vingedekoration / aarer] //
|
|
// ============================== //
|
|
|
|
Vinge_Aarer = true;
|
|
Aare_Tykkelse = 0.65; // [0.20:0.05:3]
|
|
Aare_Taethed = 5; // [1:1:14]
|
|
Tvaer_Aarer = true;
|
|
Aare_Organisk = 0.55; // [0.00:0.01:1.00]
|
|
|
|
Vinge_Pletter = true;
|
|
Plet_Antal = 2; // [0:1:6]
|
|
Plet_Skala = 1.0; // [0.3:0.05:3]
|
|
Plet_Ring = true;
|
|
|
|
// Elytra-/dækningsdekor til biller / mariehoener.
|
|
Daekvinge_Soem = true;
|
|
Daekvinge_Pletter = true;
|
|
Daekvinge_Plet_Antal = 3; // [0:1:8]
|
|
|
|
// ============================== //
|
|
// [09 - Kant / udskaeringer] //
|
|
// ============================== //
|
|
|
|
Ydre_Kant = 0.0; // [0:0.1:5]
|
|
Udskaering = 0.0; // [0.00:0.05:1.00]
|
|
Udskaering_Margin = 3.0; // [0.5:0.25:10]
|
|
|
|
// ============================== //
|
|
// [10 - Ophaeng / montage] //
|
|
// ============================== //
|
|
|
|
Ophaengshul = false;
|
|
Ophaengshul_Diameter = 3.2; // [1:0.1:10]
|
|
Ophaengshul_Y = 0; // [-20:0.5:20]
|
|
|
|
// ============================== //
|
|
// [11 - 3D] //
|
|
// ============================== //
|
|
|
|
Tykkelse = 2.4; // [0.4:0.1:12]
|
|
Relief_Hoejde = 0.70; // [0.1:0.05:5]
|
|
Relief_Haevede_Detaljer = true;
|
|
|
|
// ============================== //
|
|
// [12 - Stencil / bridges] //
|
|
// ============================== //
|
|
|
|
Stencil_Mode = false;
|
|
// Brobredde til at forbinde indre oeer med yderkonturen.
|
|
Stencil_Bro_Bredde = 1.20; // [0.30:0.05:6]
|
|
// Antal broer pr. side, placeret radialt mod vingerne.
|
|
Stencil_Bro_Antal = 2; // [1:1:6]
|
|
// Hvor langt broer ma gaa ind i silhuetten.
|
|
Stencil_Bro_Laengde = 18; // [4:0.5:50]
|
|
// Tilfoej bro til ophaengshul / centrale huller.
|
|
Stencil_Centerbro = true;
|
|
|
|
// ============================== //
|
|
// [13 - Multi-layer output] //
|
|
// ============================== //
|
|
|
|
Layer_Output = "Alle"; // [Alle,Vinger,Krop,Aarer,Pletter,Stencilbroer]
|
|
// Lidt overlap mellem separate lag kan vaere nyttigt til vinyl/laserregistrering.
|
|
Layer_Overlap = 0.20; // [0:0.05:2]
|
|
|
|
// ============================== //
|
|
// [14 - Panel / batch] //
|
|
// ============================== //
|
|
|
|
Panel_Mode = false;
|
|
Panel_Kolonner = 3; // [1:1:10]
|
|
Panel_Raekker = 2; // [1:1:10]
|
|
Panel_Afstand_X = 125; // [20:1:400]
|
|
Panel_Afstand_Y = 95; // [20:1:400]
|
|
Panel_Skiftevis_Spejling = false;
|
|
Panel_Skiftevis_Rotation = 0; // [-180:5:180]
|
|
|
|
// ============================== //
|
|
// [15 - Ornamental / Art Nouveau]//
|
|
// ============================== //
|
|
|
|
Ornamental_Mode = false;
|
|
Ornamental_Styrke = 0.55; // [0.00:0.05:1.50]
|
|
Ornamental_Tykkelse = 0.70; // [0.20:0.05:4]
|
|
Ornamental_Slyng = 3; // [1:1:8]
|
|
Ornamental_Ringe = true;
|
|
|
|
// ============================== //
|
|
// [16 - Preview] //
|
|
// ============================== //
|
|
|
|
Vis_Centerlinje = false;
|
|
|
|
$fn = Oploesning;
|
|
EPS = 0.01;
|
|
|
|
// ------------------------------------------------------------
|
|
// Hjaelpefunktioner
|
|
// ------------------------------------------------------------
|
|
function clamp(v,a,b) = min(max(v,a),b);
|
|
function lerp(a,b,t) = a + (b-a)*t;
|
|
function v2lerp(a,b,t) = [lerp(a[0],b[0],t), lerp(a[1],b[1],t)];
|
|
function bz3(p0,p1,p2,p3,t) =
|
|
let(u=1-t)
|
|
[u*u*u*p0[0] + 3*u*u*t*p1[0] + 3*u*t*t*p2[0] + t*t*t*p3[0],
|
|
u*u*u*p0[1] + 3*u*u*t*p1[1] + 3*u*t*t*p2[1] + t*t*t*p3[1]];
|
|
function bez3pts(p0,p1,p2,p3,n=16) = [for(i=[0:n]) bz3(p0,p1,p2,p3,i/n)];
|
|
|
|
function profile_min_floor() =
|
|
Produktionsprofil=="3D_Print_Robust" ? 0.80 :
|
|
Produktionsprofil=="Laser_Fin" ? 0.35 :
|
|
Produktionsprofil=="Folie_Simpel" ? 0.60 :
|
|
Produktionsprofil=="Gravering_Relief" ? 0.45 : 0;
|
|
|
|
function eff_min_feature() = max(Min_Feature, Automatisk_Produktionsoptimering ? profile_min_floor() : 0);
|
|
function eff_vein_thickness() = max(Aare_Tykkelse, eff_min_feature()*0.60);
|
|
function eff_outline() = Ydre_Kant + (Automatisk_Produktionsoptimering && Produktionsprofil=="3D_Print_Robust" ? eff_min_feature()*0.20 : 0);
|
|
function eff_cutout() = Automatisk_Produktionsoptimering && (Produktionsprofil=="3D_Print_Robust" || Produktionsprofil=="Folie_Simpel") ? min(Udskaering,0.35) : Udskaering;
|
|
function eff_veins_enabled() = Automatisk_Produktionsoptimering && Produktionsprofil=="Folie_Simpel" ? false : Vinge_Aarer;
|
|
function eff_spots_enabled() = Automatisk_Produktionsoptimering && Produktionsprofil=="Folie_Simpel" ? false : Vinge_Pletter;
|
|
function eff_crossveins() = Automatisk_Produktionsoptimering && Produktionsprofil=="Folie_Simpel" ? false : Tvaer_Aarer;
|
|
function eff_deck_spots() = Automatisk_Produktionsoptimering && Produktionsprofil=="Folie_Simpel" ? false : Daekvinge_Pletter;
|
|
|
|
function chosen_family() =
|
|
Artspreset=="Fri" ? Bruger_Type :
|
|
Artspreset=="Monark" ? "Sommerfugl" :
|
|
Artspreset=="Admiral" ? "Sommerfugl" :
|
|
Artspreset=="Paafugleoje" ? "Sommerfugl" :
|
|
Artspreset=="Morpho" ? "Sommerfugl" :
|
|
Artspreset=="Blue_Morpho" ? "Sommerfugl" :
|
|
Artspreset=="Svalehale" ? "Sommerfugl" :
|
|
Artspreset=="Luna" ? "Natsvaermer" :
|
|
Artspreset=="Atlas" ? "Natsvaermer" :
|
|
Artspreset=="Guldsmed_Stor" ? "Guldsmed" :
|
|
Artspreset=="Kejserguldsmed" ? "Guldsmed" :
|
|
Artspreset=="Vandnymfe" ? "Guldsmed" :
|
|
Artspreset=="Vandnymfe_Smal" ? "Guldsmed" :
|
|
Artspreset=="Cikade" ? "Cikade" :
|
|
Artspreset=="Mariehoene" ? "Bille" :
|
|
Artspreset=="Skarabee" ? "Bille" : Bruger_Type;
|
|
|
|
function is_butterfly() = chosen_family()=="Sommerfugl" || chosen_family()=="Natsvaermer" || chosen_family()=="Fantasi";
|
|
function is_longwing() = chosen_family()=="Guldsmed" || chosen_family()=="Cikade";
|
|
function is_beetle() = chosen_family()=="Bille";
|
|
|
|
function art_adj_forwing() =
|
|
Artspreset=="Monark" ? 1.00 :
|
|
Artspreset=="Admiral" ? 0.98 :
|
|
Artspreset=="Paafugleoje" ? 1.03 :
|
|
Artspreset=="Morpho" ? 1.08 :
|
|
Artspreset=="Blue_Morpho" ? 1.10 :
|
|
Artspreset=="Svalehale" ? 1.02 :
|
|
Artspreset=="Luna" ? 0.98 :
|
|
Artspreset=="Atlas" ? 1.12 :
|
|
1.00;
|
|
function art_adj_hindwing() =
|
|
Artspreset=="Monark" ? 0.92 :
|
|
Artspreset=="Admiral" ? 0.88 :
|
|
Artspreset=="Paafugleoje" ? 0.96 :
|
|
Artspreset=="Morpho" ? 1.00 :
|
|
Artspreset=="Blue_Morpho" ? 1.02 :
|
|
Artspreset=="Svalehale" ? 0.82 :
|
|
Artspreset=="Luna" ? 0.96 :
|
|
Artspreset=="Atlas" ? 1.05 :
|
|
0.88;
|
|
function art_adj_rounding() =
|
|
Artspreset=="Morpho" ? 0.82 :
|
|
Artspreset=="Blue_Morpho" ? 0.86 :
|
|
Artspreset=="Paafugleoje" ? 0.78 :
|
|
Artspreset=="Admiral" ? 0.60 :
|
|
Artspreset=="Monark" ? 0.62 :
|
|
Artspreset=="Svalehale" ? 0.54 :
|
|
Artspreset=="Luna" ? 0.86 :
|
|
Artspreset=="Atlas" ? 0.76 :
|
|
Bagvinge_Runding;
|
|
function art_adj_tail() =
|
|
Artspreset=="Svalehale" ? 0.52 :
|
|
Artspreset=="Luna" ? 0.86 :
|
|
Artspreset=="Atlas" ? 0.18 :
|
|
Vinge_Hale;
|
|
function art_adj_tip() =
|
|
Artspreset=="Monark" ? 0.46 :
|
|
Artspreset=="Admiral" ? 0.55 :
|
|
Artspreset=="Paafugleoje" ? 0.40 :
|
|
Artspreset=="Morpho" ? 0.30 :
|
|
Artspreset=="Blue_Morpho" ? 0.26 :
|
|
Artspreset=="Svalehale" ? 0.64 :
|
|
Artspreset=="Luna" ? 0.42 :
|
|
Artspreset=="Atlas" ? 0.38 :
|
|
Vingespids;
|
|
function art_adj_taper() =
|
|
Artspreset=="Monark" ? 0.36 :
|
|
Artspreset=="Admiral" ? 0.42 :
|
|
Artspreset=="Paafugleoje" ? 0.30 :
|
|
Artspreset=="Morpho" ? 0.22 :
|
|
Artspreset=="Blue_Morpho" ? 0.18 :
|
|
Artspreset=="Svalehale" ? 0.48 :
|
|
Artspreset=="Luna" ? 0.30 :
|
|
Artspreset=="Atlas" ? 0.24 :
|
|
Vinge_Taper;
|
|
function art_adj_sweep() =
|
|
Artspreset=="Monark" ? 0.04 :
|
|
Artspreset=="Morpho" ? 0.00 :
|
|
Artspreset=="Svalehale" ? 0.06 :
|
|
Artspreset=="Luna" ? -0.08 :
|
|
Artspreset=="Atlas" ? -0.04 :
|
|
Artspreset=="Guldsmed_Stor" ? 0.02 :
|
|
Artspreset=="Kejserguldsmed" ? 0.05 :
|
|
Artspreset=="Vandnymfe" ? -0.06 :
|
|
Artspreset=="Vandnymfe_Smal" ? -0.10 :
|
|
Artspreset=="Cikade" ? 0.00 :
|
|
Vinge_Sweep;
|
|
function art_adj_fore_notch() =
|
|
Artspreset=="Svalehale" ? 0.42 :
|
|
Artspreset=="Atlas" ? 0.25 :
|
|
Forvinge_Indhak;
|
|
function art_adj_scallop() =
|
|
Artspreset=="Morpho" ? 0.12 :
|
|
Artspreset=="Svalehale" ? 0.34 :
|
|
Artspreset=="Luna" ? 0.20 :
|
|
Bagvinge_Skalop;
|
|
function art_adj_long_sep() =
|
|
Artspreset=="Guldsmed_Stor" ? 11 :
|
|
Artspreset=="Kejserguldsmed" ? 12 :
|
|
Artspreset=="Vandnymfe" ? 7 :
|
|
Artspreset=="Vandnymfe_Smal" ? 5.5 :
|
|
Artspreset=="Cikade" ? 8 :
|
|
Langvinge_Separation;
|
|
function art_adj_root_width() =
|
|
Artspreset=="Guldsmed_Stor" ? 0.34 :
|
|
Artspreset=="Kejserguldsmed" ? 0.38 :
|
|
Artspreset=="Vandnymfe" ? 0.26 :
|
|
Artspreset=="Vandnymfe_Smal" ? 0.20 :
|
|
Artspreset=="Cikade" ? 0.48 :
|
|
Langvinge_Rod_Bredde;
|
|
function art_adj_tip_width() =
|
|
Artspreset=="Guldsmed_Stor" ? 0.46 :
|
|
Artspreset=="Kejserguldsmed" ? 0.50 :
|
|
Artspreset=="Vandnymfe" ? 0.34 :
|
|
Artspreset=="Vandnymfe_Smal" ? 0.28 :
|
|
Artspreset=="Cikade" ? 0.66 :
|
|
Langvinge_Spids_Bredde;
|
|
function art_adj_thorax() =
|
|
Artspreset=="Guldsmed_Stor" ? 1.25 :
|
|
Artspreset=="Vandnymfe" ? 1.05 :
|
|
Artspreset=="Cikade" ? 1.15 :
|
|
Artspreset=="Mariehoene" ? 1.35 :
|
|
Artspreset=="Skarabee" ? 1.22 :
|
|
Bryst_Skala;
|
|
function art_adj_head() =
|
|
Artspreset=="Guldsmed_Stor" ? 1.18 :
|
|
Artspreset=="Vandnymfe" ? 1.06 :
|
|
Artspreset=="Cikade" ? 1.20 :
|
|
Artspreset=="Mariehoene" ? 0.88 :
|
|
Artspreset=="Skarabee" ? 0.92 :
|
|
Hoved_Skala;
|
|
function art_adj_ab_taper() =
|
|
Artspreset=="Guldsmed_Stor" ? 0.38 :
|
|
Artspreset=="Vandnymfe" ? 0.32 :
|
|
Artspreset=="Cikade" ? 0.72 :
|
|
Artspreset=="Mariehoene" ? 0.90 :
|
|
Artspreset=="Skarabee" ? 0.74 :
|
|
Bagkrop_Taper;
|
|
function art_adj_segments() =
|
|
Artspreset=="Guldsmed_Stor" ? 9 :
|
|
Artspreset=="Vandnymfe" ? 8 :
|
|
Artspreset=="Cikade" ? 7 :
|
|
Artspreset=="Mariehoene" ? 4 :
|
|
Artspreset=="Skarabee" ? 5 :
|
|
Bagkrop_Segmenter;
|
|
function art_body_w_factor() =
|
|
Artspreset=="Mariehoene" ? 1.55 :
|
|
Artspreset=="Skarabee" ? 1.35 :
|
|
Artspreset=="Guldsmed_Stor" ? 0.72 :
|
|
Artspreset=="Vandnymfe" ? 0.58 :
|
|
Artspreset=="Cikade" ? 1.22 :
|
|
1.00;
|
|
function art_body_len_factor() =
|
|
Artspreset=="Guldsmed_Stor" ? 1.22 :
|
|
Artspreset=="Vandnymfe" ? 1.14 :
|
|
Artspreset=="Mariehoene" ? 0.70 :
|
|
Artspreset=="Skarabee" ? 0.82 :
|
|
1.00;
|
|
function art_ant_len() =
|
|
Artspreset=="Luna" ? 16 :
|
|
Artspreset=="Atlas" ? 15 :
|
|
Artspreset=="Guldsmed_Stor" ? 5 :
|
|
Artspreset=="Vandnymfe" ? 5 :
|
|
Artspreset=="Cikade" ? 6 :
|
|
Antenne_Laengde;
|
|
function art_ant_spread() =
|
|
Artspreset=="Luna" ? 34 :
|
|
Artspreset=="Atlas" ? 28 :
|
|
Artspreset=="Guldsmed_Stor" ? 18 :
|
|
Artspreset=="Vandnymfe" ? 14 :
|
|
Artspreset=="Cikade" ? 18 :
|
|
Antenne_Spredning;
|
|
function art_ant_fan() =
|
|
Artspreset=="Luna" ? 1.25 :
|
|
Artspreset=="Atlas" ? 1.00 :
|
|
Antenne_Fjering;
|
|
function art_vein_density() =
|
|
Artspreset=="Monark" ? 6 :
|
|
Artspreset=="Admiral" ? 5 :
|
|
Artspreset=="Paafugleoje" ? 5 :
|
|
Artspreset=="Morpho" ? 5 :
|
|
Artspreset=="Blue_Morpho" ? 5 :
|
|
Artspreset=="Svalehale" ? 5 :
|
|
Artspreset=="Luna" ? 4 :
|
|
Artspreset=="Atlas" ? 4 :
|
|
Artspreset=="Guldsmed_Stor" ? 7 :
|
|
Artspreset=="Kejserguldsmed" ? 8 :
|
|
Artspreset=="Vandnymfe" ? 6 :
|
|
Artspreset=="Vandnymfe_Smal" ? 6 :
|
|
Artspreset=="Cikade" ? 8 :
|
|
Aare_Taethed;
|
|
function art_spot_count() =
|
|
Artspreset=="Monark" ? 1 :
|
|
Artspreset=="Admiral" ? 2 :
|
|
Artspreset=="Paafugleoje" ? 3 :
|
|
Artspreset=="Morpho" ? 0 :
|
|
Artspreset=="Blue_Morpho" ? 0 :
|
|
Artspreset=="Svalehale" ? 2 :
|
|
Artspreset=="Luna" ? 2 :
|
|
Artspreset=="Atlas" ? 1 :
|
|
Plet_Antal;
|
|
function art_spots_default() =
|
|
Artspreset=="Morpho" ? false :
|
|
Artspreset=="Blue_Morpho" ? false :
|
|
Artspreset=="Guldsmed_Stor" ? false :
|
|
Artspreset=="Kejserguldsmed" ? false :
|
|
Artspreset=="Vandnymfe_Smal" ? false :
|
|
Artspreset=="Vandnymfe" ? false :
|
|
Artspreset=="Cikade" ? false :
|
|
is_butterfly();
|
|
|
|
function eff_body_w() = Krop_Bredde * art_body_w_factor() * (chosen_family()=="Guldsmed" ? 0.65 : chosen_family()=="Cikade" ? 1.15 : chosen_family()=="Bille" ? 1.35 : 1);
|
|
function eff_body_len() = Kropslaengde * Laengde_Skala * art_body_len_factor() * (chosen_family()=="Guldsmed" ? 1.15 : chosen_family()=="Bille" ? 0.80 : 1);
|
|
function eff_forwing_scale() = Forvinge_Skala * art_adj_forwing();
|
|
function eff_hindwing_scale() = Bagvinge_Skala * art_adj_hindwing();
|
|
function eff_hindwing_round() = clamp(Artspreset=="Fri" ? Bagvinge_Runding : art_adj_rounding(),0,1);
|
|
function eff_wing_tail() = clamp(Artspreset=="Fri" ? Vinge_Hale : art_adj_tail(),0,1);
|
|
function eff_tip() = clamp(Artspreset=="Fri" ? Vingespids : art_adj_tip(),0,1);
|
|
function eff_taper() = clamp(Artspreset=="Fri" ? Vinge_Taper : art_adj_taper(),0,0.95);
|
|
function eff_sweep() = Artspreset=="Fri" ? Vinge_Sweep : art_adj_sweep();
|
|
function eff_notch() = clamp(Artspreset=="Fri" ? Forvinge_Indhak : art_adj_fore_notch(),0,1);
|
|
function eff_scallop() = clamp(Artspreset=="Fri" ? Bagvinge_Skalop : art_adj_scallop(),0,1);
|
|
function eff_long_sep() = Artspreset=="Fri" ? Langvinge_Separation : art_adj_long_sep();
|
|
function eff_long_rootw() = Artspreset=="Fri" ? Langvinge_Rod_Bredde : art_adj_root_width();
|
|
function eff_long_tipw() = Artspreset=="Fri" ? Langvinge_Spids_Bredde : art_adj_tip_width();
|
|
function eff_thorax_scale() = Artspreset=="Fri" ? Bryst_Skala : art_adj_thorax();
|
|
function eff_head_scale() = Artspreset=="Fri" ? Hoved_Skala : art_adj_head();
|
|
function eff_ab_taper() = Artspreset=="Fri" ? Bagkrop_Taper : art_adj_ab_taper();
|
|
function eff_segments() = Artspreset=="Fri" ? Bagkrop_Segmenter : art_adj_segments();
|
|
function eff_ant_len() = Artspreset=="Fri" ? Antenne_Laengde : art_ant_len();
|
|
function eff_ant_spread() = Artspreset=="Fri" ? Antenne_Spredning : art_ant_spread();
|
|
function eff_ant_fan() = Artspreset=="Fri" ? Antenne_Fjering : art_ant_fan();
|
|
function eff_vein_density_count() = Artspreset=="Fri" ? Aare_Taethed : art_vein_density();
|
|
function eff_spot_count() = Artspreset=="Fri" ? Plet_Antal : art_spot_count();
|
|
function eff_spot_state() = eff_spots_enabled() && (Artspreset=="Fri" ? Vinge_Pletter : art_spots_default());
|
|
|
|
module stroke_polyline(pts, w=1) {
|
|
ww=max(w,eff_min_feature());
|
|
for(i=[0:len(pts)-2]) hull() {
|
|
translate(pts[i]) circle(d=ww);
|
|
translate(pts[i+1]) circle(d=ww);
|
|
}
|
|
}
|
|
|
|
module stroke_bezier(p0,p1,p2,p3,w=1,n=14) {
|
|
stroke_polyline(bez3pts(p0,p1,p2,p3,n),w);
|
|
}
|
|
|
|
module soft2d(r=Bloedgoering) {
|
|
if(r>0) offset(r=r) offset(delta=-r) children();
|
|
else children();
|
|
}
|
|
|
|
module mirrored_pair() {
|
|
children();
|
|
mirror([1,0,0]) children();
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Vingegeometri
|
|
// ------------------------------------------------------------
|
|
module butterfly_forewing_half(scale_fac=1) {
|
|
span = Vingefang/2 * 0.96 * Vinge_Laengde * eff_forwing_scale() * scale_fac;
|
|
chord = Vingefang * 0.29 * Vinge_Bredde * scale_fac * (chosen_family()=="Natsvaermer" ? 0.78 : 1);
|
|
rootx = eff_body_w()/2 - Vinge_Rod_Overlap;
|
|
rooty = eff_body_len()*0.08;
|
|
sweep = eff_sweep() * chord;
|
|
tipy = rooty + chord*(0.45+sweep/chord);
|
|
tip_round = 1-eff_tip();
|
|
taper=eff_taper();
|
|
notch=eff_notch();
|
|
|
|
p0=[rootx, rooty-chord*0.28];
|
|
p1=[rootx+span*0.22, rooty-chord*0.48];
|
|
p2=[rootx+span*0.72, tipy-chord*(0.42-0.15*tip_round)];
|
|
p3=[rootx+span, tipy];
|
|
p4=[rootx+span*(0.82+0.10*tip_round), tipy+chord*(0.16+0.10*tip_round)];
|
|
p5=[rootx+span*(0.45+0.08*taper), rooty+chord*(0.46-0.12*taper)];
|
|
pn=[rootx+span*(0.16+0.10*notch), rooty+chord*(0.34-0.18*notch)];
|
|
p6=[rootx, rooty+chord*0.28];
|
|
|
|
rotate(Vinge_Vinkel)
|
|
soft2d()
|
|
polygon(concat(
|
|
bez3pts(p0,p1,p2,p3,10),
|
|
bez3pts(p3,p4,p4,p5,8),
|
|
bez3pts(p5,pn,pn,p6,8)
|
|
));
|
|
}
|
|
|
|
module butterfly_hindwing_half(scale_fac=1) {
|
|
span = Vingefang/2 * 0.72 * Vinge_Laengde * eff_hindwing_scale() * scale_fac;
|
|
chord = Vingefang * 0.28 * Vinge_Bredde * scale_fac;
|
|
rootx=eff_body_w()/2 - Vinge_Rod_Overlap;
|
|
rooty=-eff_body_len()*0.04 + Bagvinge_Forskydning;
|
|
round=eff_hindwing_round();
|
|
tail=eff_wing_tail();
|
|
scal=eff_scallop();
|
|
|
|
p0=[rootx,rooty+chord*0.35];
|
|
p1=[rootx+span*0.22,rooty+chord*0.46];
|
|
p2=[rootx+span*0.78,rooty+chord*0.40];
|
|
p3=[rootx+span,rooty+chord*(0.05+0.10*eff_sweep())];
|
|
p4=[rootx+span*(0.96-0.12*round),rooty-chord*(0.28+0.20*round)];
|
|
pd=[rootx+span*(0.68-0.08*scal),rooty-chord*(0.42+0.22*scal)];
|
|
tailp=[rootx+span*(0.62+0.10*tail),rooty-chord*(0.45+0.50*tail)];
|
|
p5=[rootx+span*(0.34+0.12*round),rooty-chord*(0.40+0.18*round)];
|
|
p6=[rootx,rooty-chord*0.22];
|
|
|
|
rotate(Vinge_Vinkel*0.45)
|
|
soft2d()
|
|
polygon(concat(
|
|
bez3pts(p0,p1,p2,p3,9),
|
|
tail>0.02 ? concat(bez3pts(p3,p4,p4,tailp,6), bez3pts(tailp,pd,p5,p6,8))
|
|
: concat(bez3pts(p3,p4,pd,p5,8), bez3pts(p5,p5,p6,p6,3))
|
|
));
|
|
}
|
|
|
|
module longwing_half(yshift=0, scale_fac=1, rear=false) {
|
|
span=Vingefang/2 * 0.98 * Vinge_Laengde * scale_fac;
|
|
width=Vingefang * (chosen_family()=="Cikade" ? 0.16 : 0.105) * Vinge_Bredde * (rear ? 1.06 : 1);
|
|
rootx=eff_body_w()/2 - Vinge_Rod_Overlap;
|
|
rooty=yshift;
|
|
rootw=width*eff_long_rootw();
|
|
tipw=width*eff_long_tipw();
|
|
sweep=eff_sweep()*width*1.4;
|
|
|
|
p0=[rootx,rooty-rootw/2];
|
|
p1=[rootx+span*0.28,rooty-width*0.56];
|
|
p2=[rootx+span*0.77,rooty+sweep-width*0.46];
|
|
p3=[rootx+span,rooty+sweep-tipw*0.08];
|
|
p4=[rootx+span,rooty+sweep+tipw*0.18];
|
|
p5=[rootx+span*0.70,rooty+sweep+width*0.48];
|
|
p6=[rootx+span*0.22,rooty+width*0.48];
|
|
p7=[rootx,rooty+rootw/2];
|
|
|
|
rotate(Vinge_Vinkel)
|
|
soft2d()
|
|
polygon(concat(bez3pts(p0,p1,p2,p3,10),bez3pts(p3,p4,p5,p6,8),bez3pts(p6,p6,p7,p7,3)));
|
|
}
|
|
|
|
module beetle_elytron_half() {
|
|
span=Vingefang/2*(Artspreset=="Mariehoene" ? 0.46 : 0.53)*Vinge_Bredde;
|
|
len=eff_body_len()*(Artspreset=="Mariehoene" ? 0.56 : 0.62);
|
|
rootx=eff_body_w()*0.10;
|
|
y0=-eff_body_len()*0.12;
|
|
soft2d()
|
|
polygon(concat(
|
|
bez3pts([rootx,y0+len*0.48],[span*0.65,y0+len*0.55],[span,y0+len*0.20],[span,y0-len*0.08],10),
|
|
bez3pts([span,y0-len*0.08],[span*0.95,y0-len*0.48],[span*0.42,y0-len*0.58],[rootx,y0-len*0.52],10)
|
|
));
|
|
}
|
|
|
|
module wings_2d() {
|
|
if(is_butterfly()) {
|
|
mirrored_pair() {
|
|
butterfly_forewing_half(1 + Asymmetri);
|
|
butterfly_hindwing_half(1 + Asymmetri*0.5);
|
|
}
|
|
}
|
|
else if(is_longwing()) {
|
|
sep=eff_long_sep();
|
|
mirrored_pair() {
|
|
longwing_half(+sep/2, Langvinge_For_Skala*(1+Asymmetri), false);
|
|
longwing_half(-sep/2, Langvinge_Bag_Skala*(1+Asymmetri*0.5), true);
|
|
}
|
|
}
|
|
else if(is_beetle()) {
|
|
mirrored_pair() beetle_elytron_half();
|
|
mirrored_pair() rotate(-8) scale([1.12,0.72]) longwing_half(-3,0.72,false);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Krop, hoved, antenner, ben
|
|
// ------------------------------------------------------------
|
|
module body_core_2d() {
|
|
L=eff_body_len();
|
|
W=eff_body_w();
|
|
head_y=L*0.32;
|
|
thor_y=L*0.12;
|
|
abdomen_y=-L*0.13;
|
|
abdomen_len=L*0.53;
|
|
|
|
union() {
|
|
hull() {
|
|
translate([0,abdomen_y+abdomen_len*0.35]) circle(d=W*(0.82-0.28*Talje));
|
|
translate([0,abdomen_y-abdomen_len*0.48]) circle(d=W*eff_ab_taper());
|
|
}
|
|
translate([0,thor_y]) scale([eff_thorax_scale(),1.18]) circle(d=W);
|
|
hull() {
|
|
translate([0,thor_y+W*0.30]) circle(d=W*0.48);
|
|
translate([0,head_y]) scale([eff_head_scale(),0.90*eff_head_scale()]) circle(d=W);
|
|
}
|
|
}
|
|
}
|
|
|
|
module antenna_half(side=1) {
|
|
L=eff_body_len(); W=eff_body_w();
|
|
y=L*0.37;
|
|
antL=eff_ant_len();
|
|
fan=eff_ant_fan();
|
|
p0=[side*W*0.20,y];
|
|
p1=[side*(W*0.35 + antL*0.18), y+antL*0.30];
|
|
p2=[side*(W*0.35 + antL*(0.48+0.12*Antenne_Krumning)), y+antL*0.68];
|
|
p3=[side*(W*0.30 + antL*sin(eff_ant_spread())), y+antL];
|
|
stroke_bezier(p0,p1,p2,p3,eff_min_feature(),14);
|
|
|
|
if(fan>0.02)
|
|
for(t=[0.18:0.12:0.82]) {
|
|
pt=bz3(p0,p1,p2,p3,t);
|
|
dir=[side*fan*antL*(0.08+0.08*t), fan*antL*(0.01+0.01*t)];
|
|
stroke_polyline([pt, pt+[dir[0],dir[1]]], eff_min_feature()*0.65);
|
|
stroke_polyline([pt, pt+[dir[0],-dir[1]]], eff_min_feature()*0.65);
|
|
}
|
|
|
|
if(Antenne_Knop>0) translate(p3) circle(d=max(Antenne_Knop,eff_min_feature()));
|
|
}
|
|
|
|
module legs_2d() {
|
|
if(Ben) {
|
|
L=eff_body_len(); W=eff_body_w();
|
|
for(yy=[-0.03,0.10,0.20])
|
|
for(s=[-1,1]) {
|
|
root=[s*W*0.30,L*yy];
|
|
knee=[s*(W*0.65+Ben_Laengde*0.38),L*yy-Ben_Laengde*0.12];
|
|
tip=[s*(W*0.65+Ben_Laengde*cos(Ben_Vinkel)),L*yy-Ben_Laengde*sin(Ben_Vinkel)];
|
|
stroke_polyline([root,knee,tip],eff_min_feature());
|
|
}
|
|
}
|
|
}
|
|
|
|
module body_2d() {
|
|
union() {
|
|
soft2d(Bloedgoering*0.5) body_core_2d();
|
|
if(Antenner) { antenna_half(-1); antenna_half(1); }
|
|
legs_2d();
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Dekoration: aarer, pletter, kropssegmenter
|
|
// ------------------------------------------------------------
|
|
module butterfly_veins_half(fore=true) {
|
|
span=Vingefang/2 * (fore ? 0.90*eff_forwing_scale() : 0.66*eff_hindwing_scale()) * Vinge_Laengde;
|
|
chord=Vingefang * (fore ? 0.24 : 0.23) * Vinge_Bredde;
|
|
root=[eff_body_w()/2, fore ? eff_body_len()*0.08 : -eff_body_len()*0.04+Bagvinge_Forskydning];
|
|
baseang=fore ? Vinge_Vinkel : Vinge_Vinkel*0.45;
|
|
|
|
rotate(baseang) {
|
|
stroke_bezier(root,
|
|
[root[0]+span*0.25,root[1]+chord*0.02],
|
|
[root[0]+span*0.58,root[1]+chord*(fore?0.15:-0.08)],
|
|
[root[0]+span*0.90,root[1]+chord*(fore?0.28:-0.12)], eff_vein_thickness(),14);
|
|
|
|
for(i=[1:eff_vein_density_count()]) {
|
|
t=i/(eff_vein_density_count()+1);
|
|
start=[root[0]+span*(0.07+0.50*t), root[1]+chord*(fore?0.04:-0.02)];
|
|
ey = fore ? lerp(-0.31,0.48,t) : lerp(-0.38,0.30,t);
|
|
end=[root[0]+span*lerp(0.50,0.95,t), root[1]+chord*ey];
|
|
bend=Aare_Organisk*chord*0.10*sin(i*37);
|
|
stroke_bezier(start,
|
|
v2lerp(start,end,0.35)+[0,bend],
|
|
v2lerp(start,end,0.72)+[0,-bend*0.4],end,
|
|
eff_vein_thickness(),9);
|
|
}
|
|
|
|
if(eff_crossveins())
|
|
for(i=[1:max(1,eff_vein_density_count()-1)]) {
|
|
t=i/eff_vein_density_count();
|
|
x=root[0]+span*(0.34+0.45*t);
|
|
stroke_bezier([x,root[1]-chord*0.18],[x+span*0.03,root[1]-chord*0.05],
|
|
[x-span*0.02,root[1]+chord*0.15],[x,root[1]+chord*0.30],
|
|
eff_vein_thickness()*0.75,7);
|
|
}
|
|
}
|
|
}
|
|
|
|
module longwing_veins_half(yshift=0,scale_fac=1) {
|
|
span=Vingefang/2*0.91*Vinge_Laengde*scale_fac;
|
|
width=Vingefang*(chosen_family()=="Cikade"?0.14:0.09)*Vinge_Bredde;
|
|
root=[eff_body_w()/2,yshift];
|
|
rotate(Vinge_Vinkel) {
|
|
for(j=[-1,0,1])
|
|
stroke_bezier(root,
|
|
[root[0]+span*0.28,root[1]+j*width*0.22],
|
|
[root[0]+span*0.66,root[1]+j*width*0.26],
|
|
[root[0]+span*0.92,root[1]+j*width*0.16],eff_vein_thickness(),12);
|
|
if(eff_crossveins())
|
|
for(i=[1:eff_vein_density_count()]) {
|
|
t=i/(eff_vein_density_count()+1);
|
|
x=root[0]+span*(0.15+0.70*t);
|
|
w=width*(0.35+0.55*sin(t*180));
|
|
stroke_bezier([x,root[1]-w],[x+span*0.025,root[1]-w*0.3],
|
|
[x-span*0.015,root[1]+w*0.3],[x,root[1]+w],eff_vein_thickness()*0.70,6);
|
|
}
|
|
}
|
|
}
|
|
|
|
module pterostigma_half(yshift=0,scale_fac=1) {
|
|
if(Pterostigma && (chosen_family()=="Guldsmed" || chosen_family()=="Cikade")) {
|
|
span=Vingefang/2*0.91*Vinge_Laengde*scale_fac;
|
|
width=Vingefang*(chosen_family()=="Cikade"?0.14:0.09)*Vinge_Bredde;
|
|
root=[eff_body_w()/2,yshift];
|
|
rotate(Vinge_Vinkel)
|
|
translate([root[0]+span*0.82,root[1]+width*0.18])
|
|
scale([1.8,0.75]) circle(d=max(width*0.22*Pterostigma_Skala, eff_min_feature()*1.4));
|
|
}
|
|
}
|
|
|
|
module wing_spots_half() {
|
|
if(eff_spot_state() && eff_spot_count()>0 && is_butterfly()) {
|
|
span=Vingefang/2*0.90*Vinge_Laengde*eff_forwing_scale();
|
|
chord=Vingefang*0.24*Vinge_Bredde;
|
|
root=[eff_body_w()/2,eff_body_len()*0.08];
|
|
rotate(Vinge_Vinkel)
|
|
for(i=[0:eff_spot_count()-1]) {
|
|
t=(i+1)/(eff_spot_count()+1);
|
|
c=[root[0]+span*lerp(0.52,0.78,t),root[1]+chord*lerp(-0.08,0.25,t)];
|
|
d=Vingefang*0.045*Plet_Skala*(1-0.15*i);
|
|
if(Plet_Ring) {
|
|
difference() {
|
|
translate(c) circle(d=d);
|
|
translate(c) circle(d=max(d-2*max(eff_vein_thickness(),eff_min_feature()),eff_min_feature()));
|
|
}
|
|
} else translate(c) circle(d=d);
|
|
}
|
|
}
|
|
}
|
|
|
|
module beetle_spots_half() {
|
|
if(eff_deck_spots() && is_beetle()) {
|
|
span=Vingefang/2*(Artspreset=="Mariehoene" ? 0.42 : 0.45);
|
|
y0=-eff_body_len()*0.12;
|
|
for(i=[0:Daekvinge_Plet_Antal-1]) {
|
|
t=(i+1)/(Daekvinge_Plet_Antal+1);
|
|
px=eff_body_w()*0.18 + span*lerp(0.22,0.82,t);
|
|
py=y0 + eff_body_len()*lerp(0.10,-0.28,t) + (i%2==0 ? 2.0 : -1.5);
|
|
translate([px,py]) scale([1.15,0.95]) circle(d=Vingefang*0.045*(Artspreset=="Mariehoene" ? 1.0 : 0.75));
|
|
}
|
|
}
|
|
}
|
|
|
|
module body_decoration_2d() {
|
|
L=eff_body_len(); W=eff_body_w();
|
|
if(eff_segments()>0)
|
|
for(i=[0:eff_segments()-1]) {
|
|
t=(i+0.75)/(eff_segments()+1);
|
|
y=lerp(-L*0.38,L*0.05,t);
|
|
ww=lerp(W*eff_ab_taper(),W*0.75,t);
|
|
stroke_polyline([[-ww*0.34,y],[ww*0.34,y]],max(eff_vein_thickness(),eff_min_feature()));
|
|
}
|
|
stroke_polyline([[0,L*0.03],[0,L*0.22]],max(eff_vein_thickness(),eff_min_feature()));
|
|
|
|
if(Daekvinge_Soem && is_beetle())
|
|
stroke_polyline([[0,-L*0.36],[0,L*0.18]],max(eff_vein_thickness(),eff_min_feature()));
|
|
|
|
if(chosen_family()=="Cikade") {
|
|
translate([ W*0.28, L*0.30]) circle(d=max(W*0.18, eff_min_feature()));
|
|
translate([-W*0.28, L*0.30]) circle(d=max(W*0.18, eff_min_feature()));
|
|
}
|
|
}
|
|
|
|
module decorations_raw_2d() {
|
|
intersection() {
|
|
union() {
|
|
if(eff_veins_enabled()) {
|
|
if(is_butterfly()) mirrored_pair() {
|
|
butterfly_veins_half(true);
|
|
butterfly_veins_half(false);
|
|
}
|
|
else if(is_longwing()) mirrored_pair() {
|
|
longwing_veins_half(+eff_long_sep()/2,Langvinge_For_Skala);
|
|
longwing_veins_half(-eff_long_sep()/2,Langvinge_Bag_Skala);
|
|
pterostigma_half(+eff_long_sep()/2,Langvinge_For_Skala);
|
|
pterostigma_half(-eff_long_sep()/2,Langvinge_Bag_Skala);
|
|
}
|
|
else if(is_beetle()) mirrored_pair() {
|
|
stroke_bezier([eff_body_w()*0.15,eff_body_len()*0.18],
|
|
[Vingefang*0.13,eff_body_len()*0.12],
|
|
[Vingefang*0.20,-eff_body_len()*0.15],
|
|
[Vingefang*0.17,-eff_body_len()*0.35],eff_vein_thickness(),12);
|
|
}
|
|
}
|
|
wing_spots_half();
|
|
mirror([1,0,0]) wing_spots_half();
|
|
beetle_spots_half();
|
|
mirror([1,0,0]) beetle_spots_half();
|
|
}
|
|
wings_2d();
|
|
}
|
|
body_decoration_2d();
|
|
ornamental_2d();
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Ornamental / Art Nouveau
|
|
// ------------------------------------------------------------
|
|
module ornamental_half() {
|
|
if(Ornamental_Mode && Ornamental_Styrke>0) {
|
|
W=Vingefang;
|
|
L=eff_body_len();
|
|
w=max(Ornamental_Tykkelse,eff_min_feature()*0.65);
|
|
for(i=[0:Ornamental_Slyng-1]) {
|
|
t=(i+1)/(Ornamental_Slyng+1);
|
|
p0=[eff_body_w()*0.40, lerp(-L*0.22,L*0.24,t)];
|
|
p1=[W*lerp(0.10,0.17,t), lerp(-L*0.34,L*0.38,t)];
|
|
p2=[W*lerp(0.25,0.36,t), lerp(L*0.18,-L*0.12,t)];
|
|
p3=[W*lerp(0.34,0.46,t), lerp(-L*0.05,L*0.30,t)];
|
|
stroke_bezier(p0,p1,p2,p3,w*Ornamental_Styrke,16);
|
|
if(Ornamental_Ringe)
|
|
translate(p3) difference() {
|
|
circle(d=W*(0.018+0.008*t)*Ornamental_Styrke+2*w);
|
|
circle(d=max(W*(0.018+0.008*t)*Ornamental_Styrke,w));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
module ornamental_2d() {
|
|
intersection() {
|
|
mirrored_pair() ornamental_half();
|
|
wings_2d();
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Stencil bridges
|
|
// ------------------------------------------------------------
|
|
module stencil_bridges_half() {
|
|
if(Stencil_Mode) {
|
|
bw=max(Stencil_Bro_Bredde,eff_min_feature());
|
|
for(i=[0:Stencil_Bro_Antal-1]) {
|
|
t=(i+1)/(Stencil_Bro_Antal+1);
|
|
y=lerp(-eff_body_len()*0.18,eff_body_len()*0.20,t);
|
|
x0=eff_body_w()*0.25;
|
|
x1=x0+Stencil_Bro_Laengde*(0.72+0.28*t);
|
|
stroke_polyline([[x0,y],[x1,y+(t-0.5)*Stencil_Bro_Laengde*0.18]],bw);
|
|
}
|
|
}
|
|
}
|
|
|
|
module stencil_bridges_2d() {
|
|
union() {
|
|
mirrored_pair() stencil_bridges_half();
|
|
if(Stencil_Mode && Stencil_Centerbro && Ophaengshul) {
|
|
bw=max(Stencil_Bro_Bredde,eff_min_feature());
|
|
y=eff_body_len()*0.32+Ophaengshul_Y;
|
|
translate([-bw/2,y-Ophaengshul_Diameter/2-0.2]) square([bw,Ophaengshul_Diameter+0.4]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Silhuet, udskaeringer, montage
|
|
// ------------------------------------------------------------
|
|
module cutout_pattern_half() {
|
|
if(eff_cutout()>0) {
|
|
span=Vingefang/2*0.78;
|
|
for(i=[1:3]) {
|
|
yy=lerp(-Vingefang*0.12,Vingefang*0.14,i/4);
|
|
translate([eff_body_w()/2+span*(0.25+0.16*i),yy])
|
|
scale([1.5,1]) circle(d=Vingefang*0.05*eff_cutout());
|
|
}
|
|
}
|
|
}
|
|
|
|
module silhouette_raw_2d() {
|
|
union() { wings_2d(); body_2d(); }
|
|
}
|
|
|
|
module silhouette_2d() {
|
|
union() {
|
|
difference() {
|
|
if(eff_outline()>0) offset(r=eff_outline()) offset(r=0.06) offset(delta=-0.06) silhouette_raw_2d();
|
|
else offset(r=0.06) offset(delta=-0.06) silhouette_raw_2d();
|
|
|
|
if(eff_cutout()>0)
|
|
intersection() {
|
|
offset(delta=-Udskaering_Margin) wings_2d();
|
|
union() { cutout_pattern_half(); mirror([1,0,0]) cutout_pattern_half(); }
|
|
}
|
|
|
|
if(Ophaengshul)
|
|
translate([0,eff_body_len()*0.32+Ophaengshul_Y]) circle(d=Ophaengshul_Diameter);
|
|
}
|
|
if(Stencil_Mode)
|
|
intersection() { stencil_bridges_2d(); silhouette_raw_2d(); }
|
|
}
|
|
}
|
|
|
|
module decoration_2d() {
|
|
decorations_raw_2d();
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Multi-layer helpers
|
|
// ------------------------------------------------------------
|
|
module wing_layer_2d() {
|
|
if(Layer_Overlap>0) offset(delta=Layer_Overlap) wings_2d(); else wings_2d();
|
|
}
|
|
module body_layer_2d() {
|
|
if(Layer_Overlap>0) offset(delta=Layer_Overlap) body_2d(); else body_2d();
|
|
}
|
|
module spot_layer_2d() {
|
|
intersection() {
|
|
union() {
|
|
wing_spots_half(); mirror([1,0,0]) wing_spots_half();
|
|
beetle_spots_half(); mirror([1,0,0]) beetle_spots_half();
|
|
if(is_longwing()) mirrored_pair() {
|
|
pterostigma_half(+eff_long_sep()/2,Langvinge_For_Skala);
|
|
pterostigma_half(-eff_long_sep()/2,Langvinge_Bag_Skala);
|
|
}
|
|
}
|
|
wings_2d();
|
|
}
|
|
}
|
|
module vein_layer_2d() {
|
|
difference() { decoration_2d(); spot_layer_2d(); }
|
|
}
|
|
module selected_layer_2d() {
|
|
if(Layer_Output=="Vinger") wing_layer_2d();
|
|
else if(Layer_Output=="Krop") body_layer_2d();
|
|
else if(Layer_Output=="Aarer") vein_layer_2d();
|
|
else if(Layer_Output=="Pletter") spot_layer_2d();
|
|
else if(Layer_Output=="Stencilbroer") stencil_bridges_2d();
|
|
else union() { silhouette_2d(); decoration_2d(); }
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Panel / batch layout
|
|
// ------------------------------------------------------------
|
|
module panelize() {
|
|
for(r=[0:Panel_Raekker-1])
|
|
for(c=[0:Panel_Kolonner-1]) {
|
|
idx=r*Panel_Kolonner+c;
|
|
tx=(c-(Panel_Kolonner-1)/2)*Panel_Afstand_X;
|
|
ty=((Panel_Raekker-1)/2-r)*Panel_Afstand_Y;
|
|
translate([tx,ty,0])
|
|
rotate(idx%2==1 ? Panel_Skiftevis_Rotation : 0)
|
|
if(Panel_Skiftevis_Spejling && idx%2==1) mirror([1,0,0]) children();
|
|
else children();
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// 3D
|
|
// ------------------------------------------------------------
|
|
module extrude_soft(height=2) {
|
|
linear_extrude(height=height) children();
|
|
}
|
|
|
|
module model_3d_flat() {
|
|
extrude_soft(Tykkelse) silhouette_2d();
|
|
}
|
|
|
|
module model_3d_relief() {
|
|
if(Relief_Haevede_Detaljer) {
|
|
union() {
|
|
extrude_soft(Tykkelse) silhouette_2d();
|
|
translate([0,0,Tykkelse-EPS])
|
|
linear_extrude(height=Relief_Hoejde+EPS)
|
|
intersection() { decoration_2d(); silhouette_2d(); }
|
|
}
|
|
} else {
|
|
difference() {
|
|
extrude_soft(Tykkelse) silhouette_2d();
|
|
translate([0,0,max(0,Tykkelse-Relief_Hoejde)])
|
|
linear_extrude(height=Relief_Hoejde+EPS*2)
|
|
intersection() { decoration_2d(); silhouette_2d(); }
|
|
}
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Top-level output
|
|
// ------------------------------------------------------------
|
|
module single_output() {
|
|
if(Output=="2D_SILHOUET")
|
|
if(Layer_Output=="Alle") silhouette_2d(); else selected_layer_2d();
|
|
else if(Output=="2D_DEKORATION")
|
|
if(Layer_Output=="Alle") decoration_2d(); else selected_layer_2d();
|
|
else if(Output=="2D_COMBINED")
|
|
if(Layer_Output=="Alle") union() { silhouette_2d(); decoration_2d(); } else selected_layer_2d();
|
|
else if(Output=="3D_FLAT")
|
|
model_3d_flat();
|
|
else
|
|
model_3d_relief();
|
|
}
|
|
|
|
if(Panel_Mode)
|
|
panelize() single_output();
|
|
else
|
|
single_output();
|
|
|
|
if(Vis_Centerlinje && $preview && !Panel_Mode)
|
|
color("red") translate([-0.15,-eff_body_len()/2,0]) square([0.3,eff_body_len()]); |