From ed500abd39f071b0a091759f6d02ad43466973b3 Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Thu, 25 Dec 2014 23:12:32 +0530 Subject: [PATCH 001/174] indent unindent icons added --- images/Decrease-Indent-32 (3).png | Bin 0 -> 4196 bytes images/Increase-Indent-32.png | Bin 0 -> 4196 bytes openscad.pro.user | 201 ++++++++++++++++++++++++++++++ openscad.qrc | 124 +++++++++--------- src/MainWindow.ui | 37 ++++-- 5 files changed, 292 insertions(+), 70 deletions(-) create mode 100644 images/Decrease-Indent-32 (3).png create mode 100644 images/Increase-Indent-32.png create mode 100644 openscad.pro.user diff --git a/images/Decrease-Indent-32 (3).png b/images/Decrease-Indent-32 (3).png new file mode 100644 index 0000000000000000000000000000000000000000..8697e9d054f102f138731e4fec31125e35117cd6 GIT binary patch literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0J_ z8UmvsfEoh2y1GWBU{h05DGdz`E+Do+$C{d&HbB6HY6AhDxVZR#Qm~SeQY%os7B)Q+ z5)%In3=DV(ScxhPG{}q;40M2uv9U1+5SyW66B83NS65fkLIBk{>AD$Ov1K|Tjr4oVNw z($eRRjEsa}azxW=YHC@eU|>+2feiQd_NLr&qFsrm5EksPoFFSJdtOFHW_PQ)zZ?^fH?vfg|pq=-NoG8+(ghZ$qoSK z^F|<^iVFi%x)01ys3V?(LI9|~9VSj!8rc!RBHe+mmcuLqIRcnHb6|Xu=#Y>Q8B%aW zLNo~i9kY-W j1*3{bLtr!nMqCK^Eq`CK=KB?CkjFh;{an^LB{Ts5Hv#~n literal 0 HcmV?d00001 diff --git a/images/Increase-Indent-32.png b/images/Increase-Indent-32.png new file mode 100644 index 0000000000000000000000000000000000000000..3be843cd206f1561b264a04c1b6cfe7da2628309 GIT binary patch literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0J_ z8UmvsfIkGZwY9A@G&F3mU;#@@OEFztT_aL3e%r9fN=r+B78e))j|DratE*>W5yz$$ zE{4Sl{6c1CW=6)w#%5SBAJ73}KnIwSg7MpiLsm~uPr=U4jt_@4ZG{aD4HcxMq#n!4 z${w|~wMB76Mn(o(YHBJUDVSu}0)5T}w0tipu0f7K4hc<7%`8bt$^WEak{tljfXflU zbfKfBrj|ttCg=be8JYdqFwpnMVJRM4bPzO{SOqXk@X^2^e-A7l^oTW+Bz10XZX(z) zupnv$ISOPskZlGs6j%Vo$;rt*#)akO + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Qt 4.8.6 (qt4) + Qt 4.8.6 (qt4) + {90222843-28c9-4a66-ac82-99bd31ae7263} + 0 + 0 + 0 + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + false + CONFIG+=experimental + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + openscad + + Qt4ProjectManager.Qt4RunConfiguration:/home/shaina/letsstartopenscad/openscad/openscad.pro + + openscad.pro + false + false + + 3768 + true + false + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {56f57d1a-fe9b-42b2-a96b-3ac76cf7565f} + + + ProjectExplorer.Project.Updater.FileVersion + 15 + + diff --git a/openscad.qrc b/openscad.qrc index f202c2d4..34be07fc 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -1,63 +1,65 @@ - - icons/openscad.png - icons/button.png - icons/background-welcome-screen.svg - icons/prefsFeatures.png - icons/stopbutton.png - icons/prefsAdvanced.png - icons/prefs3DView.png - icons/prefsEditor.png - icons/prefsUpdate.png - icons/flattr.png - src/AboutDialog.html - images/Arrowhead-Right-32.png - images/export.png - images/axes.png - images/export-white.png - images/back.png - images/Document-New-128.png - images/front.png - images/grid.png - images/Open-128.png - images/openscad.png - images/right.png - images/Save-128.png - images/up.png - images/bottom.png - images/left.png - images/blackUp.png - images/blackNew.png - images/blackRender.png - images/Rotation-32.png - images/Shape-Cube-32.png - images/Open-32.png - images/Save-32.png - images/blackbottom.png - images/blackleft (copy).png - images/rightright.png - images/blackfront.png - images/blackback.png - images/blackaxes.png - images/zoomin.png - images/zoomout.png - images/wireframe1.png - images/surface.png - images/Zoom-In-32.png - images/Zoom-Out-32.png - images/zoom-all.png - images/zoom-all-white.png - images/surfaceWhite.png - images/wireframeWhite.png - images/orthogonal.png - images/cross.png - images/perspective1.png - images/Preview-32.png - images/animate.png - images/Preview-32 (1).png - images/orthogonalwhite.png - images/perspective1white.png - images/crosswhite.png - icons/background.png - + + icons/openscad.png + icons/button.png + icons/background-welcome-screen.svg + icons/prefsFeatures.png + icons/stopbutton.png + icons/prefsAdvanced.png + icons/prefs3DView.png + icons/prefsEditor.png + icons/prefsUpdate.png + icons/flattr.png + src/AboutDialog.html + images/Arrowhead-Right-32.png + images/export.png + images/axes.png + images/export-white.png + images/back.png + images/Document-New-128.png + images/front.png + images/grid.png + images/Open-128.png + images/openscad.png + images/right.png + images/Save-128.png + images/up.png + images/bottom.png + images/left.png + images/blackUp.png + images/blackNew.png + images/blackRender.png + images/Rotation-32.png + images/Shape-Cube-32.png + images/Open-32.png + images/Save-32.png + images/blackbottom.png + images/blackleft (copy).png + images/rightright.png + images/blackfront.png + images/blackback.png + images/blackaxes.png + images/zoomin.png + images/zoomout.png + images/wireframe1.png + images/surface.png + images/Zoom-In-32.png + images/Zoom-Out-32.png + images/zoom-all.png + images/zoom-all-white.png + images/surfaceWhite.png + images/wireframeWhite.png + images/orthogonal.png + images/cross.png + images/perspective1.png + images/Preview-32.png + images/animate.png + images/Preview-32 (1).png + images/orthogonalwhite.png + images/perspective1white.png + images/crosswhite.png + icons/background.png + images/Decrease-Indent-32 (3).png + images/Increase-Indent-32.png + diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 74365644..97ddb8ce 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -170,7 +170,7 @@ 0 0 1397 - 22 + 25 @@ -346,6 +346,8 @@ + + @@ -603,6 +605,10 @@ + + + :/images/Increase-Indent-32.png:/images/Increase-Indent-32.png + &Indent @@ -610,14 +616,6 @@ Ctrl+I - - - U&nindent - - - Ctrl+Shift+I - - C&omment @@ -1137,6 +1135,27 @@ Hide toolbars + + + + :/images/Decrease-Indent-32 (1).png:/images/Decrease-Indent-32 (1).png + + + Unindent + + + + + + :/images/Decrease-Indent-32 (3).png:/images/Decrease-Indent-32 (3).png + + + U&nindent + + + Ctrl+Shift+I + + From 3bfa28c83dbf55b126afb6baf2a24b7dedfc4af8 Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Thu, 25 Dec 2014 23:27:28 +0530 Subject: [PATCH 002/174] indent image name changed --- ...dent-32 (3).png => Decrease-Indent-32.png} | Bin openscad.pro.user | 201 ------------------ openscad.qrc | 2 +- 3 files changed, 1 insertion(+), 202 deletions(-) rename images/{Decrease-Indent-32 (3).png => Decrease-Indent-32.png} (100%) delete mode 100644 openscad.pro.user diff --git a/images/Decrease-Indent-32 (3).png b/images/Decrease-Indent-32.png similarity index 100% rename from images/Decrease-Indent-32 (3).png rename to images/Decrease-Indent-32.png diff --git a/openscad.pro.user b/openscad.pro.user deleted file mode 100644 index 53b4bd75..00000000 --- a/openscad.pro.user +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - true - 1 - true - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - ProjectExplorer.Project.Target.0 - - Qt 4.8.6 (qt4) - Qt 4.8.6 (qt4) - {90222843-28c9-4a66-ac82-99bd31ae7263} - 0 - 0 - 0 - - - - - true - qmake - - QtProjectManager.QMakeBuildStep - false - false - CONFIG+=experimental - false - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Release - - Qt4ProjectManager.Qt4BuildConfiguration - 0 - true - - 1 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - Deploy locally - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - openscad - - Qt4ProjectManager.Qt4RunConfiguration:/home/shaina/letsstartopenscad/openscad/openscad.pro - - openscad.pro - false - false - - 3768 - true - false - false - false - true - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.EnvironmentId - {56f57d1a-fe9b-42b2-a96b-3ac76cf7565f} - - - ProjectExplorer.Project.Updater.FileVersion - 15 - - diff --git a/openscad.qrc b/openscad.qrc index 34be07fc..46e8173f 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -59,7 +59,7 @@ images/perspective1white.png images/crosswhite.png icons/background.png - images/Decrease-Indent-32 (3).png images/Increase-Indent-32.png + images/Decrease-Indent-32.png From 040aac5e8f24759838817b2d87703ac6a0846f62 Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Thu, 25 Dec 2014 23:34:28 +0530 Subject: [PATCH 003/174] Indent icon added --- src/MainWindow.ui | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 97ddb8ce..b67213a6 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -1137,7 +1137,7 @@ - + :/images/Decrease-Indent-32 (1).png:/images/Decrease-Indent-32 (1).png @@ -1147,7 +1147,7 @@ - :/images/Decrease-Indent-32 (3).png:/images/Decrease-Indent-32 (3).png + :/images/Decrease-Indent-32.png:/images/Decrease-Indent-32.png U&nindent From 2654bf95755d5cd6ad8127e976b9e83b0b14a7ab Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Thu, 25 Dec 2014 23:44:41 +0530 Subject: [PATCH 004/174] unindent duplicate image removed --- src/MainWindow.ui | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index b67213a6..011ef440 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -1135,15 +1135,6 @@ Hide toolbars - - - - :/images/Decrease-Indent-32 (1).png:/images/Decrease-Indent-32 (1).png - - - Unindent - - From 295f257bf878bf0984fd79cf5025b2d5679b74ae Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Fri, 26 Dec 2014 00:35:13 +0530 Subject: [PATCH 005/174] undo redo icons added --- images/Command-Redo-32.png | Bin 0 -> 4196 bytes images/Command-Undo-32.png | Bin 0 -> 4196 bytes openscad.qrc | 2 ++ src/MainWindow.ui | 10 ++++++++++ 4 files changed, 12 insertions(+) create mode 100644 images/Command-Redo-32.png create mode 100644 images/Command-Undo-32.png diff --git a/images/Command-Redo-32.png b/images/Command-Redo-32.png new file mode 100644 index 0000000000000000000000000000000000000000..f9c77c5e42d009bf1759b765901181325d8eb4d7 GIT binary patch literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0J_ z8UmvsFhoKiJ3E_6S6A0UQBko(K|x`roSfWZAU$14NvXg92x#Vwu&^)|6%~~<85xUm2&y_nUteEFR#x^XE=#eA14Cx3iHV62HirO1kp-JLRxv$2JtZkA zsmJJ+0DbxxXvs!kR4fHLZmYDk^h+#it^yq)f^4w5y1E}Qgkq4zaI$S}ZFzteT}L(; z$Um*6rR9{Al*ELrF(@dAMMFcw59kmS^+3lR4h#$g`&d&`(?U{G@+&aS6d~)y$p$Ly zN46a3+nN6U{&<7W(b17hUS579vOZt}EdnN74WQ+(LE=F9cAS>NB!EFD1Jv*nW)LX2 zK{)^>kB@eBb>#qt)Jd3LU=+RvhRl5!ALxL&`1FJ2fUd5BX#fSAv9YlfK}|>sfN947 zsQ)j_3}hPUne|9Yu`_`_*bmbL)UX)4D*U3r_=lSTGYdq6(gl820_3OkW4MP`GtEPmZUS)eQ7 z@dwO4J_I!&DFBw3dB_%`vw;ryi=-So6FJoaeN%>A6{e`Fs%n^ogaq92=$6Cym^#r! zfC;5pOiXMy2m|AiaK44=H#If20!En=A&h3-D0egjMnhmU1O`3?a-46NmH60kfL!9~ L>gTe~DWM4fVkqY> literal 0 HcmV?d00001 diff --git a/images/Command-Undo-32.png b/images/Command-Undo-32.png new file mode 100644 index 0000000000000000000000000000000000000000..2deea680ca7872b6725dc7883a8b7bc3f14d6a56 GIT binary patch literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0J_ z8UmvsFhoPZ(9lprNl7V7K|x`voSfWZAU#)6QL#!(OUofLGLnU6-qO&}@Q{_2Jt;0O z{vQ{XmX?01tgKw(?(PmMfJp=S`T1B~Z)a!61@z@&T$W-JmywaVtgWrBL6QrAK6Fu4 zRZT$#BVh< zH9wd_d3pKO$OZ!~ehhSEOh7;YMiA@h=$HW=wHry1KfAqXOvCsYseoQo5$5rWXM_QKW5bZ1{klcnLEPWHyQdY#d+^ zFNbMBrhy6UW?o(%6E;2g#DJD|!ps4haT}jnupCekN&-UCeA>sy2P4rDG7y-n++bz^ z)75`M>KT9zI1kf+P6K_jxUQ~_q)@Q5wA4a2hoA$1QSca913DX6{B{#G1W5rf`xzmd zfh2{U2@HYn$QrP*Ra8{+u11CK_J-is`E4#9?GNPga y7;PnDVq&{N80fj_Xx5E#M?+vV1V%$(;6os<@icons/background.png images/Increase-Indent-32.png images/Decrease-Indent-32.png + images/Command-Undo-32.png + images/Command-Redo-32.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 011ef440..9fd886d7 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -348,6 +348,8 @@ + + @@ -550,6 +552,10 @@ + + + :/images/Command-Undo-32.png:/images/Command-Undo-32.png + &Undo @@ -561,6 +567,10 @@ + + + :/images/Command-Redo-32.png:/images/Command-Redo-32.png + &Redo From 1ba221610877116cc995b713821d9464a9f1b667 Mon Sep 17 00:00:00 2001 From: shaina7837 Date: Fri, 26 Dec 2014 00:56:31 +0530 Subject: [PATCH 006/174] reset view icon added --- images/Command-Reset-32.png | Bin 0 -> 4196 bytes openscad.qrc | 1 + src/MainWindow.ui | 13 +++++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 images/Command-Reset-32.png diff --git a/images/Command-Reset-32.png b/images/Command-Reset-32.png new file mode 100644 index 0000000000000000000000000000000000000000..b24e419f9d48c59b5f76d66c03fab84afed43d9d GIT binary patch literal 4196 zcmeHJJ!n%=6n;vOS}b%3Hc8XuHGj=d6VlX{Btsfw5-r#gipJ0(1m_S$OOWEC4pPub z#6dcULnmFt!J!m!5^)ff4n;b2k|LtGloH~1qNlxy$-6IhlLlVyefOU4JLjHr?m2HM zH+#0P*V3yfO5gOk^c+T&o}Od)zqYveQ&IW@)9KR}3dfJA{hQygdiXo^fPN2*kB_Uv z!^4Y1Lqn@ptMv<>`rzPT9pg6EUa6{jb8KwPub;7vWFnC;x?HZRxCK(1-ELnonM}I_ z0|Rx*Q?uD@&qJY*SLDz=PbQNdQh?Ju&StYc9*?JBHk-dol>TKDFgrL%S+`;q^!a=t zRtDE@U|!>Q8nL#HFx>F_{fS5SD zG^_#H-$DrT3=~I@)SOP|^?gb08H_N(h)w1|VysJt(GV&u_tyVR2pj819bB+0Mv*gA@Q664+h{TzX#bRnJVYlz# zxy%OOFrT``A6PybjW+5E8G)O$tD6uN(NZWBsEZ%ym&@f0P`p>Dq+|%eQ;IvXzD`9( z3Xlk-QmO6?fbwmQ8C5t5zjPa(bTA)0QIi6wt1$rHSdaoF0=QN4%!k8mNW}5+rmD9Y zK($>8kO)v`WIo)kM-p*Gp?(g)UIRjHKQ9G!5J2HMMHQ3{Kw(OC5N%$D)h`%Cjb&nD z!q_Y!f18?`Isun|U>@>jrBcyX#E^V`Y9I^-(HpAma<#uDNI4X~WIV-bics%Z!nVB(UG8qF-tRmYB zlyG9qNghf4q*yHKbA3B2V8m519HK$Uk2*c#nlP`?$xEfuzbj{h0)apTF?}tNcT(C| zr-bV|=B!L>M1148%MTFab*gG?5Y>9DZ6E~8bk)k`^1)B7Wys;)f8~L@&NIuGetf)0 OhnmjJrk|xsw|)Wjimages/Decrease-Indent-32.png images/Command-Undo-32.png images/Command-Redo-32.png + images/Command-Reset-32.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 9fd886d7..08d22b61 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -342,14 +342,15 @@ + + + + - - - - + @@ -1080,6 +1081,10 @@ + + + :/images/Command-Reset-32.png:/images/Command-Reset-32.png + Reset View From 1068f61dc6aa709df52b54b6f22bf84593457040 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Fri, 26 Dec 2014 21:44:31 -0600 Subject: [PATCH 007/174] Add optional menu driven scaling tics to the large axes Tim Deagan 12/26/2014 While add-on rulers can be extremely useful, there are many times that a quick scaling marker would be handy. This feature generates tics every 10 units, driven off the log10 of the l variable defining axes length. As you zoom in or out, the tics automatically re-scale themselves. Every tenth tic is slightly larger. A menu item is added to the view menu to enable or disable the feature. I experimented with menu driven scaling (.01, .1, 1, 10, etc.), but using small increments when zoomed out brought the app to it's knees. Adding a visual indicator of the current scaling might be nice, but I'm nto sure where to put it (possibly below the small axes,) since it changes as zooming and would clutter the console. Changes to be committed: new file: images/scalemarkers.png modified: openscad.qrc modified: src/GLView.cc modified: src/GLView.h modified: src/MainWindow.h modified: src/MainWindow.ui modified: src/QGLView.h modified: src/mainwin.cc --- images/scalemarkers.png | Bin 0 -> 265 bytes openscad.qrc | 1 + src/GLView.cc | 67 +++++++++++++++++++++++++++++++++++++++- src/GLView.h | 2 ++ src/MainWindow.h | 3 +- src/MainWindow.ui | 16 ++++++++++ src/QGLView.h | 4 +++ src/mainwin.cc | 15 ++++++++- 8 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 images/scalemarkers.png diff --git a/images/scalemarkers.png b/images/scalemarkers.png new file mode 100644 index 0000000000000000000000000000000000000000..067b936638574f58dfdd186f9b664ffc8ba3ff09 GIT binary patch literal 265 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQM~clzb&qdhBT#6Xr;B4q#NoG-eYp-R2)NB(=qdh9 zZ0~=|H+JnOICq`M+BCDtLnvd5>A^|`s|ObK^AloZPSzd}<$9-gyHW3O`GvoUQW;^) z@>Q1|HcM47=_|aj^jqPd6R!1e#sYq?qIr#mo3@KFY;Vpjm#z|eu&?Mk^LyF*>-W#e zxb1AzG~Y=lZHU20i;XGVot97JIi literal 0 HcmV?d00001 diff --git a/openscad.qrc b/openscad.qrc index f202c2d4..aa090fe4 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -59,5 +59,6 @@ images/perspective1white.png images/crosswhite.png icons/background.png + images/scalemarkers.png diff --git a/src/GLView.cc b/src/GLView.cc index d52b3c9b..9fd6c469 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -23,6 +23,7 @@ GLView::GLView() showfaces = true; showaxes = false; showcrosshairs = false; + showscale = false; renderer = NULL; colorscheme = &ColorMap::inst()->defaultColorScheme(); cam = Camera(); @@ -164,6 +165,8 @@ void GLView::paintGL() glTranslated(cam.object_trans.x(), cam.object_trans.y(), cam.object_trans.z()); // ...the axis lines need to follow the object translation. if (showaxes) GLView::showAxes(bgcontrast); + // mark the scale along the axis lines + if (showscale) GLView::showScalemarkers(bgcontrast); } glEnable(GL_LIGHTING); @@ -354,7 +357,6 @@ void GLView::initializeGL() glEnable(GL_LIGHT1); glEnable(GL_LIGHTING); glEnable(GL_NORMALIZE); - glEnable(GL_LINE_STIPPLE); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); // The following line is reported to fix issue #71 @@ -468,6 +470,7 @@ void GLView::showAxes(const Color4f &col) glEnd(); glPushAttrib(GL_LINE_BIT); + glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0xAAAA); glBegin(GL_LINES); glVertex3d(0, 0, 0); @@ -496,3 +499,65 @@ void GLView::showCrosshairs() glEnd(); } +void GLView::showScalemarkers(const Color4f &col) +{ + // Add scale tics on large axes + double l = cam.projection == Camera::PERSPECTIVE ? cam.viewer_distance : cam.height; + glLineWidth(this->getDPI()); + glColor3f(col[0], col[1], col[2]); + + int log_l = (int)log10(l); + double j = 10; + j = pow(j,log_l-1); + int size_div_sm = 60; // divisor for l to determine tic size + int size_div = size_div_sm; + int line_cnt = 0; + + for (double i=0;i + @@ -826,6 +827,21 @@ Ctrl+3 + + + true + + + + :/images/scalemarkers.png:/images/scalemarkers.png + + + Show Scale Markers + + + true diff --git a/src/QGLView.h b/src/QGLView.h index 21b6133d..29147aab 100644 --- a/src/QGLView.h +++ b/src/QGLView.h @@ -17,6 +17,7 @@ class QGLView : public QGLWidget, public GLView Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes); Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs); Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode); + Q_PROPERTY(double showScaleProportional READ showScaleProportional WRITE setShowScaleProportional); public: QGLView(QWidget *parent = NULL); @@ -35,6 +36,9 @@ public: void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; } bool orthoMode() const { return (this->cam.projection == Camera::ORTHOGONAL); } void setOrthoMode(bool enabled); + bool showScaleProportional() const { return this->showscale; } + void setShowScaleProportional(bool enabled) { this->showscale = enabled; } + std::string getRendererInfo() const; #if QT_VERSION >= 0x050100 float getDPI() { return this->devicePixelRatio(); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 3e51f1f3..4eb3d611 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -370,7 +370,8 @@ MainWindow::MainWindow(const QString &filename) connect(this->viewActionShowEdges, SIGNAL(triggered()), this, SLOT(viewModeShowEdges())); connect(this->viewActionShowAxes, SIGNAL(triggered()), this, SLOT(viewModeShowAxes())); connect(this->viewActionShowCrosshairs, SIGNAL(triggered()), this, SLOT(viewModeShowCrosshairs())); - connect(this->viewActionAnimate, SIGNAL(triggered()), this, SLOT(viewModeAnimate())); + connect(this->viewActionShowScaleProportional, SIGNAL(triggered()), this, SLOT(viewModeShowScaleProportional())); + connect(this->viewActionAnimate, SIGNAL(triggered()), this, SLOT(viewModeAnimate())); connect(this->viewActionTop, SIGNAL(triggered()), this, SLOT(viewAngleTop())); connect(this->viewActionBottom, SIGNAL(triggered()), this, SLOT(viewAngleBottom())); connect(this->viewActionLeft, SIGNAL(triggered()), this, SLOT(viewAngleLeft())); @@ -605,6 +606,10 @@ void MainWindow::loadViewSettings(){ viewActionShowCrosshairs->setChecked(true); viewModeShowCrosshairs(); } + if (settings.value("view/showScaleProportional").toBool()) { + viewActionShowScaleProportional->setChecked(true); + viewModeShowScaleProportional(); + } if (settings.value("view/orthogonalProjection").toBool()) { viewOrthogonal(); } else { @@ -2218,6 +2223,14 @@ void MainWindow::viewModeShowCrosshairs() this->qglview->updateGL(); } +void MainWindow::viewModeShowScaleProportional() +{ + QSettings settings; + settings.setValue("view/showScaleProportional",viewActionShowScaleProportional->isChecked()); + this->qglview->setShowScaleProportional(viewActionShowScaleProportional->isChecked()); + this->qglview->updateGL(); +} + void MainWindow::viewModeAnimate() { if (viewActionAnimate->isChecked()) { From 4823f26706817aba81378408509080304e11be44 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Mon, 29 Dec 2014 14:55:15 -0600 Subject: [PATCH 008/174] Addition of function to generate scale maker numeric values on large axes. modified: src/GLView.cc The added function takes the length of the axis (l), the currrent position on the axis (i) and the size of the divisions between i and uses a variety of arrays to decode the characters of the position into GL_LINES, GL_LINE_STRIPs, GL_LINE_LOOPs as appropriate. The various orientations required by the axis are handled by abstracting the line vertex sequences into arrays (set per axis.) --- src/GLView.cc | 312 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 280 insertions(+), 32 deletions(-) diff --git a/src/GLView.cc b/src/GLView.cc index 9fd6c469..bbe8c566 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -506,58 +506,306 @@ void GLView::showScalemarkers(const Color4f &col) glLineWidth(this->getDPI()); glColor3f(col[0], col[1], col[2]); + // determine the log value to provide proportional tics int log_l = (int)log10(l); + + // j represents the increment for each minor tic double j = 10; - j = pow(j,log_l-1); - int size_div_sm = 60; // divisor for l to determine tic size + // deal with 0 log values + if (l < 1.5){ + j = pow(10,log_l-2); + } else { + j = pow(10,log_l-1); + } + + int size_div_sm = 60; // divisor for l to determine minor tic size int size_div = size_div_sm; int line_cnt = 0; - for (double i=0;i( &(std::ostringstream() << i) )->str(); + + // setup how far above the axis (or tic TBD) to draw the number + double dig_buf = (l/size_div_sm)/4; + // setup the size of the character box + double dig_w = (l/size_div_sm)/2; + double dig_h = (l/size_div_sm) + dig_buf; + // setup the distance between characters + double kern = dig_buf; + double dig_wk = (dig_w) + kern; + + // set up ordering for different axes + int ax[6][3] = { + {0,1,2}, + {1,0,2}, + {1,2,0}, + {0,1,2}, + {1,0,2}, + {1,2,0}}; + + // set up character vertex seqeunces for different axes + int or_2[6][6]={ + {0,1,3,2,4,5}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}}; + + int or_3[6][7]={ + {0,1,3,2,3,5,4}, + {1,0,2,3,2,4,5}, + {1,0,2,3,2,4,5}, + {1,0,2,3,2,4,5}, + {0,1,3,2,3,5,4}, + {0,1,3,2,3,5,4}}; + + int or_4[6][5]={ + {0,2,3,1,5}, + {1,3,2,0,4}, + {1,3,2,0,4}, + {1,3,2,0,4}, + {0,2,3,1,5}, + {0,2,3,1,5}}; + + int or_5[6][6]={ + {1,0,2,3,5,4}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}, + {0,1,3,2,4,5}, + {1,0,2,3,5,4}, + {1,0,2,3,5,4}}; + + int or_6[6][6]={ + {1,0,4,3,5,2}, + {0,1,5,4,2,3}, + {0,1,5,4,2,3}, + {0,1,5,4,2,3}, + {1,0,4,3,5,2}, + {1,0,4,3,5,2}}; + + int or_7[6][3]={ + {0,1,4}, + {1,0,5}, + {1,0,5}, + {1,0,5}, + {0,1,4}, + {0,1,4}}; + + int or_9[6][5]={ + {5,1,0,2,3}, + {4,0,1,3,2}, + {4,0,1,3,2}, + {4,0,1,3,2}, + {5,1,0,2,3}, + {5,1,0,2,3}}; + + std::string stash_digit = digit; + + // walk through axes + for (int di=0;di<6;di++){ + + // setup negative axes + double polarity = 1; + if (di>2){ + polarity = -1; + digit = "-" + stash_digit; + } + + if (di>0 && di<4){ + std::reverse(digit.begin(),digit.end()); + } + + // walk through and render the characters of the string + for(std::string::size_type char_num = 0; char_num < digit.size(); ++char_num){ + + double dig_vrt[6][3] = { + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_h,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_h,0}, + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_h/2+dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_h/2+dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_buf,0}, + {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_buf,0}}; + + switch(digit[char_num]){ + case '1': + glBegin(GL_LINES); + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glEnd(); + break; + + case '2': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_2[di][0]][ax[di][0]],dig_vrt[or_2[di][0]][ax[di][1]],dig_vrt[or_2[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_2[di][1]][ax[di][0]],dig_vrt[or_2[di][1]][ax[di][1]],dig_vrt[or_2[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_2[di][2]][ax[di][0]],dig_vrt[or_2[di][2]][ax[di][1]],dig_vrt[or_2[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_2[di][3]][ax[di][0]],dig_vrt[or_2[di][3]][ax[di][1]],dig_vrt[or_2[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_2[di][4]][ax[di][0]],dig_vrt[or_2[di][4]][ax[di][1]],dig_vrt[or_2[di][4]][ax[di][2]]); //e + glVertex3d(dig_vrt[or_2[di][5]][ax[di][0]],dig_vrt[or_2[di][5]][ax[di][1]],dig_vrt[or_2[di][5]][ax[di][2]]); //f + glEnd(); + break; + + case '3': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_3[di][0]][ax[di][0]],dig_vrt[or_3[di][0]][ax[di][1]],dig_vrt[or_3[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_3[di][1]][ax[di][0]],dig_vrt[or_3[di][1]][ax[di][1]],dig_vrt[or_3[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_3[di][2]][ax[di][0]],dig_vrt[or_3[di][2]][ax[di][1]],dig_vrt[or_3[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_3[di][3]][ax[di][0]],dig_vrt[or_3[di][3]][ax[di][1]],dig_vrt[or_3[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_3[di][4]][ax[di][0]],dig_vrt[or_3[di][4]][ax[di][1]],dig_vrt[or_3[di][4]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_3[di][5]][ax[di][0]],dig_vrt[or_3[di][5]][ax[di][1]],dig_vrt[or_3[di][5]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_3[di][6]][ax[di][0]],dig_vrt[or_3[di][6]][ax[di][1]],dig_vrt[or_3[di][6]][ax[di][2]]); //e + glEnd(); + break; + + case '4': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_4[di][0]][ax[di][0]],dig_vrt[or_4[di][0]][ax[di][1]],dig_vrt[or_4[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_4[di][1]][ax[di][0]],dig_vrt[or_4[di][1]][ax[di][1]],dig_vrt[or_4[di][1]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_4[di][2]][ax[di][0]],dig_vrt[or_4[di][2]][ax[di][1]],dig_vrt[or_4[di][2]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_4[di][3]][ax[di][0]],dig_vrt[or_4[di][3]][ax[di][1]],dig_vrt[or_4[di][3]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_4[di][4]][ax[di][0]],dig_vrt[or_4[di][4]][ax[di][1]],dig_vrt[or_4[di][4]][ax[di][2]]); //f + glEnd(); + break; + + case '5': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_5[di][0]][ax[di][0]],dig_vrt[or_5[di][0]][ax[di][1]],dig_vrt[or_5[di][0]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_5[di][1]][ax[di][0]],dig_vrt[or_5[di][1]][ax[di][1]],dig_vrt[or_5[di][1]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_5[di][2]][ax[di][0]],dig_vrt[or_5[di][2]][ax[di][1]],dig_vrt[or_5[di][2]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_5[di][3]][ax[di][0]],dig_vrt[or_5[di][3]][ax[di][1]],dig_vrt[or_5[di][3]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_5[di][4]][ax[di][0]],dig_vrt[or_5[di][4]][ax[di][1]],dig_vrt[or_5[di][4]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_5[di][5]][ax[di][0]],dig_vrt[or_5[di][5]][ax[di][1]],dig_vrt[or_5[di][5]][ax[di][2]]); //e + glEnd(); + break; + + case '6': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_6[di][0]][ax[di][0]],dig_vrt[or_6[di][0]][ax[di][1]],dig_vrt[or_6[di][0]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_6[di][1]][ax[di][0]],dig_vrt[or_6[di][1]][ax[di][1]],dig_vrt[or_6[di][1]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_6[di][2]][ax[di][0]],dig_vrt[or_6[di][2]][ax[di][1]],dig_vrt[or_6[di][2]][ax[di][2]]); //e + glVertex3d(dig_vrt[or_6[di][3]][ax[di][0]],dig_vrt[or_6[di][3]][ax[di][1]],dig_vrt[or_6[di][3]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_6[di][4]][ax[di][0]],dig_vrt[or_6[di][4]][ax[di][1]],dig_vrt[or_6[di][4]][ax[di][2]]); //d + glVertex3d(dig_vrt[or_6[di][5]][ax[di][0]],dig_vrt[or_6[di][5]][ax[di][1]],dig_vrt[or_6[di][5]][ax[di][2]]); //c + glEnd(); + break; + + case '7': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_7[di][0]][ax[di][0]],dig_vrt[or_7[di][0]][ax[di][1]],dig_vrt[or_7[di][0]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_7[di][1]][ax[di][0]],dig_vrt[or_7[di][1]][ax[di][1]],dig_vrt[or_7[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_7[di][2]][ax[di][0]],dig_vrt[or_7[di][2]][ax[di][1]],dig_vrt[or_7[di][2]][ax[di][2]]); //e + glEnd(); + break; + + case '8': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[2][ax[di][0]],dig_vrt[2][ax[di][1]],dig_vrt[2][ax[di][2]]); //c + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glVertex3d(dig_vrt[1][ax[di][0]],dig_vrt[1][ax[di][1]],dig_vrt[1][ax[di][2]]); //b + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glEnd(); + break; + + case '9': + glBegin(GL_LINE_STRIP); + glVertex3d(dig_vrt[or_9[di][0]][ax[di][0]],dig_vrt[or_9[di][0]][ax[di][1]],dig_vrt[or_9[di][0]][ax[di][2]]); //f + glVertex3d(dig_vrt[or_9[di][1]][ax[di][0]],dig_vrt[or_9[di][1]][ax[di][1]],dig_vrt[or_9[di][1]][ax[di][2]]); //b + glVertex3d(dig_vrt[or_9[di][2]][ax[di][0]],dig_vrt[or_9[di][2]][ax[di][1]],dig_vrt[or_9[di][2]][ax[di][2]]); //a + glVertex3d(dig_vrt[or_9[di][3]][ax[di][0]],dig_vrt[or_9[di][3]][ax[di][1]],dig_vrt[or_9[di][3]][ax[di][2]]); //c + glVertex3d(dig_vrt[or_9[di][4]][ax[di][0]],dig_vrt[or_9[di][4]][ax[di][1]],dig_vrt[or_9[di][4]][ax[di][2]]); //d + glEnd(); + break; + + case '0': + glBegin(GL_LINE_LOOP); + glVertex3d(dig_vrt[0][ax[di][0]],dig_vrt[0][ax[di][1]],dig_vrt[0][ax[di][2]]); //a + glVertex3d(dig_vrt[1][ax[di][0]],dig_vrt[1][ax[di][1]],dig_vrt[1][ax[di][2]]); //b + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glEnd(); + break; + + case '-': + glBegin(GL_LINES); + glVertex3d(dig_vrt[2][ax[di][0]],dig_vrt[2][ax[di][1]],dig_vrt[2][ax[di][2]]); //c + glVertex3d(dig_vrt[3][ax[di][0]],dig_vrt[3][ax[di][1]],dig_vrt[3][ax[di][2]]); //d + glEnd(); + break; + + case '.': + glBegin(GL_LINES); + glVertex3d(dig_vrt[4][ax[di][0]],dig_vrt[4][ax[di][1]],dig_vrt[4][ax[di][2]]); //e + glVertex3d(dig_vrt[5][ax[di][0]],dig_vrt[5][ax[di][1]],dig_vrt[5][ax[di][2]]); //f + glEnd(); + break; + } + } + } +} + From 1826aa98f77cd9052c2c953f0fc08da3be679fbc Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Mon, 29 Dec 2014 15:00:37 -0600 Subject: [PATCH 009/174] Addition of header to support function to print scale marker position values on large axes. modified: src/GLView.h --- src/GLView.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GLView.h b/src/GLView.h index 9276aae8..c3f93f03 100644 --- a/src/GLView.h +++ b/src/GLView.h @@ -78,4 +78,5 @@ private: void showAxes(const Color4f &col); void showSmallaxes(const Color4f &col); void showScalemarkers(const Color4f &col); + void decodeMarkerValue(double i, double l, int size_div_sm); }; From 7a71e59f2d3c9208480ce4ed03885136828839d9 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Mon, 29 Dec 2014 21:23:46 -0600 Subject: [PATCH 010/174] Fix layout of number 6 character & add comments The layout of the array that drives the 6 char was wrong. Additional commenting added --- src/GLView.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/GLView.cc b/src/GLView.cc index bbe8c566..af0b7465 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -639,12 +639,12 @@ void GLView::decodeMarkerValue(double i, double l, int size_div_sm) {1,0,2,3,5,4}}; int or_6[6][6]={ - {1,0,4,3,5,2}, + {1,0,4,5,3,2}, {0,1,5,4,2,3}, {0,1,5,4,2,3}, {0,1,5,4,2,3}, - {1,0,4,3,5,2}, - {1,0,4,3,5,2}}; + {1,0,4,5,3,2}, + {1,0,4,5,3,2}}; int or_7[6][3]={ {0,1,4}, @@ -674,13 +674,14 @@ void GLView::decodeMarkerValue(double i, double l, int size_div_sm) digit = "-" + stash_digit; } + // fix the axes that need to run the opposite direction if (di>0 && di<4){ std::reverse(digit.begin(),digit.end()); } // walk through and render the characters of the string for(std::string::size_type char_num = 0; char_num < digit.size(); ++char_num){ - + // setup the vertices for the char rendering based on the axis and position double dig_vrt[6][3] = { {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_h,0}, {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_h,0}, @@ -689,6 +690,13 @@ void GLView::decodeMarkerValue(double i, double l, int size_div_sm) {polarity*((i+((char_num)*dig_wk))-(dig_w/2)),dig_buf,0}, {polarity*((i+((char_num)*dig_wk))+(dig_w/2)),dig_buf,0}}; + // convert the char into lines appropriate for the axis being used + // psuedo 7 segment vertices are: + // A--B + // | | + // C--D + // | | + // E--F switch(digit[char_num]){ case '1': glBegin(GL_LINES); From 358ba86fc8e383c2907c5c83658a0568435ebee0 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Fri, 2 Jan 2015 01:32:37 -0600 Subject: [PATCH 011/174] Swap out spaces for tabs modified: src/GLView.h modified: src/MainWindow.h modified: src/QGLView.h modified: src/mainwin.cc QtCreator ignores the prefs and will only put in spaces instead of tabs. These are manual fixes in Notepad++ to try and keep the indents in the standard mode. --- src/GLView.h | 6 +++--- src/MainWindow.h | 4 ++-- src/QGLView.h | 7 +++---- src/mainwin.cc | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/GLView.h b/src/GLView.h index c3f93f03..734139c6 100644 --- a/src/GLView.h +++ b/src/GLView.h @@ -62,7 +62,7 @@ public: bool showfaces; bool showedges; bool showcrosshairs; - bool showscale; + bool showscale; #ifdef ENABLE_OPENCSG GLint shaderinfo[11]; @@ -77,6 +77,6 @@ private: void showCrosshairs(); void showAxes(const Color4f &col); void showSmallaxes(const Color4f &col); - void showScalemarkers(const Color4f &col); - void decodeMarkerValue(double i, double l, int size_div_sm); + void showScalemarkers(const Color4f &col); + void decodeMarkerValue(double i, double l, int size_div_sm); }; diff --git a/src/MainWindow.h b/src/MainWindow.h index e4aa2304..32717d74 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -213,8 +213,8 @@ public slots: void viewModeShowEdges(); void viewModeShowAxes(); void viewModeShowCrosshairs(); - void viewModeShowScaleProportional(); - void viewModeAnimate(); + void viewModeShowScaleProportional(); + void viewModeAnimate(); void viewAngleTop(); void viewAngleBottom(); void viewAngleLeft(); diff --git a/src/QGLView.h b/src/QGLView.h index 29147aab..3891ee51 100644 --- a/src/QGLView.h +++ b/src/QGLView.h @@ -17,7 +17,7 @@ class QGLView : public QGLWidget, public GLView Q_PROPERTY(bool showAxes READ showAxes WRITE setShowAxes); Q_PROPERTY(bool showCrosshairs READ showCrosshairs WRITE setShowCrosshairs); Q_PROPERTY(bool orthoMode READ orthoMode WRITE setOrthoMode); - Q_PROPERTY(double showScaleProportional READ showScaleProportional WRITE setShowScaleProportional); + Q_PROPERTY(double showScaleProportional READ showScaleProportional WRITE setShowScaleProportional); public: QGLView(QWidget *parent = NULL); @@ -36,9 +36,8 @@ public: void setShowCrosshairs(bool enabled) { this->showcrosshairs = enabled; } bool orthoMode() const { return (this->cam.projection == Camera::ORTHOGONAL); } void setOrthoMode(bool enabled); - bool showScaleProportional() const { return this->showscale; } - void setShowScaleProportional(bool enabled) { this->showscale = enabled; } - + bool showScaleProportional() const { return this->showscale; } + void setShowScaleProportional(bool enabled) { this->showscale = enabled; } std::string getRendererInfo() const; #if QT_VERSION >= 0x050100 float getDPI() { return this->devicePixelRatio(); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 6a4d14b2..b00b3758 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -371,8 +371,8 @@ MainWindow::MainWindow(const QString &filename) connect(this->viewActionShowEdges, SIGNAL(triggered()), this, SLOT(viewModeShowEdges())); connect(this->viewActionShowAxes, SIGNAL(triggered()), this, SLOT(viewModeShowAxes())); connect(this->viewActionShowCrosshairs, SIGNAL(triggered()), this, SLOT(viewModeShowCrosshairs())); - connect(this->viewActionShowScaleProportional, SIGNAL(triggered()), this, SLOT(viewModeShowScaleProportional())); - connect(this->viewActionAnimate, SIGNAL(triggered()), this, SLOT(viewModeAnimate())); + connect(this->viewActionShowScaleProportional, SIGNAL(triggered()), this, SLOT(viewModeShowScaleProportional())); + connect(this->viewActionAnimate, SIGNAL(triggered()), this, SLOT(viewModeAnimate())); connect(this->viewActionTop, SIGNAL(triggered()), this, SLOT(viewAngleTop())); connect(this->viewActionBottom, SIGNAL(triggered()), this, SLOT(viewAngleBottom())); connect(this->viewActionLeft, SIGNAL(triggered()), this, SLOT(viewAngleLeft())); From 4ebc9ce4d0db07e64e96d0fb6dd6a1ff983029a2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 5 Jan 2015 10:52:11 -0500 Subject: [PATCH 012/174] sync --- .gitignore | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 767c89c4..09dd7b69 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,37 @@ -/*.scad *.dmg *~ *.tar* Makefile objects .gdbinit -/*.stl -/*.dxf -/lexer_lex.cpp -/parser_yacc.cpp +.qmake.stash parser_yacc.h -/tmp -/OpenSCAD.app */#*# -/locale/*/*/*.mo -/locale/POTFILES -/nbproject -/openscad.pro.user -/openscad -/tests/openscad_nogui testdata/scad/features/import_dxf-tests.scad testdata/scad/features/import_stl-tests.scad testdata/scad/misc/include-tests.scad testdata/scad/misc/use-tests.scad -/mingw32 -/mingw64 **/project.xcworkspace **/xcuserdata +/*.scad +/*.stl +/*.dxf +/*.off +/*.amf +/*.png +/*.csg +/lexer_lex.cpp +/parser_yacc.cpp +/OpenSCAD.app +/openscad.pro.user +/openscad +/locale/*/*/*.mo +/locale/POTFILES +/tests/openscad_nogui +/tests/diffpng +/tests/test_pretty_print.log.txt +/tests/*.png +/tmp +/nbproject +/mingw32 +/mingw64 From 32b2d2ec972b362f2f32198cade7f1e8152276ab Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 5 Jan 2015 18:22:58 -0500 Subject: [PATCH 013/174] Fixed buggy vertex quantizing and polygon tessellation. Should improve some corner cases --- openscad.pro | 1 + src/cgalutils-polyhedron.cc | 37 ++++++++-------- src/cgalutils.cc | 19 +++----- src/grid.cc | 14 ++++++ src/grid.h | 87 ++++++++++++++++++++++++------------- src/polyset.cc | 30 +++++++++++-- tests/CMakeLists.txt | 1 + 7 files changed, 125 insertions(+), 64 deletions(-) create mode 100644 src/grid.cc diff --git a/openscad.pro b/openscad.pro index f9478c79..6df00a2f 100644 --- a/openscad.pro +++ b/openscad.pro @@ -410,6 +410,7 @@ SOURCES += src/version_check.cc \ src/QGLView.cc \ src/AutoUpdater.cc \ \ + src/grid.cc \ src/builtin.cc \ src/calc.cc \ src/export.cc \ diff --git a/src/cgalutils-polyhedron.cc b/src/cgalutils-polyhedron.cc index 43ab72d6..59a2ec71 100644 --- a/src/cgalutils-polyhedron.cc +++ b/src/cgalutils-polyhedron.cc @@ -48,17 +48,22 @@ namespace /* anonymous */ { void operator()(HDS& hds) { CGAL_Polybuilder B(hds, true); - std::vector vertices; Grid3d grid(GRID_FINE); - std::vector indices(3); - + std::vector vertices; + std::vector > indices; + + // Align all vertices to grid and build vertex array in vertices BOOST_FOREACH(const Polygon &p, ps.polygons) { + indices.push_back(std::vector()); + indices.back().reserve(p.size()); BOOST_REVERSE_FOREACH(Vector3d v, p) { - if (!grid.has(v)) { - // align v to the grid; the CGALPoint will receive the aligned vertex - grid.align(v) = vertices.size(); - vertices.push_back(CGALPoint(v[0], v[1], v[2])); + // align v to the grid; the CGALPoint will receive the aligned vertex + size_t idx = grid.align(v); + if (idx == vertices.size()) { + CGALPoint p(v[0], v[1], v[2]); + vertices.push_back(p); } + indices.back().push_back(idx); } } @@ -70,28 +75,24 @@ namespace /* anonymous */ { BOOST_FOREACH(const CGALPoint &p, vertices) { B.add_vertex(p); } - BOOST_FOREACH(const Polygon &p, ps.polygons) { + BOOST_FOREACH(std::vector &pindices, indices) { #ifdef GEN_SURFACE_DEBUG if (pidx++ > 0) printf(","); #endif - indices.clear(); - BOOST_FOREACH(const Vector3d &v, p) { - indices.push_back(grid.data(v)); - } // We remove duplicate indices since there is a bug in CGAL's // Polyhedron_incremental_builder_3::test_facet() which fails to detect this - std::vector::iterator last = std::unique(indices.begin(), indices.end()); + std::vector::iterator last = std::unique(pindices.begin(), pindices.end()); std::advance(last, -1); - if (*last != indices.front()) last++; // In case the first & last are equal - indices.erase(last, indices.end()); - if (indices.size() >= 3 && B.test_facet(indices.begin(), indices.end())) { - B.add_facet(indices.begin(), indices.end()); + if (*last != pindices.front()) last++; // In case the first & last are equal + pindices.erase(last, pindices.end()); + if (pindices.size() >=3 && B.test_facet(pindices.begin(), pindices.end())) { + B.add_facet(pindices.begin(), pindices.end()); } #ifdef GEN_SURFACE_DEBUG printf("["); int fidx = 0; - BOOST_REVERSE_FOREACH(size_t i, indices) { + BOOST_REVERSE_FOREACH(size_t i, pindices) { if (fidx++ > 0) printf(","); printf("%ld", i); } diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 971f12f7..4ef50e82 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -21,14 +21,6 @@ #include #include -namespace Eigen { - size_t hash_value(Vector3d const &v) { - size_t seed = 0; - for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); - return seed; - } -} - namespace /* anonymous */ { template Result vector_convert(V const& v) { @@ -50,10 +42,11 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) if (ps_tri.is_convex()) { typedef CGAL::Exact_predicates_inexact_constructions_kernel K; // Collect point cloud + // FIXME: Use unordered container (need hash) std::set points; - for (int i = 0; i < ps.polygons.size(); i++) { - for (int j = 0; j < ps.polygons[i].size(); j++) { - points.insert(vector_convert(ps.polygons[i][j])); + for (int i = 0; i < psq.polygons.size(); i++) { + for (int j = 0; j < psq.polygons[i].size(); j++) { + points.insert(vector_convert(psq.polygons[i][j])); } } @@ -72,7 +65,7 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); try { CGAL_Polyhedron P; - bool err = CGALUtils::createPolyhedronFromPolySet(ps, P); + bool err = CGALUtils::createPolyhedronFromPolySet(psq, P); if (!err) { PRINTDB("Polyhedron is closed: %d", P.is_closed()); PRINTDB("Polyhedron is valid: %d", P.is_valid(false, 0)); @@ -463,7 +456,7 @@ namespace CGALUtils { } // union && difference assert triggered by testdata/scad/bugs/rotate-diff-nonmanifold-crash.scad and testdata/scad/bugs/issue204.scad catch (const CGAL::Failure_exception &e) { - std::string opstr = op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_MINKOWSKI ? "minkowski" : "UNKNOWN"; + std::string opstr = op == OPENSCAD_INTERSECTION ? "intersection" : op == OPENSCAD_DIFFERENCE ? "difference" : op == OPENSCAD_UNION ? "union" : "UNKNOWN"; PRINTB("ERROR: CGAL error in CGALUtils::applyBinaryOperator %s: %s", opstr % e.what()); } CGAL::set_error_behaviour(old_behaviour); diff --git a/src/grid.cc b/src/grid.cc new file mode 100644 index 00000000..79d72900 --- /dev/null +++ b/src/grid.cc @@ -0,0 +1,14 @@ +#include "grid.h" + +namespace Eigen { + size_t hash_value(Vector3d const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } + size_t hash_value(Eigen::Matrix const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } +} diff --git a/src/grid.h b/src/grid.h index f9fe4d0e..b0164c34 100644 --- a/src/grid.h +++ b/src/grid.h @@ -87,59 +87,88 @@ public: } }; +typedef Eigen::Matrix Vector3l; + +namespace Eigen { + size_t hash_value(Vector3d const &v); + size_t hash_value(Vector3l const &v); +} + template class Grid3d { public: double res; - boost::unordered_map,int64_t>, T> db; + typedef Vector3l Key; + typedef boost::unordered_map GridContainer; + GridContainer db; Grid3d(double resolution) { res = resolution; } - T &align(Vector3d &v) { - int64_t ix = (int64_t)round(v[0] / res); - int64_t iy = (int64_t)round(v[1] / res); - int64_t iz = (int64_t)round(v[2] / res); - if (db.find(std::make_pair(std::make_pair(ix, iy), iz)) == db.end()) { - int dist = 10; - for (int64_t jx = ix - 1; jx <= ix + 1; jx++) { - for (int64_t jy = iy - 1; jy <= iy + 1; jy++) { - for (int64_t jz = iz - 1; jz <= iz + 1; jz++) { - if (db.find(std::make_pair(std::make_pair(jx, jy), jz)) == db.end()) - continue; - int d = abs(int(ix-jx)) + abs(int(iy-jy)) + abs(int(iz-jz)); + inline void createGridVertex(const Vector3d &v, Vector3l &i) { + i[0] = int64_t(v[0] / this->res); + i[1] = int64_t(v[1] / this->res); + i[2] = int64_t(v[2] / this->res); + } + + // Aligns vertex to the grid. Returns index of the vertex. + // Will automatically increase the index as new unique vertices are added. + T align(Vector3d &v) { + Vector3l key; + createGridVertex(v, key); + typename GridContainer::iterator iter = db.find(key); + if (iter == db.end()) { + int dist = 10; // > max possible distance + for (int64_t jx = key[0] - 1; jx <= key[0] + 1; jx++) { + for (int64_t jy = key[1] - 1; jy <= key[1] + 1; jy++) { + for (int64_t jz = key[2] - 1; jz <= key[2] + 1; jz++) { + Vector3l k(jx, jy, jz); + typename GridContainer::iterator tmpiter = db.find(k); + if (tmpiter == db.end()) continue; + int d = (key-k).norm(); if (d < dist) { dist = d; - ix = jx; - iy = jy; - iz = jz; + iter = tmpiter; } } } } } - v[0] = ix * res, v[1] = iy * res, v[2] = iz * res; - return db[std::make_pair(std::make_pair(ix, iy), iz)]; + if (iter == db.end()) { // Not found: insert using key + T &data = db[key] = db.size(); + return data; + } + + // If found, align vertex and return existing data + key = iter->first; + v[0] = key[0] * this->res; + v[1] = key[1] * this->res; + v[2] = key[2] * this->res; + return iter->second; } - bool has(const Vector3d &v) { - int64_t ix = (int64_t)round(v[0] / res); - int64_t iy = (int64_t)round(v[1] / res); - int64_t iz = (int64_t)round(v[2] / res); - if (db.find(std::make_pair(std::make_pair(ix, iy), iz)) != db.end()) + bool has(const Vector3d &v, T *data = NULL) { + Vector3l key = createGridVertex(v); + typename GridContainer::iterator pos = db.find(key); + if (pos != db.end()) { + if (data) *data = pos->second; return true; - for (int64_t jx = ix - 1; jx <= ix + 1; jx++) - for (int64_t jy = iy - 1; jy <= iy + 1; jy++) - for (int64_t jz = iz - 1; jz <= iz + 1; jz++) { - if (db.find(std::make_pair(std::make_pair(jx, jy), jz)) != db.end()) - return true; } + for (int64_t jx = key[0] - 1; jx <= key[0] + 1; jx++) + for (int64_t jy = key[1] - 1; jy <= key[1] + 1; jy++) + for (int64_t jz = key[2] - 1; jz <= key[2] + 1; jz++) { + pos = db.find(Vector3l(jx, jy, jz)); + if (pos != db.end()) { + if (data) *data = pos->second; + return true; + } + } return false; } - T &data(Vector3d v) { + T data(Vector3d v) { return align(v); } diff --git a/src/polyset.cc b/src/polyset.cc index ec31cd19..85328727 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -176,13 +176,35 @@ void PolySet::resize(Vector3d newsize, const Eigen::Matrix &autosize) this->transform(t); } +/*! + Quantizes vertices by gridding them as well as merges close vertices belonging to + neighboring grids. + May reduce the number of polygons if polygons collapse into < 3 vertices. +*/ void PolySet::quantizeVertices() { Grid3d grid(GRID_FINE); - BOOST_FOREACH(Polygon &p, this->polygons) { - BOOST_FOREACH(Vector3d &v, p) { - // align v to the grid - if (!grid.has(v)) grid.align(v); + int numverts = 0; + std::vector indices; // Vertex indices in one polygon + for (std::vector::iterator iter = this->polygons.begin(); iter != this->polygons.end();) { + Polygon &p = *iter; + indices.resize(p.size()); + // Quantize all vertices. Build index list + for (int i=0;ipolygons.erase(iter); + } + else { + iter++; } } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1b23a552..f60cd64e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -617,6 +617,7 @@ set(CORE_SOURCES ../src/handle_dep.cc ../src/value.cc ../src/calc.cc + ../src/grid.cc ../src/expr.cc ../src/func.cc ../src/stackcheck.cc From 82dbabac92911852bf78a62b64de1d7ca62cecce Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 11:12:03 -0500 Subject: [PATCH 014/174] Apply convex hull bugfix from CGAL, work around next issue by avoiding using std::set iterators, updated test cases. Fixes #1089 --- openscad.pro | 1 + src/cgalutils.cc | 35 +- src/convex_hull_3_bugfix.h | 960 ++++++++++++++++++ testdata/scad/bugs/issue1089b.scad | 3 + tests/CMakeLists.txt | 4 +- .../cgalpngtest/issue1089b-expected.png | Bin 0 -> 6488 bytes .../monotonepngtest/issue1089b-expected.png | Bin 0 -> 6520 bytes .../opencsgtest/issue1089b-expected.png | Bin 0 -> 6717 bytes 8 files changed, 993 insertions(+), 10 deletions(-) create mode 100644 src/convex_hull_3_bugfix.h create mode 100644 testdata/scad/bugs/issue1089b.scad create mode 100644 tests/regression/cgalpngtest/issue1089b-expected.png create mode 100644 tests/regression/monotonepngtest/issue1089b-expected.png create mode 100644 tests/regression/opencsgtest/issue1089b-expected.png diff --git a/openscad.pro b/openscad.pro index f9478c79..cbcef540 100644 --- a/openscad.pro +++ b/openscad.pro @@ -467,6 +467,7 @@ HEADERS += src/cgal.h \ src/CGALRenderer.h \ src/CGAL_Nef_polyhedron.h \ src/CGAL_Nef3_workaround.h \ + src/convex_hull_3_bugfix.h \ src/cgalworker.h \ src/Polygon2d-CGAL.h diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 971f12f7..97044e76 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -9,10 +9,19 @@ #include "node.h" #include "cgal.h" -#include #include #include #include + +#include +#include + +#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) +#include +#else +#include "convex_hull_3_bugfix.h" +#endif + #include "svg.h" #include "Reindexer.h" @@ -48,12 +57,14 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) PolySet ps_tri(3, psq.convexValue()); PolysetUtils::tessellate_faces(psq, ps_tri); if (ps_tri.is_convex()) { - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + typedef CGAL::Epick K; // Collect point cloud - std::set points; + // NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list + // instead. + std::list points; for (int i = 0; i < ps.polygons.size(); i++) { for (int j = 0; j < ps.polygons[i].size(); j++) { - points.insert(vector_convert(ps.polygons[i][j])); + points.push_back(vector_convert(ps.polygons[i][j])); } } @@ -115,9 +126,11 @@ namespace CGALUtils { bool applyHull(const Geometry::ChildList &children, PolySet &result) { - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + typedef CGAL::Epick K; // Collect point cloud - std::set points; + // NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list + // instead. + std::list points; BOOST_FOREACH(const Geometry::ChildItem &item, children) { const shared_ptr &chgeom = item.second; @@ -125,7 +138,7 @@ namespace CGALUtils { if (N) { if (!N->isEmpty()) { for (CGAL_Nef_polyhedron3::Vertex_const_iterator i = N->p3->vertices_begin(); i != N->p3->vertices_end(); ++i) { - points.insert(K::Point_3(to_double(i->point()[0]),to_double(i->point()[1]),to_double(i->point()[2]))); + points.push_back(vector_convert(i->point())); } } } else { @@ -133,7 +146,7 @@ namespace CGALUtils { if (ps) { BOOST_FOREACH(const Polygon &p, ps->polygons) { BOOST_FOREACH(const Vector3d &v, p) { - points.insert(K::Point_3(v[0], v[1], v[2])); + points.push_back(K::Point_3(v[0], v[1], v[2])); } } } @@ -149,6 +162,10 @@ namespace CGALUtils { try { CGAL::Polyhedron_3 r; CGAL::convex_hull_3(points.begin(), points.end(), r); + PRINTDB("After hull vertices: %d", r.size_of_vertices()); + PRINTDB("After hull facets: %d", r.size_of_facets()); + PRINTDB("After hull closed: %d", r.is_closed()); + PRINTDB("After hull valid: %d", r.is_valid()); success = !createPolySetFromPolyhedron(r, result); } catch (const CGAL::Assertion_exception &e) { @@ -206,7 +223,7 @@ namespace CGALUtils { while (++it != children.end()) { operands[1] = it->second.get(); - typedef CGAL::Exact_predicates_inexact_constructions_kernel Hull_kernel; + typedef CGAL::Epick Hull_kernel; std::list P[2]; std::list > result_parts; diff --git a/src/convex_hull_3_bugfix.h b/src/convex_hull_3_bugfix.h new file mode 100644 index 00000000..5fb7cd30 --- /dev/null +++ b/src/convex_hull_3_bugfix.h @@ -0,0 +1,960 @@ +/* + This file contains a bugfix against CGAL-4.5.1, see: + http://cgal-discuss.949826.n4.nabble.com/Epick-convex-hull-3-assertion-td4660264.html +*/ + +// Copyright (c) 2001,2011 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Susan Hert +// : Amol Prakash +// : Andreas Fabri + +#ifndef CGAL_CONVEX_HULL_3_H +#define CGAL_CONVEX_HULL_3_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef CGAL_CH_NO_POSTCONDITIONS +#include +#endif // CGAL_CH_NO_POSTCONDITIONS + + +namespace CGAL { + +namespace internal{ namespace Convex_hull_3{ + +//struct to select the default traits class for computing convex hull +template< class Point_3, + class Is_floating_point=typename boost::is_floating_point::Kernel::FT>::type, + class Has_filtered_predicates_tag=typename Kernel_traits::Kernel::Has_filtered_predicates_tag > +struct Default_traits_for_Chull_3{ + typedef typename Kernel_traits::Kernel type; +}; + +//FT is a floating point type and Kernel is a filtered kernel +template +struct Default_traits_for_Chull_3{ + typedef Convex_hull_traits_3< typename Kernel_traits::Kernel > type; +}; + +template +struct Default_polyhedron_for_Chull_3{ + typedef CGAL::Polyhedron_3 type; +}; + +template +struct Default_polyhedron_for_Chull_3 >{ + typedef typename Convex_hull_traits_3::Polyhedron_3 type; +}; + +//utility class to select the right version of internal predicate Is_on_positive_side_of_plane_3 +template ::Kernel::FT>::type, + class Has_filtered_predicates_tag=typename Kernel_traits::Kernel::Has_filtered_predicates_tag, + class Has_cartesian_tag=typename Kernel_traits::Kernel::Kernel_tag, + class Has_classical_point_type = + typename boost::is_same< + typename Kernel_traits::Kernel::Point_3, + typename Traits::Point_3 >::type + > +struct Use_advanced_filtering{ + typedef CGAL::Tag_false type; +}; + +template +struct Use_advanced_filtering{ + typedef typename Kernel_traits::Kernel K; + typedef CGAL::Boolean_tag type; +}; + +//Predicates internally used +template ::type > +class Is_on_positive_side_of_plane_3{ + typedef typename Traits::Point_3 Point_3; + typename Traits::Plane_3 plane; + typename Traits::Has_on_positive_side_3 has_on_positive_side; +public: + typedef Protect_FPU_rounding Protector; + + Is_on_positive_side_of_plane_3(const Traits& traits,const Point_3& p,const Point_3& q,const Point_3& r) + :plane(traits.construct_plane_3_object()(p,q,r)),has_on_positive_side(traits.has_on_positive_side_3_object()) {} + + bool operator() (const Point_3& s) const + { + return has_on_positive_side(plane,s); + } +}; + + +//This predicate uses copy of the code from the statically filtered version of +//Orientation_3. The rational is that the plane is a member of the functor +//so optimization are done to avoid doing several time operations on the plane. +//The main operator() first tries the static version of the predicate, then uses +//interval arithmetic (the protector must be created before using this predicate) +//and in case of failure, exact arithmetic is used. +template +class Is_on_positive_side_of_plane_3,Tag_true>{ + typedef Simple_cartesian::Type> PK; + typedef Simple_cartesian CK; + typedef Convex_hull_traits_3 Traits; + typedef typename Traits::Point_3 Point_3; + + Cartesian_converter to_CK; + Cartesian_converter to_PK; + + const Point_3& p,q,r; + mutable typename CK::Plane_3* ck_plane; + mutable typename PK::Plane_3* pk_plane; + + double m10,m20,m21,Maxx,Maxy,Maxz; + + static const int STATIC_FILTER_FAILURE = 555; + + //this function is a made from the statically filtered version of Orientation_3 + int static_filtered(double psx,double psy, double psz) const{ + + // Then semi-static filter. + double apsx = CGAL::abs(psx); + double apsy = CGAL::abs(psy); + double apsz = CGAL::abs(psz); + + double maxx = (Maxx < apsx)? apsx : Maxx; + double maxy = (Maxy < apsy)? apsy : Maxy; + double maxz = (Maxz < apsz)? apsz : Maxz; + + double det = psx*m10 - m20*psy + m21*psz; + + // Sort maxx < maxy < maxz. + if (maxx > maxz) + std::swap(maxx, maxz); + if (maxy > maxz) + std::swap(maxy, maxz); + else if (maxy < maxx) + std::swap(maxx, maxy); + + // Protect against underflow in the computation of eps. + if (maxx < 1e-97) /* cbrt(min_double/eps) */ { + if (maxx == 0) + return 0; + } + // Protect against overflow in the computation of det. + else if (maxz < 1e102) /* cbrt(max_double [hadamard]/4) */ { + double eps = 5.1107127829973299e-15 * maxx * maxy * maxz; + if (det > eps) return 1; + if (det < -eps) return -1; + } + return STATIC_FILTER_FAILURE; + } + +public: + typedef typename Interval_nt_advanced::Protector Protector; + + Is_on_positive_side_of_plane_3(const Traits&,const Point_3& p_,const Point_3& q_,const Point_3& r_) + :p(p_),q(q_),r(r_),ck_plane(NULL),pk_plane(NULL) + { + double pqx = q.x() - p.x(); + double pqy = q.y() - p.y(); + double pqz = q.z() - p.z(); + double prx = r.x() - p.x(); + double pry = r.y() - p.y(); + double prz = r.z() - p.z(); + + + m10 = pqy*prz - pry*pqz; + m20 = pqx*prz - prx*pqz; + m21 = pqx*pry - prx*pqy; + + double aprx = CGAL::abs(prx); + double apry = CGAL::abs(pry); + double aprz = CGAL::abs(prz); + + Maxx = CGAL::abs(pqx); + if (Maxx < aprx) Maxx = aprx; + Maxy = CGAL::abs(pqy); + if (Maxy < apry) Maxy = apry; + Maxz = CGAL::abs(pqz); + if (Maxz < aprz) Maxz = aprz; + } + + ~Is_on_positive_side_of_plane_3(){ + if (ck_plane!=NULL) delete ck_plane; + if (pk_plane!=NULL) delete pk_plane; + } + + bool operator() (const Point_3& s) const + { + double psx = s.x() - p.x(); + double psy = s.y() - p.y(); + double psz = s.z() - p.z(); + + int static_res = static_filtered(psx,psy,psz); + if (static_res != STATIC_FILTER_FAILURE) + return static_res == 1; + + try{ + if (ck_plane==NULL) + ck_plane=new typename CK::Plane_3(to_CK(p),to_CK(q),to_CK(r)); + return ck_plane->has_on_positive_side(to_CK(s)); + } + catch (Uncertain_conversion_exception){ + if (pk_plane==NULL) + pk_plane=new typename PK::Plane_3(to_PK(p),to_PK(q),to_PK(r)); + return pk_plane->has_on_positive_side(to_PK(s)); + } + } +}; + + +template +class Build_coplanar_poly : public Modifier_base { + public: + Build_coplanar_poly(ForwardIterator i, ForwardIterator j) + { + start = i; + end = j; + } + void operator()( HDS& hds) { + Polyhedron_incremental_builder_3 B(hds,true); + ForwardIterator iter = start; + int count = 0; + while (iter != end) + { + count++; + iter++; + } + B.begin_surface(count, 1, 2*count); + iter = start; + while (iter != end) + { + B.add_vertex(*iter); + iter++; + } + iter = start; + B.begin_facet(); + int p = 0; + while (p < count) + { + B.add_vertex_to_facet(p); + p++; + } + B.end_facet(); + B.end_surface(); + } + private: + ForwardIterator start; + ForwardIterator end; +}; + + +namespace internal { namespace Convex_hull_3{ + +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_xy_3,Traits_xy_3,false) +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_yz_3,Traits_xy_3,false) +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Traits_has_typedef_Traits_xz_3,Traits_xy_3,false) + +template ::value && + Traits_has_typedef_Traits_yz_3::value && + Traits_has_typedef_Traits_xz_3::value +> +struct Projection_traits{ + typedef typename Kernel_traits::Kernel K; + typedef CGAL::Projection_traits_xy_3 Traits_xy_3; + typedef CGAL::Projection_traits_yz_3 Traits_yz_3; + typedef CGAL::Projection_traits_xz_3 Traits_xz_3; +}; + +template +struct Projection_traits{ + typedef typename T::Traits_xy_3 Traits_xy_3; + typedef typename T::Traits_yz_3 Traits_yz_3; + typedef typename T::Traits_xz_3 Traits_xz_3; +}; + +} } //end of namespace internal::Convex_hull_3 + +template +void coplanar_3_hull(InputIterator first, InputIterator beyond, + const Point_3& p1, const Point_3& p2, const Point_3& p3, + Polyhedron_3& P, const Traits& /* traits */) +{ + typedef typename internal::Convex_hull_3::Projection_traits PTraits; + typedef typename PTraits::Traits_xy_3 Traits_xy_3; + typedef typename PTraits::Traits_yz_3 Traits_yz_3; + typedef typename PTraits::Traits_xz_3 Traits_xz_3; + + std::list CH_2; + typedef typename std::list::iterator CH_2_iterator; + + Traits_xy_3 traits_xy; + typename Traits_xy_3::Left_turn_2 left_turn_in_xy = traits_xy.left_turn_2_object(); + if ( left_turn_in_xy(p1,p2,p3) || left_turn_in_xy(p2,p1,p3) ) + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_xy ); + else{ + Traits_yz_3 traits_yz; + typename Traits_yz_3::Left_turn_2 left_turn_in_yz = traits_yz.left_turn_2_object(); + if ( left_turn_in_yz(p1,p2,p3) || left_turn_in_yz(p2,p1,p3) ) + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_yz ); + else{ + Traits_xz_3 traits_xz; + typename Traits_xz_3::Left_turn_2 left_turn_in_xz = traits_xz.left_turn_2_object(); + CGAL_assertion( left_turn_in_xz(p1,p2,p3) || left_turn_in_xz(p2,p1,p3) ); + convex_hull_points_2( first, beyond, + std::back_inserter(CH_2), + traits_xz ); + } + } + + typedef typename Polyhedron_3::Halfedge_data_structure HDS; + + Build_coplanar_poly poly(CH_2.begin(),CH_2.end()); + P.delegate(poly); +} + + +// +// visible is the set of facets visible from point and reachable from +// start_facet. +// +template +void +find_visible_set(TDS_2& tds, + const typename Traits::Point_3& point, + typename TDS_2::Face_handle start, + std::list& visible, + std::map& outside, + const Traits& traits) +{ + typedef typename Traits::Plane_3 Plane_3; + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Vertex_handle Vertex_handle; + typename Traits::Has_on_positive_side_3 has_on_positive_side = + traits.has_on_positive_side_3_object(); + + std::vector vertices; + vertices.reserve(10); + int VISITED=1, BORDER=2; + visible.clear(); + typename std::list::iterator vis_it; + visible.push_back(start); + start->info() = VISITED; + vertices.push_back(start->vertex(0)); + vertices.push_back(start->vertex(1)); + vertices.push_back(start->vertex(2)); + start->vertex(0)->info() = start->vertex(1)->info() = start->vertex(2)->info() = VISITED; + + for (vis_it = visible.begin(); vis_it != visible.end(); vis_it++) + { + // check all the neighbors of the current face to see if they have + // already been visited or not and if not whether they are visible + // or not. + + for(int i=0; i < 3; i++) { + // the facet on the other side of the current halfedge + Face_handle f = (*vis_it)->neighbor(i); + // if haven't already seen this facet + if (f->info() == 0) { + f->info() = VISITED; + Plane_3 plane(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + int ind = f->index(*vis_it); + if ( has_on_positive_side(plane, point) ){ // is visible + visible.push_back(f); + Vertex_handle vh = f->vertex(ind); + if(vh->info() == 0){ vertices.push_back(vh); vh->info() = VISITED;} + } else { + f->info() = BORDER; + f->vertex(TDS_2::cw(ind))->info() = BORDER; + f->vertex(TDS_2::ccw(ind))->info() = BORDER; + outside.insert(std::make_pair(f->vertex(TDS_2::cw(ind)), + typename TDS_2::Edge(f,ind))); + } + } else if(f->info() == BORDER) { + int ind = f->index(*vis_it); + f->vertex(TDS_2::cw(ind))->info() = BORDER; + f->vertex(TDS_2::ccw(ind))->info() = BORDER; + outside.insert(std::make_pair(f->vertex(TDS_2::cw(ind)), + typename TDS_2::Edge(f,ind))); + } + } + } + + for(typename std::vector::iterator vit = vertices.begin(); + vit != vertices.end(); + ++vit){ + if((*vit)->info() != BORDER){ + tds.delete_vertex(*vit); + } else { + (*vit)->info() = 0; + } + } + +} + +// using a third template parameter for the point instead of getting it from +// the traits class as it should be is required by M$VC6 +template +typename std::list::iterator +farthest_outside_point(Face_handle f, std::list& outside_set, + const Traits& traits) +{ + + typedef typename std::list::iterator Outside_set_iterator; + CGAL_ch_assertion(!outside_set.empty()); + + typename Traits::Plane_3 plane(f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + + typename Traits::Less_signed_distance_to_plane_3 less_dist_to_plane = + traits.less_signed_distance_to_plane_3_object(); + Outside_set_iterator farthest_it = + std::max_element(outside_set.begin(), + outside_set.end(), + boost::bind(less_dist_to_plane, plane, _1, _2)); + return farthest_it; +} + +template +void +partition_outside_sets(const std::list& new_facets, + std::list& vis_outside_set, + std::list& pending_facets, + const Traits& traits) +{ + typename std::list::const_iterator f_list_it; + typename std::list::iterator point_it, to_splice; + + // walk through all the new facets and check each unassigned outside point + // to see if it belongs to the outside set of this new facet. + for (f_list_it = new_facets.begin(); (f_list_it != new_facets.end()) && (! vis_outside_set.empty()); + ++f_list_it) + { + Face_handle f = *f_list_it; + Is_on_positive_side_of_plane_3 is_on_positive_side( + traits,f->vertex(0)->point(),f->vertex(1)->point(),f->vertex(2)->point()); + std::list& point_list = f->points; + + for (point_it = vis_outside_set.begin();point_it != vis_outside_set.end();){ + if( is_on_positive_side(*point_it) ) { + to_splice = point_it; + ++point_it; + point_list.splice(point_list.end(), vis_outside_set, to_splice); + } else { + ++point_it; + } + } + if(! point_list.empty()){ + pending_facets.push_back(f); + f->it = boost::prior(pending_facets.end()); + } else { + f->it = pending_facets.end(); + } + } + + + for (; f_list_it != new_facets.end();++f_list_it) + (*f_list_it)->it = pending_facets.end(); +} + + + +template +void +ch_quickhull_3_scan(TDS_2& tds, + std::list& pending_facets, + const Traits& traits) +{ + typedef typename TDS_2::Edge Edge; + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Vertex_handle Vertex_handle; + typedef typename Traits::Point_3 Point_3; + typedef std::list Outside_set; + typedef typename std::list::iterator Outside_set_iterator; + typedef std::map Border_edges; + + std::list visible_set; + typename std::list::iterator vis_set_it; + Outside_set vis_outside_set; + Border_edges border; + + while (!pending_facets.empty()) + { + vis_outside_set.clear(); + + Face_handle f_handle = pending_facets.front(); + + Outside_set_iterator farthest_pt_it = farthest_outside_point(f_handle, f_handle->points, traits); + Point_3 farthest_pt = *farthest_pt_it; + f_handle->points.erase(farthest_pt_it); + find_visible_set(tds, farthest_pt, f_handle, visible_set, border, traits); + + // for each visible facet + for (vis_set_it = visible_set.begin(); vis_set_it != visible_set.end(); + vis_set_it++) + { + + // add its outside set to the global outside set list + std::list& point_list = (*vis_set_it)->points; + if(! point_list.empty()){ + vis_outside_set.splice(vis_outside_set.end(), point_list, point_list.begin(), point_list.end()); + } + + if((*vis_set_it)->it != pending_facets.end()){ + pending_facets.erase((*vis_set_it)->it); + } + (*vis_set_it)->info() = 0; + } + + std::vector edges; + edges.reserve(border.size()); + typename Border_edges::iterator it = border.begin(); + Edge e = it->second; + e.first->info() = 0; + edges.push_back(e); + border.erase(it); + while(! border.empty()){ + it = border.find(e.first->vertex(TDS_2::ccw(e.second))); + assert(it != border.end()); + e = it->second; + e.first->info() = 0; + edges.push_back(e); + border.erase(it); + } + + // If we want to reuse the faces we must only pass |edges| many, and call delete_face for the others. + // Also create facets if necessary + std::ptrdiff_t diff = visible_set.size() - edges.size(); + if(diff < 0){ + for(int i = 0; i<-diff;i++){ + visible_set.push_back(tds.create_face()); + } + } else { + for(int i = 0; ipoint() = farthest_pt; + vh->info() = 0; + + // now partition the set of outside set points among the new facets. + + partition_outside_sets(visible_set, vis_outside_set, + pending_facets, traits); + + } +} + +template +void non_coplanar_quickhull_3(std::list& points, + TDS_2& tds, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + + typedef typename TDS_2::Face_handle Face_handle; + typedef typename TDS_2::Face_iterator Face_iterator; + typedef typename std::list::iterator P3_iterator; + + std::list pending_facets; + + typename Is_on_positive_side_of_plane_3::Protector p; + + // for each facet, look at each unassigned point and decide if it belongs + // to the outside set of this facet. + for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){ + Is_on_positive_side_of_plane_3 is_on_positive_side( + traits,fit->vertex(0)->point(),fit->vertex(1)->point(),fit->vertex(2)->point() ); + for (P3_iterator point_it = points.begin() ; point_it != points.end(); ) + { + if( is_on_positive_side(*point_it) ) { + P3_iterator to_splice = point_it; + ++point_it; + fit->points.splice(fit->points.end(), points, to_splice); + } else { + ++point_it; + } + } + } + // add all the facets with non-empty outside sets to the set of facets for + // further consideration + for(Face_iterator fit = tds.faces_begin(); fit != tds.faces_end(); ++fit){ + if (! fit->points.empty()){ + pending_facets.push_back(fit); + fit->it = boost::prior(pending_facets.end()); + } else { + fit->it = pending_facets.end(); + } + } + + + ch_quickhull_3_scan(tds, pending_facets, traits); + + //std::cout << "|V(tds)| = " << tds.number_of_vertices() << std::endl; +// CGAL_ch_expensive_postcondition(all_points_inside(points.begin(), +// points.end(),P,traits)); +// CGAL_ch_postcondition(is_strongly_convex_3(P, traits)); +} + + +namespace internal{ + +template +class Build_convex_hull_from_TDS_2 : public CGAL::Modifier_base { + typedef std::map Vertex_map; + + const TDS& t; + template + static unsigned get_vertex_index( Vertex_map& vertex_map, + typename TDS::Vertex_handle vh, + Builder& builder, + unsigned& vindex) + { + std::pair + res=vertex_map.insert(std::make_pair(vh,vindex)); + if (res.second){ + builder.add_vertex(vh->point()); + ++vindex; + } + return res.first->second; + } + +public: + Build_convex_hull_from_TDS_2(const TDS& t_):t(t_) + { + CGAL_assertion(t.dimension()==2); + } + void operator()( HDS& hds) { + // Postcondition: `hds' is a valid polyhedral surface. + + CGAL::Polyhedron_incremental_builder_3 B( hds, true); + Vertex_map vertex_map; + //start the surface + B.begin_surface( t.number_of_vertices(), t.number_of_faces()); + unsigned vindex=0; + for (typename TDS::Face_iterator it=t.faces_begin();it!=t.faces_end();++it) + { + unsigned i0=get_vertex_index(vertex_map,it->vertex(0),B,vindex); + unsigned i1=get_vertex_index(vertex_map,it->vertex(1),B,vindex); + unsigned i2=get_vertex_index(vertex_map,it->vertex(2),B,vindex); + B.begin_facet(); + B.add_vertex_to_facet( i0 ); + B.add_vertex_to_facet( i1 ); + B.add_vertex_to_facet( i2 ); + B.end_facet(); + } + B.end_surface(); + } +}; + +} //namespace internal + +template +void +ch_quickhull_polyhedron_3(std::list& points, + InputIterator point1_it, InputIterator point2_it, + InputIterator point3_it, Polyhedron_3& P, + const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef typename Traits::Plane_3 Plane_3; + typedef typename std::list::iterator P3_iterator; + + typedef Triangulation_data_structure_2< + Triangulation_vertex_base_with_info_2 >, + Convex_hull_face_base_2 > Tds; + typedef typename Tds::Vertex_handle Vertex_handle; + typedef typename Tds::Face_handle Face_handle; + + // found three points that are not collinear, so construct the plane defined + // by these points and then find a point that has maximum distance from this + // plane. + typename Traits::Construct_plane_3 construct_plane = + traits.construct_plane_3_object(); + Plane_3 plane = construct_plane(*point3_it, *point2_it, *point1_it); + typedef typename Traits::Less_signed_distance_to_plane_3 Dist_compare; + Dist_compare compare_dist = traits.less_signed_distance_to_plane_3_object(); + + typename Traits::Coplanar_3 coplanar = traits.coplanar_3_object(); + // find both min and max here since using signed distance. If all points + // are on the negative side of the plane, the max element will be on the + // plane. + std::pair min_max; + min_max = CGAL::min_max_element(points.begin(), points.end(), + boost::bind(compare_dist, plane, _1, _2), + boost::bind(compare_dist, plane, _1, _2)); + P3_iterator max_it; + if (coplanar(*point1_it, *point2_it, *point3_it, *min_max.second)) + { + max_it = min_max.first; + // want the orientation of the points defining the plane to be positive + // so have to reorder these points if all points were on negative side + // of plane + std::swap(*point1_it, *point3_it); + } + else + max_it = min_max.second; + + // if the maximum distance point is on the plane then all are coplanar + if (coplanar(*point1_it, *point2_it, *point3_it, *max_it)) { + coplanar_3_hull(points.begin(), points.end(), *point1_it, *point2_it, *point3_it, P, traits); + } else { + Tds tds; + Vertex_handle v0 = tds.create_vertex(); v0->set_point(*point1_it); + Vertex_handle v1 = tds.create_vertex(); v1->set_point(*point2_it); + Vertex_handle v2 = tds.create_vertex(); v2->set_point(*point3_it); + Vertex_handle v3 = tds.create_vertex(); v3->set_point(*max_it); + + v0->info() = v1->info() = v2->info() = v3->info() = 0; + Face_handle f0 = tds.create_face(v0,v1,v2); + Face_handle f1 = tds.create_face(v3,v1,v0); + Face_handle f2 = tds.create_face(v3,v2,v1); + Face_handle f3 = tds.create_face(v3,v0,v2); + tds.set_dimension(2); + f0->set_neighbors(f2, f3, f1); + f1->set_neighbors(f0, f3, f2); + f2->set_neighbors(f0, f1, f3); + f3->set_neighbors(f0, f2, f1); + + points.erase(point1_it); + points.erase(point2_it); + points.erase(point3_it); + points.erase(max_it); + if (!points.empty()){ + non_coplanar_quickhull_3(points, tds, traits); + internal::Build_convex_hull_from_TDS_2 builder(tds); + P.delegate(builder); + } + else + P.make_tetrahedron(v0->point(),v1->point(),v2->point(),v3->point()); + } + +} + +} } //namespace internal::Convex_hull_3 + +template +void +convex_hull_3(InputIterator first, InputIterator beyond, + Object& ch_object, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef std::list Point_3_list; + typedef typename Point_3_list::iterator P3_iterator; + typedef std::pair P3_iterator_pair; + + if (first == beyond) // No point + return; + + // If the first and last point are equal the collinearity test some lines below will always be true. + Point_3_list points(first, beyond); + std::size_t size = points.size(); + while((size > 1) && (points.front() == points.back())){ + points.pop_back(); + --size; + } + + if ( size == 1 ) // 1 point + { + ch_object = make_object(*points.begin()); + return; + } + else if ( size == 2 ) // 2 points + { + typedef typename Traits::Segment_3 Segment_3; + typename Traits::Construct_segment_3 construct_segment = + traits.construct_segment_3_object(); + Segment_3 seg = construct_segment(*points.begin(), *(++points.begin())); + ch_object = make_object(seg); + return; + } + else if ( size == 3 ) // 3 points + { + typedef typename Traits::Triangle_3 Triangle_3; + typename Traits::Construct_triangle_3 construct_triangle = + traits.construct_triangle_3_object(); + Triangle_3 tri = construct_triangle(*(points.begin()), + *(++points.begin()), + *(--points.end())); + ch_object = make_object(tri); + return; + } + + // at least 4 points + typename Traits::Collinear_3 collinear = traits.collinear_3_object(); + + P3_iterator point1_it = points.begin(); + P3_iterator point2_it = points.begin(); + point2_it++; + P3_iterator point3_it = points.end(); + point3_it--; + + // find three that are not collinear + while (point2_it != points.end() && + collinear(*point1_it,*point2_it,*point3_it)) + point2_it++; + + + // all are collinear, so the answer is a segment + if (point2_it == points.end()) + { + typedef typename Traits::Less_distance_to_point_3 Less_dist; + + Less_dist less_dist = traits.less_distance_to_point_3_object(); + P3_iterator_pair endpoints = + min_max_element(points.begin(), points.end(), + boost::bind(less_dist, *points.begin(), _1, _2), + boost::bind(less_dist, *points.begin(), _1, _2)); + + typename Traits::Construct_segment_3 construct_segment = + traits.construct_segment_3_object(); + typedef typename Traits::Segment_3 Segment_3; + + Segment_3 seg = construct_segment(*endpoints.first, *endpoints.second); + ch_object = make_object(seg); + return; + } + + // result will be a polyhedron + typename internal::Convex_hull_3::Default_polyhedron_for_Chull_3::type P; + + P3_iterator minx, maxx, miny, it; + minx = maxx = miny = it = points.begin(); + ++it; + for(; it != points.end(); ++it){ + if(it->x() < minx->x()) minx = it; + if(it->x() > maxx->x()) maxx = it; + if(it->y() < miny->y()) miny = it; + } + if(! collinear(*minx, *maxx, *miny) ){ + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); + } else { + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, P, traits); + } + CGAL_assertion(P.size_of_vertices()>=3); + if (boost::next(P.vertices_begin(),3) == P.vertices_end()){ + typedef typename Traits::Triangle_3 Triangle_3; + typename Traits::Construct_triangle_3 construct_triangle = + traits.construct_triangle_3_object(); + Triangle_3 tri = construct_triangle(P.halfedges_begin()->vertex()->point(), + P.halfedges_begin()->next()->vertex()->point(), + P.halfedges_begin()->opposite()->vertex()->point()); + ch_object = make_object(tri); + } + else + ch_object = make_object(P); +} + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Object& ch_object) +{ + typedef typename std::iterator_traits::value_type Point_3; + typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + convex_hull_3(first, beyond, ch_object, Traits()); +} + + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Polyhedron_3& polyhedron, const Traits& traits) +{ + typedef typename Traits::Point_3 Point_3; + typedef std::list Point_3_list; + typedef typename Point_3_list::iterator P3_iterator; + + Point_3_list points(first, beyond); + CGAL_ch_precondition(points.size() > 3); + + // at least 4 points + typename Traits::Collinear_3 collinear = traits.collinear_3_object(); + typename Traits::Equal_3 equal = traits.equal_3_object(); + + P3_iterator point1_it = points.begin(); + P3_iterator point2_it = points.begin(); + point2_it++; + + // find three that are not collinear + while (point2_it != points.end() && equal(*point1_it,*point2_it)) + ++point2_it; + + CGAL_ch_precondition_msg(point2_it != points.end(), + "All points are equal; cannot construct polyhedron."); + + P3_iterator point3_it = point2_it; + ++point3_it; + + CGAL_ch_precondition_msg(point3_it != points.end(), + "Only two points with different coordinates; cannot construct polyhedron."); + + while (point3_it != points.end() && collinear(*point1_it,*point2_it,*point3_it)) + ++point3_it; + + CGAL_ch_precondition_msg(point3_it != points.end(), + "All points are collinear; cannot construct polyhedron."); + + polyhedron.clear(); + // result will be a polyhedron + internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, + polyhedron, traits); + +} + + +template +void convex_hull_3(InputIterator first, InputIterator beyond, + Polyhedron_3& polyhedron) +{ + typedef typename std::iterator_traits::value_type Point_3; + typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + convex_hull_3(first, beyond, polyhedron, Traits()); +} + +} // namespace CGAL + +#endif // CGAL_CONVEX_HULL_3_H diff --git a/testdata/scad/bugs/issue1089b.scad b/testdata/scad/bugs/issue1089b.scad new file mode 100644 index 00000000..4cf13cb9 --- /dev/null +++ b/testdata/scad/bugs/issue1089b.scad @@ -0,0 +1,3 @@ +hull() { + polyhedron(points = [[21.015921990298082278, -9.6968661252791008565, 17.385898562432661407], [21.015921990298082278, 9.4292289939816065214, 11.538464467977924244], [21.245998787904895266, 9.1447008983105675384, 10.607815001220002316], [21.245998787904895266, -0.41834666131978626158, 13.531532048447369121], [21.245998787904895266, -9.9813942209501398395, 16.455249095674737703], [16.150059612458484537, -10.033205852946363024, 17.385898562432661407], [16.150059612458484537, 9.0928892663143443542, 11.538464467977924244], [16.380136410065297525, 8.8083611706433053712, 10.607815001220002316], [16.380136410065297525, -0.75468638898704798468, 13.531532048447369121], [16.380136410065297525, -10.317733948617402007, 16.455249095674737703], [15.17688713689056712, -10.100473798479814747, 17.165875026644524581], [15.17688713689056712, 9.0256213207808926313, 11.318440932189787418], [15.406963934497380109, 8.7410932251098536483, 10.38779146543186549], [15.406963934497380109, -0.82195433452049937451, 13.311508512659232295], [15.406963934497380109, -10.38500189415085373, 16.235225559886600877], [14.152135476691794835, -10.17119106380654614, 16.934569274178546294], [14.152135476691794835, 8.954904055454161238, 11.087135179723812684], [14.367990727181227939, 8.6694249043464353122, 10.153374950800477805], [14.367990727181227939, -0.89362265528391870983, 13.077091998027846387], [14.367990727181227939, -10.456670214914272066, 16.000809045255213192], [13.110820024653460081, -10.233961476664669377, 16.729256504918232906], [13.110820024653460081, 8.8921336425960380012, 10.881822410463495743], [13.309600712109528331, 8.6055965081559246954, 9.9446016739871083701], [13.309600712109528331, -0.95745105147442877147, 12.868318721214476952], [13.309600712109528331, -10.520498611104782682, 15.792035768441845534], [12.078282570414469177, -10.294222837947037519, 16.532150473574372285], [12.078282570414469177, 8.8318722813136698591, 10.684716379119635121], [12.262745467026753943, 8.5445178276236166681, 9.7448223118344454718], [12.262745467026753943, -1.0185297320067365767, 12.668539359061812277], [12.262745467026753943, -10.58157729163709071, 15.592256406289180859], [11.031163105767490151, -10.348029755406946251, 16.356155976708063093], [11.031163105767490151, 8.7780653638537611272, 10.508721882253327706], [11.198443837973723447, 8.4898133798050405829, 9.5658921254443249893], [11.198443837973723447, -1.0732341798253119958, 12.489609172671691795], [11.198443837973723447, -10.636281739455666795, 15.413326219899060376], [9.9920867282612331195, -10.397762464907449598, 16.193487613614035325], [9.9920867282612331195, 8.7283326543532577801, 10.346053519159298162], [10.144967804693861169, 8.4393978978853763095, 9.4009905143952519069], [10.144967804693861169, -1.1236496617449773794, 12.324707561622618712], [10.144967804693861169, -10.686697221375331068, 15.248424608849987294], [8.9400347163076823165, -10.442561786292975157, 16.046955635953878527], [8.9400347163076823165, 8.6835333329677322212, 10.199521541499144917], [9.0756439452541037838, 8.3938624405481636614, 9.2520507445299653426], [9.0756439452541037838, -1.1691851190821893614, 12.175767791757333924], [9.0756439452541037838, -10.732232678712543716, 15.09948483898470073], [7.8956741722639147696, -10.481705796269976005, 15.918921348422623296], [7.8956741722639147696, 8.6443893229907313724, 10.071487253967887909], [8.0168163367886453585, 8.3541708868691326728, 9.1222255222471790859], [8.0168163367886453585, -1.2088766727612223484, 12.045942569474547668], [8.0168163367886453585, -10.771924232391574705, 14.969659616701914473], [6.839564786514664263, -10.51746028460065574, 15.801973686643666639], [6.839564786514664263, 8.6086348346600516379, 9.9545395921889312518], [6.9433634354009168277, 8.3178424250433771192, 9.0034004777589125013], [6.9433634354009168277, -1.2452051345869770138, 11.927117524986281083], [6.9433634354009168277, -10.808252694217330259, 14.850834572213647888], [5.7911812064893624097, -10.545968319665455226, 15.708728105504132344], [5.7911812064893624097, 8.5801267995952521517, 9.861294011049396957], [5.8804599030361934808, 8.2889226275126546284, 8.9088080822795312486], [5.8804599030361934808, -1.2741249321176979503, 11.83252512950689983], [5.8804599030361934808, -10.837172491748052749, 14.756242176734266636], [4.7318927519149163174, -10.572647626142034127, 15.621464026055862817], [4.7318927519149163174, 8.5534474931186732505, 9.77402993160112743], [4.8037743563616075448, 8.2618321038161273151, 8.8201989719106297372], [4.8037743563616075448, -1.3012154558142254857, 11.743916019137996543], [4.8037743563616075448, -10.864263015444580063, 14.667633066365365124], [3.6807521204854736219, -10.590485240237288878, 15.563119819284901624], [3.6807521204854736219, 8.5356098790234185003, 9.7156857248301662366], [3.7380754567641063524, 8.2437189311402967462, 8.7609534536348423472], [3.7380754567641063524, -1.3193286284900567207, 11.684670500862209153], [3.7380754567641063524, -10.882376188120410632, 14.608387548089577734], [2.6191654551378640292, -10.608065925320802947, 15.505615989444741842], [2.6191654551378640292, 8.518029193939904431, 9.6581818949900064553], [2.659056271348898548, 8.2258902040489321195, 8.7026383149438082398], [2.659056271348898548, -1.3371573555814209033, 11.626355362171176822], [2.659056271348898548, -10.900204915211775258, 14.550072409398543627], [1.5571301313920737908, -10.615277603175528043, 15.482027654049947074], [1.5571301313920737908, 8.5108175160851793351, 9.634593559595211687], [1.5798452641030620303, 8.2185212496694965978, 8.6785355512163384617], [1.5798452641030620303, -1.3445263099608570911, 11.602252598443705267], [1.5798452641030620303, -10.90757386959121078, 14.525969645671073849], [0.5035077216434232783, -10.622159719563320834, 15.459517265642222839], [0.5035077216434232783, 8.5039353996973865435, 9.6120831711874892278], [0.5113668014119475691, 8.2115727243029539295, 8.6558079488265811108], [0.5113668014119475691, -1.3514748353273995374, 11.579524996053947916], [0.5113668014119475691, -10.914522394957753448, 14.503242043281314722], [-0.55969246949480999653, -10.620097256783905593, 15.466263277424799227], [-0.55969246949480999653, 8.5059978624768017852, 9.6188291829700638402], [-0.56928712712562057341, 8.2136396155613287107, 8.6625684455111535698], [-0.56928712712562057341, -1.3494079440690252003, 11.586285492738520375], [-0.56928712712562057341, -10.912455503699378667, 14.510002539965888957], [-1.6125195715995086498, -10.616272236324949318, 15.478774355608731383], [-1.6125195715995086498, 8.5098228829357580594, 9.6313402611539977727], [-1.6367003391161654147, 8.2175366669705987022, 8.6753151263175354302], [-1.6367003391161654147, -1.3455108926597549868, 11.599032173544902236], [-1.6367003391161654147, -10.908558452290108676, 14.522749220772269041], [-2.6750035922459902693, -10.605089410934800398, 15.515351729318147989], [-2.6750035922459902693, 8.5210057083259069799, 9.6679176348634126015], [-2.7166291222015424012, 8.2288874074141755699, 8.7124417254191364179], [-2.7166291222015424012, -1.334160152216178119, 11.636158772646505], [-2.7166291222015424012, -10.897207711846531808, 14.559875819873871805], [-3.7267390106727740218, -10.590568334550255258, 15.562848030033741509], [-3.7267390106727740218, 8.5355267847104521195, 9.7154139355790061217], [-3.7829348904509538798, 8.2436170965810333655, 8.7606203678000085233], [-3.7829348904509538798, -1.3194304630493196573, 11.684337415027377105], [-3.7829348904509538798, -10.882478022679674012, 14.60805446225474391], [-4.7876230981018181865, -10.570275178726245002, 15.629223951898024936], [-4.7876230981018181865, 8.5558199405344623756, 9.7817898574432895487], [-4.8612365692795815875, 8.2642414847358942609, 8.828079701800975343], [-4.8612365692795815875, -1.2988060748944600942, 11.751796749028343925], [-4.8612365692795815875, -10.861853634524813117, 14.67551379625571073], [-5.8369967953404051642, -10.545075590745145888, 15.711648090230719177], [-5.8369967953404051642, 8.5810195285155614897, 9.8642139957759837898], [-5.9251502312697619246, 8.2897860538008281139, 8.9116322224150632536], [-5.9251502312697619246, -1.2732615058295262411, 11.835349269642431835], [-5.9251502312697619246, -10.836309065459879264, 14.759066316869798641], [-6.895398463720493254, -10.515689075464781155, 15.807767050683622756], [-6.895398463720493254, 8.6104060437959262231, 9.9603329562288873689], [-7.0009241527878049993, 8.3196667739247160966, 9.0093676540744773718], [-7.0009241527878049993, -1.2433807857056371482, 11.933084701301844177], [-7.0009241527878049993, -10.806428345335991281, 14.856801748529212759], [-7.9411432512251920457, -10.47984140089607763, 15.925019510913235976], [-7.9411432512251920457, 8.6462537183646297478, 10.077585416458500589], [-8.0611639241462889061, 8.355995453894500713, 9.1281934120797192378], [-8.0611639241462889061, -1.2070521057358516437, 12.05191045930708782], [-8.0611639241462889061, -10.770099665366206665, 14.975627506534454625], [-8.9961818731247724656, -10.441385424593725872, 16.050803341698156146], [-8.9961818731247724656, 8.6847096946669815054, 10.203369247243418982], [-9.1335113425972984658, 8.3951080877002439706, 9.2561250727790511661], [-9.1335113425972984658, -1.1679394719301097183, 12.179842120006419748], [-9.1335113425972984658, -10.730987031560463407, 15.103559167233786553], [-10.037034938423907704, -10.394932932465536624, 16.202742597210743725], [-10.037034938423907704, 8.7311621867951707543, 10.355308502756006561], [-10.188799857367065727, 8.4421771354154273581, 9.4100809907477991345], [-10.188799857367065727, -1.120870424214927441, 12.33379803797516594], [-10.188799857367065727, -10.68391798384528002, 15.257515085202534522], [-11.087832325460665217, -10.347438306258311513, 16.358090519704578725], [-11.087832325460665217, 8.7786568130023958645, 10.510656425249845114], [-11.25682453492664159, 8.4904901774226715361, 9.5681058307041340072], [-11.25682453492664159, -1.0725573822076825969, 12.491822877931500813], [-11.25682453492664159, -10.635604941838035842, 15.415539925158867618], [-12.130826484007744881, -10.28998208592428476, 16.546021348432333298], [-12.130826484007744881, 8.8361130333364226175, 10.698587253977599687], [-12.316465776491348549, 8.5488233456115647613, 9.7589050266192529648], [-12.316465776491348549, -1.0142242140187893717, 12.68262207384661977], [-12.316465776491348549, -10.577271773649142617, 15.606339121073986576], [-13.167274479509028851, -10.232609601207819594, 16.733678290296118973], [-13.167274479509028851, 8.8934855180528877838, 10.886244195841383586], [-13.36775592988668393, 8.6070496903803430655, 9.9493548188709652891], [-13.36775592988668393, -0.9559978692500109565, 12.873071866098332094], [-13.36775592988668393, -10.519045428880364312, 15.796788913325700676], [-14.205661711313787521, -10.165804085335658158, 16.952189286815759317], [-14.205661711313787521, 8.96029103392504922, 11.104755192361025706], [-14.423211305781006075, 8.6749218454890240082, 10.171354635130359867], [-14.423211305781006075, -0.88812571414133034686, 13.095071682357726672], [-14.423211305781006075, -10.45117327377168337, 16.018788729585093478], [-15.232758954180525279, -10.098059861404790283, 17.173770659047207232], [-15.232758954180525279, 9.0280352578559170951, 11.326336564592470069], [-15.464523864863501501, 8.7436243006743357142, 10.396070240569519783], [-15.464523864863501501, -0.81942325895601786367, 13.319787287796886588], [-15.464523864863501501, -10.382470818586371664, 16.24350433502425517], [-16.263941232543412951, -10.022378056180794914, 17.421314689835732281], [-16.263941232543412951, 9.1037170630799124638, 11.573880595380996894], [-16.512649129623643063, 8.8205321051208152028, 10.647624334125161738], [-16.512649129623643063, -0.74251545450953948535, 13.571341381352528543], [-16.512649129623643063, -10.305563014139892175, 16.495058428579895349], [-17.249434174697078959, -9.946811825017595865, 17.668480694904857842], [-17.249434174697078959, 9.1792832942431115129, 11.821046600450122455], [-17.503165223042536525, 8.8964795095546467252, 10.896037100784631946], [-17.503165223042536525, -0.66656805007570774091, 13.819754148011998751], [-17.503165223042536525, -10.229615609706060653, 16.743471195239365557]], faces = [[0, 1, 6, 5], [1, 2, 7, 6], [2, 3, 8, 7], [3, 4, 9, 8], [4, 0, 5, 9], [5, 6, 11, 10], [6, 7, 12, 11], [7, 8, 13, 12], [8, 9, 14, 13], [9, 5, 10, 14], [10, 11, 16, 15], [11, 12, 17, 16], [12, 13, 18, 17], [13, 14, 19, 18], [14, 10, 15, 19], [15, 16, 21, 20], [16, 17, 22, 21], [17, 18, 23, 22], [18, 19, 24, 23], [19, 15, 20, 24], [20, 21, 26, 25], [21, 22, 27, 26], [22, 23, 28, 27], [23, 24, 29, 28], [24, 20, 25, 29], [25, 26, 31, 30], [26, 27, 32, 31], [27, 28, 33, 32], [28, 29, 34, 33], [29, 25, 30, 34], [30, 31, 36, 35], [31, 32, 37, 36], [32, 33, 38, 37], [33, 34, 39, 38], [34, 30, 35, 39], [35, 36, 41, 40], [36, 37, 42, 41], [37, 38, 43, 42], [38, 39, 44, 43], [39, 35, 40, 44], [40, 41, 46, 45], [41, 42, 47, 46], [42, 43, 48, 47], [43, 44, 49, 48], [44, 40, 45, 49], [45, 46, 51, 50], [46, 47, 52, 51], [47, 48, 53, 52], [48, 49, 54, 53], [49, 45, 50, 54], [50, 51, 56, 55], [51, 52, 57, 56], [52, 53, 58, 57], [53, 54, 59, 58], [54, 50, 55, 59], [55, 56, 61, 60], [56, 57, 62, 61], [57, 58, 63, 62], [58, 59, 64, 63], [59, 55, 60, 64], [60, 61, 66, 65], [61, 62, 67, 66], [62, 63, 68, 67], [63, 64, 69, 68], [64, 60, 65, 69], [65, 66, 71, 70], [66, 67, 72, 71], [67, 68, 73, 72], [68, 69, 74, 73], [69, 65, 70, 74], [70, 71, 76, 75], [71, 72, 77, 76], [72, 73, 78, 77], [73, 74, 79, 78], [74, 70, 75, 79], [75, 76, 81, 80], [76, 77, 82, 81], [77, 78, 83, 82], [78, 79, 84, 83], [79, 75, 80, 84], [80, 81, 86, 85], [81, 82, 87, 86], [82, 83, 88, 87], [83, 84, 89, 88], [84, 80, 85, 89], [85, 86, 91, 90], [86, 87, 92, 91], [87, 88, 93, 92], [88, 89, 94, 93], [89, 85, 90, 94], [90, 91, 96, 95], [91, 92, 97, 96], [92, 93, 98, 97], [93, 94, 99, 98], [94, 90, 95, 99], [95, 96, 101, 100], [96, 97, 102, 101], [97, 98, 103, 102], [98, 99, 104, 103], [99, 95, 100, 104], [100, 101, 106, 105], [101, 102, 107, 106], [102, 103, 108, 107], [103, 104, 109, 108], [104, 100, 105, 109], [105, 106, 111, 110], [106, 107, 112, 111], [107, 108, 113, 112], [108, 109, 114, 113], [109, 105, 110, 114], [110, 111, 116, 115], [111, 112, 117, 116], [112, 113, 118, 117], [113, 114, 119, 118], [114, 110, 115, 119], [115, 116, 121, 120], [116, 117, 122, 121], [117, 118, 123, 122], [118, 119, 124, 123], [119, 115, 120, 124], [120, 121, 126, 125], [121, 122, 127, 126], [122, 123, 128, 127], [123, 124, 129, 128], [124, 120, 125, 129], [125, 126, 131, 130], [126, 127, 132, 131], [127, 128, 133, 132], [128, 129, 134, 133], [129, 125, 130, 134], [130, 131, 136, 135], [131, 132, 137, 136], [132, 133, 138, 137], [133, 134, 139, 138], [134, 130, 135, 139], [135, 136, 141, 140], [136, 137, 142, 141], [137, 138, 143, 142], [138, 139, 144, 143], [139, 135, 140, 144], [140, 141, 146, 145], [141, 142, 147, 146], [142, 143, 148, 147], [143, 144, 149, 148], [144, 140, 145, 149], [145, 146, 151, 150], [146, 147, 152, 151], [147, 148, 153, 152], [148, 149, 154, 153], [149, 145, 150, 154], [150, 151, 156, 155], [151, 152, 157, 156], [152, 153, 158, 157], [153, 154, 159, 158], [154, 150, 155, 159], [155, 156, 161, 160], [156, 157, 162, 161], [157, 158, 163, 162], [158, 159, 164, 163], [159, 155, 160, 164], [160, 161, 166, 165], [161, 162, 167, 166], [162, 163, 168, 167], [163, 164, 169, 168], [164, 160, 165, 169], [4, 3, 2, 1, 0], [165, 166, 167, 168, 169]], convexity = 5); +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 608b60c1..efbbc163 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1217,10 +1217,12 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089.scad) #list(APPEND EXPORTCSG_TEST_FILES ) list(APPEND ALL_2D_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad) diff --git a/tests/regression/cgalpngtest/issue1089b-expected.png b/tests/regression/cgalpngtest/issue1089b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..f90390f007711b59155a5345dcffe00aa4d6e4fa GIT binary patch literal 6488 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 g^8YhNbxJPyBG!J!|cK_WAaA&OUpu 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 literal 0 HcmV?d00001 From 61c17092e1ee9542e0c5ff8961f3138864395da7 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 12:24:53 -0500 Subject: [PATCH 015/174] #1089 Only apply convex_hull_3 bugfix to appropriate CGAL versions --- src/cgalutils.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 97044e76..c320c2de 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -16,7 +16,8 @@ #include #include -#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) +// Apply CGAL bugfix. Note: If using CGAL < 4.3, hull() might be buggy +#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,3,0) #include #else #include "convex_hull_3_bugfix.h" From 1a6a7392e73dbf60ccb52f6ab7b1230d12bf5fd5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 12:39:49 -0500 Subject: [PATCH 016/174] #1089 Moved testcases to good tests --- testdata/scad/{bugs => 3D/issues}/issue1089.scad | 0 .../scad/{bugs => 3D/issues}/issue1089b.scad | 0 tests/CMakeLists.txt | 2 -- .../throwntogethertest/issue1089-expected.png | Bin 0 -> 5330 bytes .../throwntogethertest/issue1089b-expected.png | Bin 0 -> 6717 bytes 5 files changed, 2 deletions(-) rename testdata/scad/{bugs => 3D/issues}/issue1089.scad (100%) rename testdata/scad/{bugs => 3D/issues}/issue1089b.scad (100%) create mode 100644 tests/regression/throwntogethertest/issue1089-expected.png create mode 100644 tests/regression/throwntogethertest/issue1089b-expected.png diff --git a/testdata/scad/bugs/issue1089.scad b/testdata/scad/3D/issues/issue1089.scad similarity index 100% rename from testdata/scad/bugs/issue1089.scad rename to testdata/scad/3D/issues/issue1089.scad diff --git a/testdata/scad/bugs/issue1089b.scad b/testdata/scad/3D/issues/issue1089b.scad similarity index 100% rename from testdata/scad/bugs/issue1089b.scad rename to testdata/scad/3D/issues/issue1089b.scad diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index efbbc163..57b9e1ae 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1216,8 +1216,6 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1089b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES diff --git a/tests/regression/throwntogethertest/issue1089-expected.png b/tests/regression/throwntogethertest/issue1089-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..017bb85e097932fd62c89bc922d72545e91cbb68 GIT binary patch literal 5330 zcmeHL|5FoJ5P$c)=y4VjAxr>k6KmBdSR5%@i<2A#L8M|7T5A#fQU_2OM4=KSaEFXv zS{${~5ivL+;uN)|u~3T4AUUa)X~&8krYJQfXAuFR5D0`wzV-2U^nSW~Z+AbtZ|Cjq zXWkd;qGUq7YR*0OG2I*yt1u_OChhT-uYbaP?-Ze1rF9 zPghOWoEed3=SQtaq)|y>hSIp?hqoREE?n;F^Yl5Vy;_?PgE%qb<7z2rDEAS`D2|3C z8zrL{_67rke0zIvLZk-00I9_Z#B7%J(K3o*pmi=GlC54@1LDdG)*_jhSw}ITbQ>mE z9n#u}fNDVNEb>`W&iuh$-NFD&!1*HlJt-7+cJ5dfz%&OaWCBQy4!L#88h!6KaCR~lDlT|ym{A1E;E3R zVOWNJ+U&_d%Vp)tcPK6fwoRFcWXuJBkp{@rE4e&xKPP4@Z@M-@JSo6h-|4>%ROt^u zJbek5>cuk!Ry;*{5tORg0R`^*>kf2WsW5G1*a}=btjC=vrQd=!=7mutv&u2OGd@A_ z&w!kXm(K*FP{R;H*{SWXEfp&OdveUi=%YT`12p$$&Tj(Vo72O0i@;Yf8 zw-3c8nLnvV0Q7N(iFimlx|J(tq_-_z=XL!e&nE&A3|ano1(#>3diGiK$Kd?bWEWAr zoJ*zCmz~bO4*Y!DL-4m2Bd^4Rt9k=C)^Kd7AJ>kCONPpY+d=r;>0!dW6sb#ehVzKx zbSONlN-O6(x=qzuyJRKPGq|Ya6w~PrUZ0&~0BiFKrlQa(Er!v862x*8?6{FIhaz)h zb;}OKc6J{PDrkxOYSzCV37>4CqbC*p z;Z)mWqZ&v^TXnK_*cPV!El;I<9)St0RTpUQ56oeAheGM8-}<^P*3+)T#jK7?r0YBH z8ViTIn(V7EL2lv$y<2q0)!bWWj?zoiz_yixmgD-P#>;FPB)NBgdS$5a*52J(IMvml z)iE$DairN^+=ujC%@-#seOgr%)~a#`n{0*1Y$EeTf2RNYh&H|{YF`v;cDGDNnpDq- z(sGo>zB2cpvv!WbuuWVp@~xpfhhjVC?T>~{knYaOIfBYYbOskw_cJderg;~VHS3~u zh=t1h)nI{s?`)MJoZgY_Bt&dCQCO_@6ymjyLuVxC+`f$oMB~AT4pT-34*ve= xB@f8wkiRy3rSQ#x?}z+M;m0V?973&{ literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/issue1089b-expected.png b/tests/regression/throwntogethertest/issue1089b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c4475ab67ecabf8e405d836553b9071a0a49a760 GIT binary patch literal 6717 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 literal 0 HcmV?d00001 From 499a9717d7cf36a9c83c100e457ad6dd42b1b927 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 17:35:04 -0500 Subject: [PATCH 017/174] #1105 Added another testcase --- testdata/scad/bugs/issue1105b.scad | 11 +++++++++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1105b-expected.png | Bin 0 -> 8279 bytes .../monotonepngtest/issue1105b-expected.png | Bin 0 -> 8219 bytes .../opencsgtest/issue1105b-expected.png | Bin 0 -> 8583 bytes 5 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue1105b.scad create mode 100644 tests/regression/cgalpngtest/issue1105b-expected.png create mode 100644 tests/regression/monotonepngtest/issue1105b-expected.png create mode 100644 tests/regression/opencsgtest/issue1105b-expected.png diff --git a/testdata/scad/bugs/issue1105b.scad b/testdata/scad/bugs/issue1105b.scad new file mode 100644 index 00000000..3bfb3928 --- /dev/null +++ b/testdata/scad/bugs/issue1105b.scad @@ -0,0 +1,11 @@ +translate([54.5, -10, 2]) + rotate(90) + translate([2,30,26]) { + difference() { + cube(size = [4, 21.5, 4]); + translate([-0.1,-1.1,2]) cube(size = [2.1, 23.5, 2.1]); + } + } + +translate([-3,-8,12]) cube(size = [6, 3, 20]); +translate([0, -5, 2]) rotate(90) rotate_extrude($fn = 10) polygon(points = [[0, 18], [0, 30], [7, 26]]); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 57b9e1ae..8d147975 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1216,7 +1216,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1105b-expected.png b/tests/regression/cgalpngtest/issue1105b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..40fe3763625b292be8b09c85d5d4f2dab5002636 GIT binary patch literal 8279 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 literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue1105b-expected.png b/tests/regression/monotonepngtest/issue1105b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..86ca1284ea1eee2b702d70dc1af152542c9ea134 GIT binary patch literal 8219 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 A%m4rY literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue1105b-expected.png b/tests/regression/opencsgtest/issue1105b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..d124af22db37e5635f829e766d49121f4a8a82c3 GIT binary patch literal 8583 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 Date: Tue, 6 Jan 2015 17:35:19 -0500 Subject: [PATCH 018/174] sync --- xcode/OpenSCAD.xcodeproj/project.pbxproj | 10 ++++++ .../xcschemes/OpenSCAD.app.xcscheme | 32 +++++++++++++++++-- .../xcschemes/openscad_nogui.xcscheme | 10 ++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/xcode/OpenSCAD.xcodeproj/project.pbxproj b/xcode/OpenSCAD.xcodeproj/project.pbxproj index 418fa3fc..9535d40b 100644 --- a/xcode/OpenSCAD.xcodeproj/project.pbxproj +++ b/xcode/OpenSCAD.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ E0034E2019AA8409009F0BD0 /* dummy.c in Sources */ = {isa = PBXBuildFile; fileRef = E0034E1F19AA8409009F0BD0 /* dummy.c */; }; E018B43619AA8AA1004C9DF7 /* dummy.c in Sources */ = {isa = PBXBuildFile; fileRef = E0034E1F19AA8409009F0BD0 /* dummy.c */; }; + E0ED6EC71A50B0F3007E979A /* Test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E0ED6EC51A50B0F3007E979A /* Test.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -262,6 +263,10 @@ E0BD020A1979C2D90020CC1B /* FontListDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontListDialog.h; sourceTree = ""; }; E0BD020B1979C2D90020CC1B /* FreetypeRenderer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FreetypeRenderer.cc; sourceTree = ""; }; E0BD020C1979C2D90020CC1B /* FreetypeRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FreetypeRenderer.h; sourceTree = ""; }; + E0ED6EC51A50B0F3007E979A /* Test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Test.cpp; path = ../Test.cpp; sourceTree = ""; }; + E0ED6EC61A50B0F3007E979A /* Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Test.h; path = ../Test.h; sourceTree = ""; }; + E0F8E5411A5B02AB004723C5 /* cgalutils-polyhedron.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cgalutils-polyhedron.cc"; sourceTree = ""; }; + E0FCDD621A27B96C0024E633 /* clipper-utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "clipper-utils.cc"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ @@ -276,6 +281,8 @@ E022640517C307FA00499974 = { isa = PBXGroup; children = ( + E0ED6EC51A50B0F3007E979A /* Test.cpp */, + E0ED6EC61A50B0F3007E979A /* Test.h */, E018B43719AA8B2D004C9DF7 /* dummy sources */, E05FBE6A17C30A05004F525B /* src */, E056783C19AA721200F5650C /* Products */, @@ -328,11 +335,13 @@ E05FBE8817C30A05004F525B /* CGALRenderer.cc */, E05FBE8917C30A05004F525B /* CGALRenderer.h */, E091574D19AA58C900D699E9 /* cgalutils-tess.cc */, + E0F8E5411A5B02AB004723C5 /* cgalutils-polyhedron.cc */, E05FBE8A17C30A05004F525B /* cgalutils.cc */, E05FBE8B17C30A05004F525B /* cgalutils.h */, E05FBE8C17C30A05004F525B /* cgalworker.cc */, E05FBE8D17C30A05004F525B /* cgalworker.h */, E091574E19AA58C900D699E9 /* clipper-utils.h */, + E0FCDD621A27B96C0024E633 /* clipper-utils.cc */, E05FBE8E17C30A05004F525B /* CocoaUtils.h */, E05FBE8F17C30A05004F525B /* CocoaUtils.mm */, E05FBE9017C30A05004F525B /* color.cc */, @@ -661,6 +670,7 @@ buildActionMask = 2147483647; files = ( E0034E2019AA8409009F0BD0 /* dummy.c in Sources */, + E0ED6EC71A50B0F3007E979A /* Test.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme index 34ad778b..4779571b 100644 --- a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme +++ b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/OpenSCAD.app.xcscheme @@ -60,13 +60,41 @@ + + + + + + + + + + + + + + diff --git a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme index f230c7fa..4e34982a 100644 --- a/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme +++ b/xcode/OpenSCAD.xcodeproj/xcshareddata/xcschemes/openscad_nogui.xcscheme @@ -58,6 +58,16 @@ ReferencedContainer = "container:OpenSCAD.xcodeproj"> + + + + + + From 08fd03329313fdea9c67c7e047aff9d488e4d27f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 17:55:42 -0500 Subject: [PATCH 019/174] Be conservative and don't apply the CGAL hull fix to unknown versions without testing --- src/cgalutils.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index c320c2de..01d87dd5 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -16,8 +16,8 @@ #include #include -// Apply CGAL bugfix. Note: If using CGAL < 4.3, hull() might be buggy -#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,3,0) +// Apply CGAL bugfix for CGAL-4.5.x +#if CGAL_VERSION_NR > CGAL_VERSION_NUMBER(4,5,1) || CGAL_VERSION_NR < CGAL_VERSION_NUMBER(4,5,0) #include #else #include "convex_hull_3_bugfix.h" From 7b2d01ff515e37bc01f26e3e6c01e1ca0f62cdd1 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 7 Jan 2015 00:50:58 +0100 Subject: [PATCH 020/174] Use double backslashes to quote fontconfig input. --- src/FontListDialog.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/FontListDialog.cc b/src/FontListDialog.cc index 474c2ef3..90b46cba 100644 --- a/src/FontListDialog.cc +++ b/src/FontListDialog.cc @@ -136,11 +136,11 @@ void FontListDialog::update_font_list() QString FontListDialog::quote(const QString& text) { QString result = text; - result.replace('\\', "\\\\") - .replace('-', "\\-") - .replace(':', "\\:") - .replace(',', "\\,") - .replace('=', "\\=") - .replace('_', "\\_"); + result.replace('\\', "\\\\\\\\") + .replace('-', "\\\\-") + .replace(':', "\\\\:") + .replace(',', "\\\\,") + .replace('=', "\\\\=") + .replace('_', "\\\\_"); return result; } From dda527dabd0b4dbeba82b277900d076d2c7b1224 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 7 Jan 2015 03:14:46 +0100 Subject: [PATCH 021/174] Show error/warning status in viewport. --- icons/close.png | Bin 0 -> 20477 bytes icons/information-icons-error.png | Bin 0 -> 52554 bytes icons/information-icons-info.png | Bin 0 -> 59057 bytes icons/information-icons-question.png | Bin 0 -> 53132 bytes icons/information-icons-warning.png | Bin 0 -> 43352 bytes icons/license.txt | 11 +++ openscad.qrc | 5 + src/MainWindow.h | 6 ++ src/MainWindow.ui | 138 +++++++++++++++++---------- src/mainwin.cc | 47 ++++++++- src/parser.y | 2 +- 11 files changed, 156 insertions(+), 53 deletions(-) create mode 100644 icons/close.png create mode 100644 icons/information-icons-error.png create mode 100644 icons/information-icons-info.png create mode 100644 icons/information-icons-question.png create mode 100644 icons/information-icons-warning.png diff --git a/icons/close.png b/icons/close.png new file mode 100644 index 0000000000000000000000000000000000000000..9782e419d51c3bb6a59e105888d5953e96489b93 GIT binary patch literal 20477 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 V)wM7}W&l_BfvhdgnbWX%(tqaC(V_qV literal 0 HcmV?d00001 diff --git a/icons/information-icons-error.png b/icons/information-icons-error.png new file mode 100644 index 0000000000000000000000000000000000000000..1d963f91cb576a151aa9efba03429f676dbd6636 GIT binary patch literal 52554 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 literal 0 HcmV?d00001 diff --git a/icons/information-icons-question.png b/icons/information-icons-question.png new file mode 100644 index 0000000000000000000000000000000000000000..75bb0fe27c7fd20ad94e9fe699398c0c2b8d8b37 GIT binary patch literal 53132 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

1oXAf$t0S^~_28VLT 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 literal 0 HcmV?d00001 diff --git a/icons/information-icons-warning.png b/icons/information-icons-warning.png new file mode 100644 index 0000000000000000000000000000000000000000..6d439cbae5f72d98365ea109b5b6790491a884e1 GIT binary patch literal 43352 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 literal 0 HcmV?d00001 diff --git a/icons/license.txt b/icons/license.txt index 97e6931b..f73b0891 100644 --- a/icons/license.txt +++ b/icons/license.txt @@ -1,3 +1,14 @@ Taken from http://tango.freedesktop.org/Tango_Icon_Library, version 0.8.90 / public domain: - prefsFeatures.png (converted from preferences-system.svg) + +https://openclipart.org/detail/2281/information-icons-set-by-kuba / public domain: + +- information-icons-error.png +- information-icons-question.png +- information-icons-info.png +- information-icons-warning.png + +https://openclipart.org/detail/171382/cross-icon-by-zawertun-171382 / public domain: + +- close.png diff --git a/openscad.qrc b/openscad.qrc index f202c2d4..77327356 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -1,5 +1,10 @@ + icons/close.png + icons/information-icons-error.png + icons/information-icons-info.png + icons/information-icons-question.png + icons/information-icons-warning.png icons/openscad.png icons/button.png icons/background-welcome-screen.svg diff --git a/src/MainWindow.h b/src/MainWindow.h index 50d4bb6d..8b0c9109 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -78,6 +78,9 @@ public: QString editortype; bool useScintilla; + int compileErrors; + int compileWarnings; + MainWindow(const QString &filename); ~MainWindow(); @@ -103,6 +106,7 @@ private: void updateTemporalVariables(); bool fileChangedOnDisk(); void compileTopLevelDocument(); + void updateCompileResult(); void compile(bool reload, bool forcedone = false); void compileCSG(bool procevents); bool maybeSave(); @@ -149,6 +153,7 @@ private slots: void hideToolbars(); void hideEditor(); void hideConsole(); + void showConsole(); private slots: void selectFindType(int); @@ -200,6 +205,7 @@ public slots: void actionReloadRenderPreview(); void on_editorDock_visibilityChanged(bool); void on_consoleDock_visibilityChanged(bool); + void on_pushButtonCompileResultClose_clicked(); void editorTopLevelChanged(bool); void consoleTopLevelChanged(bool); #ifdef ENABLE_OPENCSG diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 74365644..722961cc 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -15,16 +15,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -39,18 +30,89 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 + + + + QFrame::Box + + + QFrame::Raised + + + + 9 + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 26 + 26 + + + + + + + :/icons/information-icons-error.png + + + true + + + + + + + + 1 + 0 + + + + + 14 + 75 + true + + + + Message + + + + + + + + + + + :/icons/close.png:/icons/close.png + + + true + + + + + + @@ -82,16 +144,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -160,6 +213,7 @@ animate_panel qglview viewerToolBar + frameCompileResult @@ -170,7 +224,7 @@ 0 0 1397 - 22 + 33 @@ -324,16 +378,7 @@ 0 - - 0 - - - 0 - - - 0 - - + 0 @@ -453,16 +498,7 @@ - - 0 - - - 0 - - - 0 - - + 0 diff --git a/src/mainwin.cc b/src/mainwin.cc index 67bc93a8..2011a433 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -282,6 +282,9 @@ MainWindow::MainWindow(const QString &filename) animate_panel->hide(); find_panel->hide(); + frameCompileResult->hide(); + this->labelCompileResultMessage->setOpenExternalLinks(false); + connect(this->labelCompileResultMessage, SIGNAL(linkActivated(QString)), SLOT(showConsole())); // File menu connect(this->fileActionNew, SIGNAL(triggered()), this, SLOT(actionNew())); @@ -873,6 +876,9 @@ void MainWindow::compile(bool reload, bool forcedone) bool shouldcompiletoplevel = false; bool didcompile = false; + compileErrors = 0; + compileWarnings = 0; + this->renderingTime.start(); // Reload checks the timestamp of the toplevel file and refreshes if necessary, @@ -946,12 +952,43 @@ void MainWindow::waitAfterReload() } } +void MainWindow::on_pushButtonCompileResultClose_clicked() +{ + frameCompileResult->hide(); +} + +void MainWindow::updateCompileResult() +{ + if ((compileErrors == 0) && (compileWarnings == 0)) { + frameCompileResult->hide(); + return; + } + + QString msg; + if (compileErrors > 0) { + if (fileName.isEmpty()) { + msg = QString(_("Compile error.")); + } else { + QFileInfo fileInfo(fileName); + msg = QString(_("Error while compiling '%1'.")).arg(fileInfo.fileName()); + } + labelCompileResultIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/information-icons-error.png"))); + } else { + msg = QString(_("Compilation generated %1 warnings.")).arg(compileWarnings); + labelCompileResultIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/information-icons-warning.png"))); + } + msg += _(" For details see console window."); + labelCompileResultMessage->setText(msg); + frameCompileResult->show(); +} + void MainWindow::compileDone(bool didchange) { const char *callslot; if (didchange) { instantiateRoot(); updateCamera(); + updateCompileResult(); callslot = afterCompileSlot; } else { @@ -2399,8 +2436,14 @@ void MainWindow::hideEditor() } } -void MainWindow::hideConsole() +void MainWindow::showConsole() +{ + viewActionHideConsole->setChecked(false); + consoleDock->show(); + frameCompileResult->hide(); +} +void MainWindow::hideConsole() { if (viewActionHideConsole->isChecked()) { consoleDock->hide(); @@ -2572,8 +2615,10 @@ void MainWindow::consoleOutput(const std::string &msg, void *userdata) MainWindow *thisp = static_cast(userdata); QString qmsg = QString::fromUtf8(msg.c_str()); if (qmsg.startsWith("WARNING:")) { + thisp->compileWarnings++; qmsg = "" + qmsg + ""; } else if (qmsg.startsWith("ERROR:")) { + thisp->compileErrors++; qmsg = "" + qmsg + ""; } QMetaObject::invokeMethod(thisp->console, "append", Qt::QueuedConnection, Q_ARG(QString, qmsg)); diff --git a/src/parser.y b/src/parser.y index 73c07504..1600e7c9 100644 --- a/src/parser.y +++ b/src/parser.y @@ -560,7 +560,7 @@ int parserlex(void) void yyerror (char const *s) { // FIXME: We leak memory on parser errors... - PRINTB("Parser error in line %d: %s\n", lexerget_lineno() % s); + PRINTB("ERROR: Parser error in line %d: %s\n", lexerget_lineno() % s); } FileModule *parse(const char *text, const char *path, int debug) From 2eda0b60a0798ad78414b79214ea88a7fa6ae956 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 22:50:07 -0500 Subject: [PATCH 022/174] cosmetics --- src/openscad.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openscad.cc b/src/openscad.cc index ab7e3acf..f2232934 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -461,7 +461,8 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c if (renderer == Render::CGAL && root_geom->getDimension() == 3) { const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get()); if (!N) { - root_geom.reset(CGALUtils::createNefPolyhedronFromGeometry(*root_geom)); + N = CGALUtils::createNefPolyhedronFromGeometry(*root_geom); + root_geom.reset(N); PRINT("Converted to Nef polyhedron"); } } From 5537e822747d90e925509d00a0e812d275d77e0c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 22:50:40 -0500 Subject: [PATCH 023/174] Added printPolyhedron --- src/cgalutils-polyhedron.cc | 57 +++++++++++++++++++++++++++++++++++++ src/cgalutils.h | 1 + 2 files changed, 58 insertions(+) diff --git a/src/cgalutils-polyhedron.cc b/src/cgalutils-polyhedron.cc index 59a2ec71..c821f541 100644 --- a/src/cgalutils-polyhedron.cc +++ b/src/cgalutils-polyhedron.cc @@ -296,6 +296,63 @@ namespace CGALUtils { template bool createPolySetFromPolyhedron(const CGAL::Polyhedron_3 &p, PolySet &ps); template bool createPolySetFromPolyhedron(const CGAL::Polyhedron_3 > &p, PolySet &ps); + class Polyhedron_writer { + std::ostream *out; + bool firstv; + std::vector indices; + public: + Polyhedron_writer() {} + void write_header(std::ostream &stream, + std::size_t vertices, + std::size_t halfedges, + std::size_t facets, + bool normals = false) { + this->out = &stream; + *out << "polyhedron(points=["; + firstv = true; + } + void write_footer() { + *out << "]);" << std::endl; + } + void write_vertex( const double& x, const double& y, const double& z) { + *out << (firstv ? "" : ",") << '[' << x << ',' << y << ',' << z << ']'; + firstv = false; + } + void write_facet_header() { + *out << "], faces=["; + firstv = true; + } + void write_facet_begin( std::size_t no) { + *out << (firstv ? "" : ",") << '['; + indices.clear(); + firstv = false; + } + void write_facet_vertex_index( std::size_t index) { + indices.push_back(index); + } + void write_facet_end() { + bool firsti = true; + BOOST_REVERSE_FOREACH(int i, indices) { + *out << (firsti ? "" : ",") << i; + firsti = false; + } + *out << ']'; + } + }; + + template + std::string printPolyhedron(const Polyhedron &p) { + std::stringstream sstream; + sstream.precision(20); + + Polyhedron_writer writer; + generic_print_polyhedron(sstream, p, writer); + + return sstream.str(); + } + + template std::string printPolyhedron(const CGAL_Polyhedron &p); + }; // namespace CGALUtils #endif /* ENABLE_CGAL */ diff --git a/src/cgalutils.h b/src/cgalutils.h index c8eb69db..92c909dd 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -21,6 +21,7 @@ namespace CGALUtils { bool is_approximately_convex(const PolySet &ps); Geometry const* applyMinkowski(const Geometry::ChildList &children); + template std::string printPolyhedron(const Polyhedron &p); template bool createPolySetFromPolyhedron(const Polyhedron &p, PolySet &ps); template bool createPolyhedronFromPolySet(const PolySet &ps, Polyhedron &p); template From 1941a7fc0d4099f90cdf339d6d7dfcc642842c98 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 6 Jan 2015 22:51:44 -0500 Subject: [PATCH 024/174] #1105 Workaround for CGAL problem: Don't trust normal vectors from Nef polyhedrons, normalize calculated normal vectors --- src/cgalutils-tess.cc | 2 ++ src/cgalutils.cc | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cgalutils-tess.cc b/src/cgalutils-tess.cc index e230e9db..7a8b80f0 100644 --- a/src/cgalutils-tess.cc +++ b/src/cgalutils-tess.cc @@ -107,6 +107,8 @@ namespace CGALUtils { else { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygons.front().begin(), polygons.front().end(), normalvec); + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); } // Pass the normal vector to the (undocumented) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 5d951936..7003eb3e 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -917,10 +917,13 @@ namespace CGALUtils { and let the tessellater deal with the holes, and then just output the resulting 3d triangles*/ - CGAL::Vector_3 nvec = plane.orthogonal_vector(); - K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); std::vector triangles; - bool err = CGALUtils::tessellatePolygonWithHoles(polyholes, triangles, &normal); + bool err = CGALUtils::tessellatePolygonWithHoles(polyholes, triangles, NULL); if (!err) { BOOST_FOREACH(const Polygon &p, triangles) { if (p.size() != 3) { From cfc879cd1c802e5630e9a5888565857913f684d4 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 00:34:33 -0500 Subject: [PATCH 025/174] Mac compile fix --- tests/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2570c77c..0173b029 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -264,7 +264,9 @@ if (EIGEN_DIR) endif() if (NOT EIGEN_INCLUDE_DIR) - find_path(EIGEN_INCLUDE_DIR Eigen/Core HINTS ${OPENSCAD_LIBDIR}/include/eigen3) + # The NO_CMAKE_SYSTEM_PATH is necessary to avoid OS X from picking up + # a stray Eigen from /Library/Framework + find_path(EIGEN_INCLUDE_DIR Eigen/Core HINTS ${OPENSCAD_LIBDIR}/include/eigen3 NO_CMAKE_SYSTEM_PATH) endif() if (NOT EIGEN_INCLUDE_DIR) From 55b5d26965928d735988efdea843125559e3c2d8 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 01:02:29 -0500 Subject: [PATCH 026/174] Bugfix: Integer norm is only available in Eigen 3.2.3 -> --- src/grid.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/grid.h b/src/grid.h index b0164c34..10dde9d8 100644 --- a/src/grid.h +++ b/src/grid.h @@ -120,14 +120,14 @@ public: createGridVertex(v, key); typename GridContainer::iterator iter = db.find(key); if (iter == db.end()) { - int dist = 10; // > max possible distance + float dist = 10.0f; // > max possible distance for (int64_t jx = key[0] - 1; jx <= key[0] + 1; jx++) { for (int64_t jy = key[1] - 1; jy <= key[1] + 1; jy++) { for (int64_t jz = key[2] - 1; jz <= key[2] + 1; jz++) { Vector3l k(jx, jy, jz); typename GridContainer::iterator tmpiter = db.find(k); if (tmpiter == db.end()) continue; - int d = (key-k).norm(); + float d = sqrt((key-k).squaredNorm()); if (d < dist) { dist = d; iter = tmpiter; From 8c53981cfa97dc0b877de10247cc7beb2ce035c8 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 02:06:25 -0500 Subject: [PATCH 027/174] Killed compiler warnings --- src/cgalutils.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 5d951936..5b60bb77 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -56,9 +56,9 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps) // NB! CGAL's convex_hull_3() doesn't like std::set iterators, so we use a list // instead. std::list points; - for (int i = 0; i < ps.polygons.size(); i++) { - for (int j = 0; j < ps.polygons[i].size(); j++) { - points.push_back(vector_convert(ps.polygons[i][j])); + BOOST_FOREACH(const Polygon &poly, ps.polygons) { + BOOST_FOREACH(const Vector3d &p, poly) { + points.push_back(vector_convert(p)); } } @@ -270,8 +270,8 @@ namespace CGALUtils { std::vector points[2]; std::vector minkowski_points; - for (int i = 0; i < P[0].size(); i++) { - for (int j = 0; j < P[1].size(); j++) { + for (size_t i = 0; i < P[0].size(); i++) { + for (size_t j = 0; j < P[1].size(); j++) { t.start(); points[0].clear(); points[1].clear(); From 0bd0129f8f22ed71d87c910faf3c7fea46ef0181 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 02:09:37 -0500 Subject: [PATCH 028/174] bugfix: Apparently execution order wasn't deterministic, caused bugs on older gcc's --- src/grid.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/grid.h b/src/grid.h index 10dde9d8..e3db9a43 100644 --- a/src/grid.h +++ b/src/grid.h @@ -137,7 +137,8 @@ public: } } if (iter == db.end()) { // Not found: insert using key - T &data = db[key] = db.size(); + T data = db.size(); + db[key] = data; return data; } From da657d75435d1880023503bd74e638577844c433 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 7 Jan 2015 17:05:31 +0100 Subject: [PATCH 029/174] Treat deprecation as warning message (fixes #1143). --- src/control.cc | 2 +- src/import.cc | 4 ++-- src/linearextrude.cc | 2 +- src/mainwin.cc | 2 +- src/openscad.cc | 4 ++-- src/primitives.cc | 2 +- src/printutils.cc | 3 ++- src/rotateextrude.cc | 2 +- src/value.cc | 2 +- 9 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/control.cc b/src/control.cc index bcbae4a5..21a2fe4b 100644 --- a/src/control.cc +++ b/src/control.cc @@ -169,7 +169,7 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns switch (this->type) { case CHILD: { - printDeprecation("DEPRECATED: child() will be removed in future releases. Use children() instead."); + printDeprecation("child() will be removed in future releases. Use children() instead."); int n = 0; if (evalctx->numArgs() > 0) { double v; diff --git a/src/import.cc b/src/import.cc index ddc4a950..1f1686d2 100644 --- a/src/import.cc +++ b/src/import.cc @@ -95,7 +95,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti if (v->isUndefined()) { v = c.lookup_variable("filename"); if (!v->isUndefined()) { - printDeprecation("DEPRECATED: filename= is deprecated. Please use file="); + printDeprecation("filename= is deprecated. Please use file="); } } std::string filename = lookup_file(v->isUndefined() ? "" : v->toString(), inst->path(), ctx->documentPath()); @@ -119,7 +119,7 @@ AbstractNode *ImportModule::instantiate(const Context *ctx, const ModuleInstanti if (layerval.isUndefined()) { layerval = *c.lookup_variable("layername"); if (!layerval.isUndefined()) { - printDeprecation("DEPRECATED: layername= is deprecated. Please use layer="); + printDeprecation("layername= is deprecated. Please use layer="); } } node->layername = layerval.isUndefined() ? "" : layerval.toString(); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index e535c28d..cddbc314 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -75,7 +75,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI ValuePtr slices = c.lookup_variable("slices", true); if (!file->isUndefined() && file->type() == Value::STRING) { - printDeprecation("DEPRECATED: Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); + printDeprecation("Support for reading files in linear_extrude will be removed in future releases. Use a child import() instead."); node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 2011a433..e19ebaee 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -2614,7 +2614,7 @@ void MainWindow::consoleOutput(const std::string &msg, void *userdata) // originates in a worker thread. MainWindow *thisp = static_cast(userdata); QString qmsg = QString::fromUtf8(msg.c_str()); - if (qmsg.startsWith("WARNING:")) { + if (qmsg.startsWith("WARNING:") || qmsg.startsWith("DEPRECATED:")) { thisp->compileWarnings++; qmsg = "" + qmsg + ""; } else if (qmsg.startsWith("ERROR:")) { diff --git a/src/openscad.cc b/src/openscad.cc index ab7e3acf..9f28ea9e 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -830,12 +830,12 @@ int main(int argc, char **argv) output_file = vm["o"].as().c_str(); } if (vm.count("s")) { - printDeprecation("DEPRECATED: The -s option is deprecated. Use -o instead.\n"); + printDeprecation("The -s option is deprecated. Use -o instead.\n"); if (output_file) help(argv[0], true); output_file = vm["s"].as().c_str(); } if (vm.count("x")) { - printDeprecation("DEPRECATED: The -x option is deprecated. Use -o instead.\n"); + printDeprecation("The -x option is deprecated. Use -o instead.\n"); if (output_file) help(argv[0], true); output_file = vm["x"].as().c_str(); } diff --git a/src/primitives.cc b/src/primitives.cc index 5381db8c..0727c7aa 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -245,7 +245,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta // backwards compatible node->faces = c.lookup_variable("triangles", true); if (node->faces->type() != Value::UNDEFINED) { - printDeprecation("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); + printDeprecation("polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); } } break; diff --git a/src/printutils.cc b/src/printutils.cc index 4e400ccb..7098fd1a 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -114,8 +114,9 @@ std::set printedDeprecations; void printDeprecation(const std::string &str) { if (printedDeprecations.find(str) == printedDeprecations.end()) { - PRINT(str); printedDeprecations.insert(str); + std::string msg = "DEPRECATED: " + str; + PRINT(msg); } } diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 700fb7c9..48b029a6 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -69,7 +69,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI ValuePtr scale = c.lookup_variable("scale", true); if (!file->isUndefined()) { - printDeprecation("DEPRECATED: Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); + printDeprecation("Support for reading files in rotate_extrude will be removed in future releases. Use a child import() instead."); node->filename = lookup_file(file->toString(), inst->path(), c.documentPath()); } diff --git a/src/value.cc b/src/value.cc index 4723b611..f519948c 100644 --- a/src/value.cc +++ b/src/value.cc @@ -707,7 +707,7 @@ Value Value::operator[](const Value &v) const void Value::RangeType::normalize() { if ((step_val>0) && (end_val < begin_val)) { std::swap(begin_val,end_val); - printDeprecation("DEPRECATED: Using ranges of the form [begin:end] with begin value greater than the end value is deprecated."); + printDeprecation("Using ranges of the form [begin:end] with begin value greater than the end value is deprecated."); } } From c915ecfde036ae1677bb2830b5fa071454a1d5fc Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 7 Jan 2015 17:25:15 +0100 Subject: [PATCH 030/174] Change license for example files. --- examples/Advanced/offset.scad | 16 +++- examples/Basics/logo_and_text.scad | 16 +++- examples/Basics/text_on_cube.scad | 16 +++- examples/COPYING-CC0.txt | 121 +++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 examples/COPYING-CC0.txt diff --git a/examples/Advanced/offset.scad b/examples/Advanced/offset.scad index 18cc2e4b..9476ca16 100644 --- a/examples/Advanced/offset.scad +++ b/examples/Advanced/offset.scad @@ -1,6 +1,16 @@ -// Example for offset() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// offset.scad - Example for offset() usage in OpenSCAD +// +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . +// $fn = 40; diff --git a/examples/Basics/logo_and_text.scad b/examples/Basics/logo_and_text.scad index 140ff248..9dbc3d2a 100644 --- a/examples/Basics/logo_and_text.scad +++ b/examples/Basics/logo_and_text.scad @@ -1,6 +1,16 @@ -// Example for text() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// logo_and_text.scad - Example for text() usage in OpenSCAD +// +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . +// echo(version=version()); diff --git a/examples/Basics/text_on_cube.scad b/examples/Basics/text_on_cube.scad index 046be735..ad592bea 100644 --- a/examples/Basics/text_on_cube.scad +++ b/examples/Basics/text_on_cube.scad @@ -1,6 +1,16 @@ -// Example for text() usage -// (c) 2014 Torsten Paul -// CC-BY-SA 4.0 +// text_on_cube.scad - Example for text() usage in OpenSCAD +// +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . +// echo(version=version()); diff --git a/examples/COPYING-CC0.txt b/examples/COPYING-CC0.txt new file mode 100644 index 00000000..0e259d42 --- /dev/null +++ b/examples/COPYING-CC0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. From 4538134990d6962311ceb839ef27544c88b9d046 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 13:20:02 -0500 Subject: [PATCH 031/174] #1105 Yet another testcase --- testdata/scad/bugs/issue1105c.scad | 14 ++++++++++++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1105c-expected.png | Bin 0 -> 7956 bytes .../monotonepngtest/issue1105c-expected.png | Bin 0 -> 7956 bytes .../opencsgtest/issue1105c-expected.png | Bin 0 -> 8109 bytes 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue1105c.scad create mode 100644 tests/regression/cgalpngtest/issue1105c-expected.png create mode 100644 tests/regression/monotonepngtest/issue1105c-expected.png create mode 100644 tests/regression/opencsgtest/issue1105c-expected.png diff --git a/testdata/scad/bugs/issue1105c.scad b/testdata/scad/bugs/issue1105c.scad new file mode 100644 index 00000000..527ee895 --- /dev/null +++ b/testdata/scad/bugs/issue1105c.scad @@ -0,0 +1,14 @@ +translate([59.5, -40, 2]) rotate(90) translate([2,31.5,26]) + cube(size = [4, 23, 4], center = false); + +translate([5,-35,2]) { + difference() { + rotate(90) { + translate([-3,-3,1]) cube(size = [3, 6, 30]); + rotate_extrude($fn = 14) { + polygon(points = [[0, 18], [0, 30], [7, 26]]); + } + } + cylinder(h = 30, r = 1); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0173b029..19bdaaff 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1220,7 +1220,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1105c-expected.png b/tests/regression/cgalpngtest/issue1105c-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1321cdc55a77d9b163c13b3882dffb7706fa35 GIT binary patch literal 7956 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 E0z%t6=l}o! literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue1105c-expected.png b/tests/regression/monotonepngtest/issue1105c-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..9c1321cdc55a77d9b163c13b3882dffb7706fa35 GIT binary patch literal 7956 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 E0z%t6=l}o! literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue1105c-expected.png b/tests/regression/opencsgtest/issue1105c-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..521cb7a4e82ffe35aead4985c553c6fb6f23887b GIT binary patch literal 8109 zcmeHMXH-*Zw>~EcRfM1@ATmZQpb=pxA`0e!y-*Yd4E1xQi5LV?dV;892NVHCNmK*` z131!Kz!9+kVL$?cAxM!DAxI0Po%?djpZnvkd)NKyTJtMs?X}N)_WSI;pIvgz(SGk@ zxc|zsu%mI6TH>C2a0Et`NLkYtv5LRXtlr zLhtgls~C8hhQ@NaJ7I<^F6}!YyR5kSfO2xm#p{@LOH3AD@VWNEmay�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 literal 0 HcmV?d00001 From 156d7ccefb0d02a2f812df93a5f548795f4b7f41 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 7 Jan 2015 19:35:41 +0100 Subject: [PATCH 032/174] Clarify license for basic examples. --- examples/Advanced/offset.scad | 25 +++++++++++++------------ examples/Basics/difference_cube.scad | 15 +++++++++++++++ examples/Basics/difference_sphere.scad | 15 +++++++++++++++ examples/Basics/intersection.scad | 15 +++++++++++++++ examples/Basics/logo_and_text.scad | 24 ++++++++++++------------ examples/Basics/surface.scad | 16 ++++++++++++++++ examples/Basics/text_on_cube.scad | 25 +++++++++++++------------ examples/Basics/translate.scad | 16 ++++++++++++++++ examples/Basics/union.scad | 15 +++++++++++++++ 9 files changed, 130 insertions(+), 36 deletions(-) diff --git a/examples/Advanced/offset.scad b/examples/Advanced/offset.scad index 9476ca16..5f1ebdfa 100644 --- a/examples/Advanced/offset.scad +++ b/examples/Advanced/offset.scad @@ -1,16 +1,4 @@ // offset.scad - Example for offset() usage in OpenSCAD -// -// Written in 2014 by Torsten Paul -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any -// warranty. -// -// You should have received a copy of the CC0 Public Domain -// Dedication along with this software. -// If not, see . -// $fn = 40; @@ -41,3 +29,16 @@ translate([0, 0, foot_height]) { %cylinder(r = 14, h = 100); %translate([0, 0, 100]) sphere(r = 30); + + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/difference_cube.scad b/examples/Basics/difference_cube.scad index c8127844..c4b210ec 100644 --- a/examples/Basics/difference_cube.scad +++ b/examples/Basics/difference_cube.scad @@ -1,3 +1,5 @@ +// difference_cube.scad - Example for difference() usage in OpenSCAD + echo(version=version()); module difference_cube() @@ -10,3 +12,16 @@ module difference_cube() difference_cube(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/difference_sphere.scad b/examples/Basics/difference_sphere.scad index 3d80d626..67d6dee9 100644 --- a/examples/Basics/difference_sphere.scad +++ b/examples/Basics/difference_sphere.scad @@ -1,3 +1,5 @@ +// difference_sphere.scad - Example for difference() usage in OpenSCAD + echo(version=version()); module difference_sphere() @@ -25,3 +27,16 @@ module difference_sphere() difference_sphere(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/intersection.scad b/examples/Basics/intersection.scad index 082b72e7..ac2046bb 100644 --- a/examples/Basics/intersection.scad +++ b/examples/Basics/intersection.scad @@ -1,3 +1,5 @@ +// intersection.scad - Example for intersection() usage in OpenSCAD + echo(version=version()); module example_intersection() @@ -22,3 +24,16 @@ module example_intersection() example_intersection(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/logo_and_text.scad b/examples/Basics/logo_and_text.scad index 9dbc3d2a..bddaa336 100644 --- a/examples/Basics/logo_and_text.scad +++ b/examples/Basics/logo_and_text.scad @@ -1,16 +1,4 @@ // logo_and_text.scad - Example for text() usage in OpenSCAD -// -// Written in 2014 by Torsten Paul -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any -// warranty. -// -// You should have received a copy of the CC0 Public Domain -// Dedication along with this software. -// If not, see . -// echo(version=version()); @@ -56,3 +44,15 @@ translate([110, 0, 80]) { translate([160, 0, -40]) black() t("Solid 3D CAD Modeller"); } + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/surface.scad b/examples/Basics/surface.scad index dbf93485..e49605e2 100644 --- a/examples/Basics/surface.scad +++ b/examples/Basics/surface.scad @@ -1,3 +1,5 @@ +// surface.scad - Example for surface() usage in OpenSCAD +// // surface.dat generated using octave: // d = (sin(1:0.2:10)' * cos(1:0.2:10)) * 10; // save("surface.dat", "d"); @@ -13,3 +15,17 @@ intersection() surface(file = "surface.dat", center = true, convexity = 5); } + + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/text_on_cube.scad b/examples/Basics/text_on_cube.scad index ad592bea..35647cf1 100644 --- a/examples/Basics/text_on_cube.scad +++ b/examples/Basics/text_on_cube.scad @@ -1,16 +1,4 @@ // text_on_cube.scad - Example for text() usage in OpenSCAD -// -// Written in 2014 by Torsten Paul -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any -// warranty. -// -// You should have received a copy of the CC0 Public Domain -// Dedication along with this software. -// If not, see . -// echo(version=version()); @@ -48,3 +36,16 @@ difference() { translate([0, 0, o]) letter("\u263A"); translate([0, 0, -o - letter_height]) letter("\u263C"); } + + + +// Written in 2014 by Torsten Paul +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/translate.scad b/examples/Basics/translate.scad index 1aaa674c..a7c8fe9e 100644 --- a/examples/Basics/translate.scad +++ b/examples/Basics/translate.scad @@ -1,3 +1,5 @@ +// translate.scad - Example for translate() usage in OpenSCAD + echo(version=version()); module example_translate() @@ -19,3 +21,17 @@ module example_translate() } example_translate(); + + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/union.scad b/examples/Basics/union.scad index 1b410e2c..681c5823 100644 --- a/examples/Basics/union.scad +++ b/examples/Basics/union.scad @@ -1,3 +1,5 @@ +// union.scad - Example for union() usage in OpenSCAD + echo(version=version()); module example_union() @@ -19,3 +21,16 @@ module example_union() example_union(); + + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . From b519718b6482384cf8f00f0f121c3bbcc63a154b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 13:50:14 -0500 Subject: [PATCH 033/174] Another crash example --- cgal/data/issue1105c.polygon | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 cgal/data/issue1105c.polygon diff --git a/cgal/data/issue1105c.polygon b/cgal/data/issue1105c.polygon new file mode 100644 index 00000000..7deb4626 --- /dev/null +++ b/cgal/data/issue1105c.polygon @@ -0,0 +1,8 @@ +11.8244953852727654464160877978,-33.4423534623057960857295256574,28 +11.8244953852727654464160877978,-34,28 +11.8244953852727654464160877978,-36.5576465376941897034157591406,28 +7.99999999999999911182158029987,-35.6847304231704427479598962236,23.516743531220182461538570351 +8,-35,23.516743531220182461538570351 +5.99999999999999911182158029987,-35,21.1722478437400596362749638502 +6,-35,21.1722478437400596362749638502 +5.8577590289166048265201425238,-34.8042220990505484223831444979,21.0055061720960587479112291476 From 6a398121602bd52c6dd92c1d37677dab25e41231 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 14:10:31 -0500 Subject: [PATCH 034/174] Stand-alone program for exporting a Nef polyhedron to STL --- cgal/export_nef.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++ cgal/export_nef.pro | 109 +++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 cgal/export_nef.cpp create mode 100644 cgal/export_nef.pro diff --git a/cgal/export_nef.cpp b/cgal/export_nef.cpp new file mode 100644 index 00000000..2048a3f4 --- /dev/null +++ b/cgal/export_nef.cpp @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include + +#include "cgalutils.h" +#include "export.h" +#include "polyset.h" +#include "CGAL_Nef_polyhedron.h" +#include "boosty.h" + +#include + +using namespace CGALUtils; + +#define STL_FACET_NUMBYTES 4*3*4+2 +// as there is no 'float32_t' standard, we assume the systems 'float' +// is a 'binary32' aka 'single' standard IEEE 32-bit floating point type +union stl_facet { + uint8_t data8[ STL_FACET_NUMBYTES ]; + uint32_t data32[4*3]; + struct facet_data { + float i, j, k; + float x1, y1, z1; + float x2, y2, z2; + float x3, y3, z3; + uint16_t attribute_byte_count; + } data; +}; + +void uint32_byte_swap( uint32_t &x ) +{ +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 + x = __builtin_bswap32( x ); +#elif defined(__clang__) + x = __builtin_bswap32( x ); +#elif defined(_MSC_VER) + x = _byteswap_ulong( x ); +#else + uint32_t b1 = ( 0x000000FF & x ) << 24; + uint32_t b2 = ( 0x0000FF00 & x ) << 8; + uint32_t b3 = ( 0x00FF0000 & x ) >> 8; + uint32_t b4 = ( 0xFF000000 & x ) >> 24; + x = b1 | b2 | b3 | b4; +#endif +} + +void read_stl_facet( std::ifstream &f, stl_facet &facet ) +{ + f.read( (char*)facet.data8, STL_FACET_NUMBYTES ); +#ifdef BOOST_BIG_ENDIAN + for ( int i = 0; i < 12; i++ ) { + uint32_byte_swap( facet.data32[ i ] ); + } + // we ignore attribute byte count +#endif +} + +PolySet *import_stl(const std::string &filename) +{ + PolySet *p = new PolySet(3); + + // Open file and position at the end + std::ifstream f(filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + if (!f.good()) { + PRINTB("WARNING: Can't open import file '%s'.", filename); + return NULL; + } + + boost::regex ex_sfe("solid|facet|endloop"); + boost::regex ex_outer("outer loop"); + boost::regex ex_vertex("vertex"); + boost::regex ex_vertices("\\s*vertex\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)"); + + bool binary = false; + std::streampos file_size = f.tellg(); + f.seekg(80); + if (f.good() && !f.eof()) { + uint32_t facenum = 0; + f.read((char *)&facenum, sizeof(uint32_t)); +#ifdef BOOST_BIG_ENDIAN + uint32_byte_swap( facenum ); +#endif + if (file_size == static_cast(80 + 4 + 50*facenum)) { + binary = true; + } + } + f.seekg(0); + + char data[5]; + f.read(data, 5); + if (!binary && !f.eof() && f.good() && !memcmp(data, "solid", 5)) { + int i = 0; + double vdata[3][3]; + std::string line; + std::getline(f, line); + while (!f.eof()) { + std::getline(f, line); + boost::trim(line); + if (boost::regex_search(line, ex_sfe)) { + continue; + } + if (boost::regex_search(line, ex_outer)) { + i = 0; + continue; + } + boost::smatch results; + if (boost::regex_search(line, results, ex_vertices)) { + try { + for (int v=0;v<3;v++) { + vdata[i][v] = boost::lexical_cast(results[v+1]); + } + } + catch (const boost::bad_lexical_cast &blc) { + PRINTB("WARNING: Can't parse vertex line '%s'.", line); + i = 10; + continue; + } + if (++i == 3) { + p->append_poly(); + p->append_vertex(vdata[0][0], vdata[0][1], vdata[0][2]); + p->append_vertex(vdata[1][0], vdata[1][1], vdata[1][2]); + p->append_vertex(vdata[2][0], vdata[2][1], vdata[2][2]); + } + } + } + } + else if (binary && !f.eof() && f.good()) + { + f.ignore(80-5+4); + while (1) { + stl_facet facet; + read_stl_facet( f, facet ); + if (f.eof()) break; + p->append_poly(); + p->append_vertex(facet.data.x1, facet.data.y1, facet.data.z1); + p->append_vertex(facet.data.x2, facet.data.y2, facet.data.z2); + p->append_vertex(facet.data.x3, facet.data.y3, facet.data.z3); + } + } + return p; +} + +int main(int argc, char *argv[]) +{ + + OpenSCAD::debug = "export_nef"; + CGAL_Nef_polyhedron *N = NULL; + + PolySet *ps = NULL; + if (argc == 2) { + std::string filename(argv[1]); + std::string suffix = boosty::extension_str(filename); + boost::algorithm::to_lower(suffix); + if (suffix == ".stl") { + if (!(ps = import_stl(filename))) { + std::cerr << "Error importing STL " << argv[1] << std::endl; + exit(1); + } + std::cerr << "Imported " << ps->numPolygons() << " polygons" << std::endl; + } + else if (suffix == ".nef3") { + N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3); + std::ifstream stream(filename.c_str()); + stream >> *N->p3; + } + } + else { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + exit(1); + } + + if (ps && !N) N = createNefPolyhedronFromGeometry(*ps); + + export_stl(N, std::cout); + std::cerr << "Done." << std::endl; +} diff --git a/cgal/export_nef.pro b/cgal/export_nef.pro new file mode 100644 index 00000000..6f6becbb --- /dev/null +++ b/cgal/export_nef.pro @@ -0,0 +1,109 @@ +CONFIG += debug +CONFIG -= qt +debug: DEFINES += DEBUG + +TEMPLATE = app + +INCLUDEPATH += ../src +DEPENDPATH += ../src + +# Handle custom library location. +# Used when manually installing 3rd party libraries +isEmpty(OPENSCAD_LIBDIR) OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES) +macx:isEmpty(OPENSCAD_LIBDIR) { + exists(/opt/local):exists(/usr/local/Cellar) { + error("It seems you might have libraries in both /opt/local and /usr/local. Please specify which one to use with qmake OPENSCAD_LIBDIR=") + } else { + exists(/opt/local) { + #Default to MacPorts on Mac OS X + message("Automatically searching for libraries in /opt/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /opt/local + } else:exists(/usr/local/Cellar) { + message("Automatically searching for libraries in /usr/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /usr/local + } + } +} +!isEmpty(OPENSCAD_LIBDIR) { + QMAKE_INCDIR = $$OPENSCAD_LIBDIR/include + QMAKE_LIBDIR = $$OPENSCAD_LIBDIR/lib +} + +TARGET = export_nef +mac { + CONFIG -= app_bundle +} + +macx { + # Mac needs special care to link against the correct C++ library + # We attempt to auto-detect it by inspecting Boost + dirs = $${BOOSTDIR} $${QMAKE_LIBDIR} + for(dir, dirs) { + system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) { + message("Detected libc++-linked boost in $${dir}") + CONFIG += libc++ + } + } + + libc++ { + QMAKE_CXXFLAGS += -stdlib=libc++ + QMAKE_LFLAGS += -stdlib=libc++ + QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++ + # libc++ on requires Mac OS X 10.7+ + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 + } +} + +# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs. +*g++* { + QMAKE_CXXFLAGS *= -fno-strict-aliasing + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs # ignored before 4.8 +} + +*clang* { + # http://llvm.org/bugs/show_bug.cgi?id=9182 + QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + # disable enormous amount of warnings about CGAL / boost / etc + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function + QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions + # might want to actually turn this on once in a while + QMAKE_CXXFLAGS_WARN_ON += -Wno-sign-compare +} + +# Application configuration +CONFIG += cgal +CONFIG += boost +CONFIG += eigen +CONFIG += gettext + +mac: { + LIBS += -framework OpenGL +} + +include(../common.pri) + +HEADERS += ../src/cgal.h \ + ../src/cgalutils.h \ + ../src/linalg.h \ + ../src/polyset.h \ + ../src/polyset-utils.h \ + ../src/printutils.h + +SOURCES += export_nef.cpp \ + ../src/polygon2d.cc \ + ../src/polygon2d-CGAL.cc \ + ../src/CGAL_Nef_polyhedron.cc \ + ../src/CGAL_Nef_polyhedron_DxfData.cc \ + ../src/cgalutils.cc \ + ../src/cgalutils-tess.cc \ + ../src/cgalutils-polyhedron.cc \ + ../src/polyset.cc \ + ../src/svg.cc \ + ../src/node.cc \ + ../src/export.cc \ + ../src/polyset-utils.cc \ + ../src/progress.cc \ + ../src/printutils.cc \ + ../src/grid.cc From e44c103b72f28f710eb8168b465fcbb92cc94bb9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 23:55:38 -0500 Subject: [PATCH 035/174] Fixed merge error --- src/GLView.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GLView.cc b/src/GLView.cc index d021a36a..687db19f 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -506,7 +506,7 @@ void GLView::showCrosshairs() void GLView::showScalemarkers(const Color4f &col) { // Add scale tics on large axes - double l = cam.projection == Camera::PERSPECTIVE ? cam.viewer_distance : cam.height; + double l = cam.zoomValue(); glLineWidth(this->getDPI()); glColor3f(col[0], col[1], col[2]); From 6e0d94ec449d5d37a978e2cbe0aec14ece490883 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 7 Jan 2015 23:55:38 -0500 Subject: [PATCH 036/174] Fixed merge error --- src/GLView.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GLView.cc b/src/GLView.cc index d021a36a..687db19f 100644 --- a/src/GLView.cc +++ b/src/GLView.cc @@ -506,7 +506,7 @@ void GLView::showCrosshairs() void GLView::showScalemarkers(const Color4f &col) { // Add scale tics on large axes - double l = cam.projection == Camera::PERSPECTIVE ? cam.viewer_distance : cam.height; + double l = cam.zoomValue(); glLineWidth(this->getDPI()); glColor3f(col[0], col[1], col[2]); From 35d25f394c058af3a23cf1fe9474ece9db0e763f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 8 Jan 2015 00:16:45 -0500 Subject: [PATCH 037/174] Normalize calculated normal vector also for polygons without holes --- src/cgalutils-tess.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cgalutils-tess.cc b/src/cgalutils-tess.cc index 7a8b80f0..e0ed641b 100644 --- a/src/cgalutils-tess.cc +++ b/src/cgalutils-tess.cc @@ -164,6 +164,8 @@ namespace CGALUtils { else { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygon.begin(), polygon.end(), normalvec); + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); } // Pass the normal vector to the (undocumented) From e3441b50a10c522202c78c6d0584ecc0f4855e5f Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 8 Jan 2015 19:12:13 +0100 Subject: [PATCH 038/174] Move winconsole to separate folder. --- scripts/release-common.sh | 2 +- {src => winconsole}/winconsole.c | 0 winconsole.pro => winconsole/winconsole.pro | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) rename {src => winconsole}/winconsole.c (100%) rename winconsole.pro => winconsole/winconsole.pro (83%) diff --git a/scripts/release-common.sh b/scripts/release-common.sh index 2da42495..2c98a625 100755 --- a/scripts/release-common.sh +++ b/scripts/release-common.sh @@ -255,7 +255,7 @@ case $OS in exit fi # make console pipe-able openscad.com - see winconsole.pro for info - qmake ../winconsole.pro + qmake ../winconsole/winconsole.pro make if [ ! -e $TARGET/openscad.com ]; then echo "cant find $TARGET/openscad.com. build failed. stopping." diff --git a/src/winconsole.c b/winconsole/winconsole.c similarity index 100% rename from src/winconsole.c rename to winconsole/winconsole.c diff --git a/winconsole.pro b/winconsole/winconsole.pro similarity index 83% rename from winconsole.pro rename to winconsole/winconsole.pro index 11078f36..8b423a6a 100644 --- a/winconsole.pro +++ b/winconsole/winconsole.pro @@ -11,13 +11,13 @@ # properly TEMPLATE = app -TARGET = openscad_winconsole +TARGET = winconsole FORMS = HEADERS = FLEXSOURCES = BISONSOURCES = RESOURCES = -SOURCES = src/winconsole.c +SOURCES = winconsole.c CONFIG -= qt CONFIG += console # sets IMAGE_SUBSYSTEM_WINDOWS_CUI in binary -QMAKE_POST_LINK = cd $(DESTDIR) && mv openscad_winconsole.exe openscad.com +QMAKE_POST_LINK = cd $(DESTDIR) && mv winconsole.exe openscad.com From 10bee498e6c7f3623b8deb4bbee5c071d3646b99 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 8 Jan 2015 19:34:37 +0100 Subject: [PATCH 039/174] Fix duplicated output of DEPRECATED marker. --- src/fileutils.cc | 2 +- src/modcontext.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fileutils.cc b/src/fileutils.cc index ac3144ea..621bb600 100644 --- a/src/fileutils.cc +++ b/src/fileutils.cc @@ -22,7 +22,7 @@ std::string lookup_file(const std::string &filename, if (!fs::exists(absfile) && fs::exists(absfile_fallback)) { resultfile = absfile_fallback.string(); - PRINT_DEPRECATION("DEPRECATED: Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); + PRINT_DEPRECATION("Imported file (%s) found in document root instead of relative to the importing module. This behavior is deprecated", filename); } else { resultfile = absfile.string(); diff --git a/src/modcontext.cc b/src/modcontext.cc index 04d46e60..90f04700 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -116,7 +116,7 @@ const AbstractModule *ModuleContext::findLocalModule(const std::string &name) co } std::string replacement = Builtins::instance()->isDeprecated(name); if (!replacement.empty()) { - PRINT_DEPRECATION("DEPRECATED: The %s() module will be removed in future releases. Use %s instead.", name % replacement); + PRINT_DEPRECATION("The %s() module will be removed in future releases. Use %s instead.", name % replacement); } return m; } From 6e85c54fc48f8244f464b0147f8fce50db7efab9 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 8 Jan 2015 22:11:45 +0100 Subject: [PATCH 040/174] Validate size of search vector entries (fixes #1147). --- src/func.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/func.cc b/src/func.cc index 75597720..8fc10da2 100644 --- a/src/func.cc +++ b/src/func.cc @@ -712,7 +712,7 @@ ValuePtr builtin_lookup(const Context *, const EvalContext *evalctx) */ static Value::VectorType search(const std::string &find, const std::string &table, - unsigned int num_returns_per_match, unsigned int index_col_num) + unsigned int num_returns_per_match) { Value::VectorType returnvec; //Unicode glyph count for the length @@ -761,7 +761,12 @@ static Value::VectorType search(const std::string &find, const Value::VectorType Value::VectorType resultvec; const gchar *ptr_ft = g_utf8_offset_to_pointer(find.c_str(), i); for (size_t j = 0; j < searchTableSize; j++) { - const gchar *ptr_st = g_utf8_offset_to_pointer(table[j].toVector()[index_col_num].toString().c_str(), 0); + Value::VectorType entryVec = table[j].toVector(); + if (entryVec.size() <= index_col_num) { + PRINTB("WARNING: Invalid entry in search vector at index %d, required number of values in the entry: %d. Invalid entry: %s", j % (index_col_num + 1) % table[j]); + return Value::VectorType(); + } + const gchar *ptr_st = g_utf8_offset_to_pointer(entryVec[index_col_num].toString().c_str(), 0); if (ptr_ft && ptr_st && (g_utf8_get_char(ptr_ft) == g_utf8_get_char(ptr_st)) ) { matchCount++; if (num_returns_per_match == 1) { @@ -814,7 +819,7 @@ ValuePtr builtin_search(const Context *, const EvalContext *evalctx) } } else if (findThis->type() == Value::STRING) { if (searchTable->type() == Value::STRING) { - returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match, index_col_num); + returnvec = search(findThis->toString(), searchTable->toString(), num_returns_per_match); } else { returnvec = search(findThis->toString(), searchTable->toVector(), num_returns_per_match, index_col_num); From 13ba427bb461ca65c03b765f2a1862607f4e2c08 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 9 Jan 2015 02:00:33 +0100 Subject: [PATCH 041/174] Extend Windows version detection (fixes #1076). As GetVersionEx() is deprecated and will not report Windows 8.1 without additional resource file manipulation this is now using the code from http://hg.m1xa.com/findversion (by M1xA / MIT license) which is using the VerifyVersionInfo API. --- openscad.pro | 1 + src/PlatformUtils-win.cc | 24 +++++++- src/findversion.h | 120 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 src/findversion.h diff --git a/openscad.pro b/openscad.pro index e25639f4..baf92464 100644 --- a/openscad.pro +++ b/openscad.pro @@ -496,6 +496,7 @@ unix:!macx { SOURCES += src/PlatformUtils-posix.cc } win* { + HEADERS += src/findversion.h SOURCES += src/PlatformUtils-win.cc } diff --git a/src/PlatformUtils-win.cc b/src/PlatformUtils-win.cc index 2a54d8fd..c3cba45a 100644 --- a/src/PlatformUtils-win.cc +++ b/src/PlatformUtils-win.cc @@ -1,5 +1,6 @@ #include "PlatformUtils.h" #include "printutils.h" +#include "findversion.h" #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 #endif @@ -126,7 +127,8 @@ std::string PlatformUtils::sysinfo() OSVERSIONINFOEX osinfo; osinfo.dwOSVersionInfoSize = sizeof(osinfo); - if (GetVersionEx((OSVERSIONINFO*)&osinfo) == 0) { + + if (GetVersionExEx(&osinfo) == 0) { result += "Unknown Windows"; } else { unsigned int version = osinfo.dwMajorVersion * 1000 + osinfo.dwMinorVersion; @@ -154,9 +156,25 @@ std::string PlatformUtils::sysinfo() // For applications that have been manifested for Windows 8.1. result += (osinfo.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"); break; + default: + result += "Unknown Windows"; + break; } - boost::format fmt(" (v%d.%d)"); - fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion; + + if (osinfo.wServicePackMajor > 0) { + boost::format fmtServicePack; + if (osinfo.wServicePackMinor == 0) { + fmtServicePack = boost::format(" SP%d"); + fmtServicePack % osinfo.wServicePackMajor; + } else { + fmtServicePack = boost::format(" SP%d.%d"); + fmtServicePack % osinfo.wServicePackMajor % osinfo.wServicePackMinor; + } + result += fmtServicePack.str(); + } + + boost::format fmt(" (v%d.%d.%d.%d)"); + fmt % osinfo.dwMajorVersion % osinfo.dwMinorVersion % osinfo.wServicePackMajor % osinfo.wServicePackMinor; result += fmt.str(); } else { boost::format fmt("Unknown Windows (dwPlatformId = %d, dwMajorVersion = %d, dwMinorVersion = %d"); diff --git a/src/findversion.h b/src/findversion.h new file mode 100644 index 00000000..b027f68b --- /dev/null +++ b/src/findversion.h @@ -0,0 +1,120 @@ +/* +* Find Windows version using bisection method and VerifyVersionInfo. +* +* Author: M1xA, www.m1xa.com +* Date: 2013.07.07 +* Licence: MIT +* Version: 1.0 +* +* API: +* +* BOOL GetVersionExEx(OSVERSIONINFOEX * osVer); +* Returns: 0 if fails. +* +* Supported OS: Windows 2000 .. Windows 8.1. +*/ +#ifndef __FIND_VERSION__ +#define __FIND_VERSION__ + +#include + +#define FV_EQUAL 0 +#define FV_LESS -1 +#define FV_GREAT 1 +#define FV_MIN_VALUE 0 +#define FV_MINOR_VERSION_MAX_VALUE 16 + +int testValue(OSVERSIONINFOEX * value, DWORD verPart, DWORDLONG eq, DWORDLONG gt) +{ + if (VerifyVersionInfo(value, verPart, eq) == FALSE) + { + if (VerifyVersionInfo(value, verPart, gt) == TRUE) + return FV_GREAT; + return FV_LESS; + } + else + return FV_EQUAL; +} + +DWORDLONG gtFor(DWORD target) +{ + return VerSetConditionMask(0, target, VER_GREATER); +} + +DWORDLONG eqFor(DWORD target) +{ + return VerSetConditionMask(0, target, VER_EQUAL); +} + +#define findPartTemplate(T)\ +BOOL findPart##T(T * part, DWORD partType, OSVERSIONINFOEX * ret, T a, T b) \ +{ \ + int funx = FV_EQUAL; \ +\ + DWORDLONG const eq = eqFor(partType); \ + DWORDLONG const gt = gtFor(partType); \ +\ + T * p = part; \ +\ + *p = (a + b) / 2; \ +\ + while ((funx = testValue(ret, partType, eq, gt)) != FV_EQUAL) \ + { \ + switch (funx) \ + { \ + case FV_GREAT: a = *p; break; \ + case FV_LESS: b = *p; break; \ + } \ +\ + *p = (a + b) / 2; \ +\ + if (*p == a) \ + { \ + if (testValue(ret, partType, eq, gt) == FV_EQUAL) \ + return TRUE; \ +\ + *p = b; \ +\ + if (testValue(ret, partType, eq, gt) == FV_EQUAL) \ + return TRUE; \ +\ + a = 0; \ + b = 0; \ + *p = 0; \ + } \ +\ + if (a == b) \ + { \ + *p = 0; \ + return FALSE; \ + } \ + } \ +\ + return TRUE; \ +} + +findPartTemplate(DWORD) +findPartTemplate(WORD) +findPartTemplate(BYTE) + +BOOL GetVersionExEx(OSVERSIONINFOEX * osVer) +{ + BOOL ret = TRUE; + + ZeroMemory(osVer, sizeof(OSVERSIONINFOEX)); + + osVer->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + ret &= findPartDWORD(&osVer->dwPlatformId, VER_PLATFORMID, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartDWORD(&osVer->dwMajorVersion, VER_MAJORVERSION, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartDWORD(&osVer->dwMinorVersion, VER_MINORVERSION, osVer, FV_MIN_VALUE, FV_MINOR_VERSION_MAX_VALUE); + ret &= findPartDWORD(&osVer->dwBuildNumber, VER_BUILDNUMBER, osVer, FV_MIN_VALUE, MAXDWORD); + ret &= findPartWORD(&osVer->wServicePackMajor, VER_SERVICEPACKMAJOR, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartWORD(&osVer->wServicePackMinor, VER_SERVICEPACKMINOR, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartWORD(&osVer->wSuiteMask, VER_SUITENAME, osVer, FV_MIN_VALUE, MAXWORD); + ret &= findPartBYTE(&osVer->wProductType, VER_PRODUCT_TYPE, osVer, FV_MIN_VALUE, MAXBYTE); + + return ret; +} + +#endif From 166e3df8501e040362f7ac7bb1322360cfb24e2a Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 9 Jan 2015 18:20:07 +0100 Subject: [PATCH 042/174] Remove setting the font size for the warning/error bar. --- src/MainWindow.h | 2 +- src/MainWindow.ui | 78 +++++++++++++++++++++++++++-------------------- src/mainwin.cc | 9 +++--- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/MainWindow.h b/src/MainWindow.h index dc5c8140..f753bdfe 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -205,7 +205,7 @@ public slots: void actionReloadRenderPreview(); void on_editorDock_visibilityChanged(bool); void on_consoleDock_visibilityChanged(bool); - void on_pushButtonCompileResultClose_clicked(); + void on_toolButtonCompileResultClose_clicked(); void editorTopLevelChanged(bool); void consoleTopLevelChanged(bool); #ifdef ENABLE_OPENCSG diff --git a/src/MainWindow.ui b/src/MainWindow.ui index e316e56b..22740ec6 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -45,37 +45,18 @@ 9 + + 9 + - 2 + 9 - 2 + 6 + + + 4 - - - - - 0 - 0 - - - - - 26 - 26 - - - - - - - :/icons/information-icons-error.png - - - true - - - @@ -86,7 +67,6 @@ - 14 75 true @@ -97,7 +77,10 @@ - + + + + @@ -105,11 +88,43 @@ :/icons/close.png:/icons/close.png - + + + 22 + 22 + + + + Qt::ToolButtonIconOnly + + true + + + + QToolButton { border: none; } + + + + + + + :/icons/information-icons-error.png:/icons/information-icons-error.png + + + + 22 + 22 + + + + false + + + @@ -874,9 +889,6 @@ Show Scale Markers - diff --git a/src/mainwin.cc b/src/mainwin.cc index 123bfd4d..014a5f13 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -957,7 +957,7 @@ void MainWindow::waitAfterReload() } } -void MainWindow::on_pushButtonCompileResultClose_clicked() +void MainWindow::on_toolButtonCompileResultClose_clicked() { frameCompileResult->hide(); } @@ -977,10 +977,11 @@ void MainWindow::updateCompileResult() QFileInfo fileInfo(fileName); msg = QString(_("Error while compiling '%1'.")).arg(fileInfo.fileName()); } - labelCompileResultIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/information-icons-error.png"))); + toolButtonCompileResultIcon->setIcon(QIcon(QString::fromUtf8(":/icons/information-icons-error.png"))); } else { - msg = QString(_("Compilation generated %1 warnings.")).arg(compileWarnings); - labelCompileResultIcon->setPixmap(QPixmap(QString::fromUtf8(":/icons/information-icons-warning.png"))); + const char *fmt = ngettext("Compilation generated %1 warning.", "Compilation generated %1 warnings.", compileWarnings); + msg = QString(fmt).arg(compileWarnings); + toolButtonCompileResultIcon->setIcon(QIcon(QString::fromUtf8(":/icons/information-icons-warning.png"))); } msg += _(" For details see console window."); labelCompileResultMessage->setText(msg); From 59437041947725a096cba5bd2e824fac9d889419 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 9 Jan 2015 19:04:43 +0100 Subject: [PATCH 043/174] Fix icon selection for dark theme. --- ...review-32 (1).png => Preview-32-white.png} | Bin openscad.qrc | 2 +- src/MainWindow.h | 1 + src/MainWindow.ui | 2 +- src/mainwin.cc | 86 +++++++----------- 5 files changed, 35 insertions(+), 56 deletions(-) rename images/{Preview-32 (1).png => Preview-32-white.png} (100%) diff --git a/images/Preview-32 (1).png b/images/Preview-32-white.png similarity index 100% rename from images/Preview-32 (1).png rename to images/Preview-32-white.png diff --git a/openscad.qrc b/openscad.qrc index 4e55aaaf..0d831562 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -59,9 +59,9 @@ images/perspective1.png images/Preview-32.png images/animate.png - images/Preview-32 (1).png images/orthogonalwhite.png images/perspective1white.png + images/Preview-32-white.png images/crosswhite.png icons/background.png images/scalemarkers.png diff --git a/src/MainWindow.h b/src/MainWindow.h index f753bdfe..354da70e 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -99,6 +99,7 @@ private slots: void showProgress(); void openCSGSettingsChanged(); private: + void initActionIcon(QAction *action, const char *darkResource, const char *lightResource); void openFile(const QString &filename); void handleFileDrop(const QString &filename); void refreshDocument(); diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 22740ec6..f5589ddf 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -239,7 +239,7 @@ 0 0 1397 - 33 + 35 diff --git a/src/mainwin.cc b/src/mainwin.cc index 014a5f13..6cbbee67 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -473,60 +473,31 @@ MainWindow::MainWindow(const QString &filename) addKeyboardShortCut(this->viewerToolBar->actions()); addKeyboardShortCut(this->editortoolbar->actions()); - //Toolbar - int defaultcolor = viewerToolBar->palette().background().color().lightness(); - - if (defaultcolor > 165) { - fileActionNew->setIcon(QIcon("://images/blackNew.png")); - fileActionOpen->setIcon(QIcon("://images/Open-32.png")); - fileActionSave->setIcon(QIcon("://images/Save-32.png")); - editActionZoomIn->setIcon(QIcon("://images/zoomin.png")); - editActionZoomOut->setIcon(QIcon("://images/zoomout.png")); - designActionRender->setIcon(QIcon("://images/blackRender.png")); - viewActionShowAxes->setIcon(QIcon("://images/blackaxes.png")); - viewActionShowEdges->setIcon(QIcon("://images/Rotation-32.png")); - viewActionZoomIn->setIcon(QIcon("://images/zoomin.png")); - viewActionZoomOut->setIcon(QIcon("://images/zoomout.png")); - viewActionTop->setIcon(QIcon("://images/blackUp.png")); - viewActionBottom->setIcon(QIcon("://images/blackbottom.png")); - viewActionLeft->setIcon(QIcon("://images/blackleft (copy).png")); - viewActionRight->setIcon(QIcon("://images/rightright.png")); - viewActionFront->setIcon(QIcon("://images/blackfront.png")); - viewActionBack->setIcon(QIcon("://images/blackback.png")); - viewActionSurfaces->setIcon(QIcon("://images/surface.png")); - viewActionWireframe->setIcon(QIcon("://images/wireframe1.png")); - viewActionShowCrosshairs->setIcon(QIcon("://images/cross.png")); - viewActionPerspective->setIcon(QIcon("://images/perspective1.png")); - viewActionOrthogonal->setIcon(QIcon("://images/orthogonal.png")); - viewActionPreview->setIcon(QIcon("://images/Preview-32.png")); - viewActionAnimate->setIcon(QIcon("://images/animate.png")); - } else { - fileActionNew->setIcon(QIcon("://images/Document-New-128.png")); - fileActionOpen->setIcon(QIcon("://images/Open-128.png")); - fileActionSave->setIcon(QIcon("://images/Save-128.png")); - editActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png")); - editActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png")); - designActionRender->setIcon(QIcon("://images/Arrowhead-Right-32.png")); - viewActionZoomIn->setIcon(QIcon("://images/Zoom-In-32.png")); - viewActionZoomOut->setIcon(QIcon("://images/Zoom-Out-32.png")); - viewActionShowAxes->setIcon(QIcon("://images/axes.png")); - viewActionShowEdges->setIcon(QIcon("://images/grid.png")); - viewActionTop->setIcon(QIcon("://images/up.png")); - viewActionBottom->setIcon(QIcon("://images/bottom.png")); - viewActionLeft->setIcon(QIcon("://images/left.png")); - viewActionRight->setIcon(QIcon("://images/right.png")); - viewActionFront->setIcon(QIcon("://images/front.png")); - viewActionBack->setIcon(QIcon("://images/back.png")); - viewActionSurfaces->setIcon(QIcon("://images/surfaceWhite.png")); - viewActionWireframe->setIcon(QIcon("://images/wireframeWhite.png")); - viewActionShowCrosshairs->setIcon(QIcon("://images/crosswhite.png")); - viewActionPreview->setIcon(QIcon("://images/Preview-32(1).png")); - viewActionPerspective->setIcon(QIcon("://images/perspective1white.png")); - viewActionOrthogonal->setIcon(QIcon("://images/orthogonalwhite.png")); - viewActionAnimate->setIcon(QIcon("://images/animate.png")); - designActionExportSTL->setIcon(QIcon(":/images/export-white.png")); - viewActionViewAll->setIcon(QIcon(":/images/zoom-all-white.png")); - } + initActionIcon(fileActionNew, ":/images/blackNew.png", ":/images/Document-New-128.png"); + initActionIcon(fileActionOpen, ":/images/Open-32.png", ":/images/Open-128.png"); + initActionIcon(fileActionSave, ":/images/Save-32.png", ":/images/Save-128.png"); + initActionIcon(editActionZoomIn, ":/images/zoomin.png", ":/images/Zoom-In-32.png"); + initActionIcon(editActionZoomOut, ":/images/zoomout.png", ":/images/Zoom-Out-32.png"); + initActionIcon(designActionRender, ":/images/blackRender.png", ":/images/Arrowhead-Right-32.png"); + initActionIcon(viewActionShowAxes, ":/images/blackaxes.png", ":/images/axes.png"); + initActionIcon(viewActionShowEdges, ":/images/Rotation-32.png", ":/images/grid.png"); + initActionIcon(viewActionZoomIn, ":/images/zoomin.png", ":/images/Zoom-In-32.png"); + initActionIcon(viewActionZoomOut, ":/images/zoomout.png", ":/images/Zoom-Out-32.png"); + initActionIcon(viewActionTop, ":/images/blackUp.png", ":/images/up.png"); + initActionIcon(viewActionBottom, ":/images/blackbottom.png", ":/images/bottom.png"); + initActionIcon(viewActionLeft, ":/images/blackleft (copy).png", ":/images/left.png"); + initActionIcon(viewActionRight, ":/images/rightright.png", ":/images/right.png"); + initActionIcon(viewActionFront, ":/images/blackfront.png", ":/images/front.png"); + initActionIcon(viewActionBack, ":/images/blackback.png", ":/images/back.png"); + initActionIcon(viewActionSurfaces, ":/images/surface.png", ":/images/surfaceWhite.png"); + initActionIcon(viewActionWireframe, ":/images/wireframe1.png", ":/images/wireframeWhite.png"); + initActionIcon(viewActionShowCrosshairs, ":/images/cross.png", ":/images/crosswhite.png"); + initActionIcon(viewActionPerspective, ":/images/perspective1.png", ":/images/perspective1white.png"); + initActionIcon(viewActionOrthogonal, ":/images/orthogonal.png", ":/images/orthogonalwhite.png"); + initActionIcon(designActionPreview, ":/images/Preview-32.png", ":/images/Preview-32-white.png"); + initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); + initActionIcon(designActionExportSTL, ":/images/export.png", ":/images/export-white.png"); + initActionIcon(viewActionViewAll, ":/images/zoom-all.png", ":/images/zoom-all-white.png"); // make sure it looks nice.. QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray(); @@ -587,6 +558,13 @@ MainWindow::MainWindow(const QString &filename) clearCurrentOutput(); } +void MainWindow::initActionIcon(QAction *action, const char *darkResource, const char *lightResource) +{ + int defaultcolor = viewerToolBar->palette().background().color().lightness(); + const char *resource = (defaultcolor > 165) ? darkResource : lightResource; + action->setIcon(QIcon(resource)); +} + void MainWindow::addKeyboardShortCut(const QList &actions) { foreach (QAction *action, actions) { From bb7adc83cb7a0e737d100bad9e6adaac2dc2a05a Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 9 Jan 2015 19:24:04 +0100 Subject: [PATCH 044/174] Add white icons. --- images/Command-Redo-32-white.png | Bin 0 -> 722 bytes images/Command-Reset-32-white.png | Bin 0 -> 1084 bytes images/Command-Undo-32-white.png | Bin 0 -> 726 bytes images/Decrease-Indent-32-white.png | Bin 0 -> 580 bytes images/Increase-Indent-32-white.png | Bin 0 -> 577 bytes openscad.qrc | 5 +++++ src/MainWindow.ui | 4 ++-- src/mainwin.cc | 5 +++++ 8 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 images/Command-Redo-32-white.png create mode 100644 images/Command-Reset-32-white.png create mode 100644 images/Command-Undo-32-white.png create mode 100644 images/Decrease-Indent-32-white.png create mode 100644 images/Increase-Indent-32-white.png diff --git a/images/Command-Redo-32-white.png b/images/Command-Redo-32-white.png new file mode 100644 index 0000000000000000000000000000000000000000..51a198ce6316db9798e0a972c310605703c52f20 GIT binary patch literal 722 zcmV;@0xkWCP)_AF$6)`A0T?$Wf$#rPZw+w z9a3t07?UvuwLd6J+BNN4FRPTzwy7W@`_^m33n0D#eGykxOhB71v#8>v)E=tGfcCXmTwBvBN%4F-e# z)SK>8O24$*?IS|SIgGK75Mn*mlRZ22QGBCxx=yE-;D_Ncp76y?><&d$S7DAejlY-?+4T#}>+$8q!Bnk>tYWm%4kqWBSG zEH)aA7cQ4;Wgvl6DrIL`_Ca@je0=;i9*-{$G6w(%1OiGvpTDiD>Zfjv}%lSk@(!MYgcerIbDt#QGo>mOe>v7ipn?z*3=Xf714;u-hf=!#?=1 zr3KL>{UH&FmS~d7Wbt9uL1U9J`86}n+&X(9qByl}hEo&d$!eeSLjz z+HAJ3DT)$WQOht4wNxtI^?JRZw*-((CP(ac`|kh%plO=OFibxHfHJ?=G%c-Z+M`OP z60KINyMzz}W8BO0d;lRdi81!q)+?1t3m%W>J<9+a8ynXh4o9THFZxrK<-41kn-3-? zCX5#qOr=t92!ikhP19~OCd=}i*X#Y*5bftA;`>$r#>U1D_xAQ)J2^So1pojD zAr=JTexuwo0G*wk9Sx;|km7m%UOJur%pyd#P$=9spIMe2Pb3o8ngXb*`VR#(O?##& z%6FwwY4+gY;N``|#h}$r@cDd8s;Y*~XP)P$>T}NYG)>b|wOaj3)3l$Dj*fl{1OmJ5 zIGv&>4>88$004jxy78Y|?dt04fFwyok|eUfzpphtf*MD3hC(6SE`TISPYvVmuB9jn zH9dk%Ci56$d=(+&<~Z&p0Kl_$00iOR4fKox7~|^gM5anD6fH{suxwof=$xX=y2J zsSOK-!aN~FJvAn`!{K-mi^Y0c*}T8M|1rZbm(9ymmgTu%Flbl;7#SH!7K_FCns?!< z%jJq~Z*PxVk=^6*{E9KYX~xRs@`BIji?%!yilX=t&+~WctaVvc)rW_Nhrb*jAMbW_ zbO4O8+v#*(V_9|zV|>e$9RL6-mCCo#XmomddfGVGP%4Vz9ggGfK?re!jxq0#hErL& zTwaJoA|K4m%ouG=#amljenAjE!5F_{C0|w5xGc+aFOvP-V|gNx2-s}4DVnBl&@??j zom!k>7(mx`(J+i?u~>Yxyu2Kqot-r<{`FieE9);Y9+St}v<24y0000f)xwS$-->>`t< zAlgA?T?RoJ=c9|l;QBEJQHObM^UgcZ`~05w{k;QV!h{JE{}|Yxepo7%d^Vfy5<C2Fx)QWQm63xaTyrs*5gmy#syHJi<|Ua$9kEEYS~-(WCU$Y!(KgTdgj zPK1NwxaWpiP_Nfh48uH{oV2HD+JGR4Q(}_ePkzPjtMN#xxn{Y`B006*Zu{@|&tM`lwU|H6u+aIH2TXQzh z>-Db9vub7_<#alYlF6iMzySw_VLJc-s;bt^|Gx!He2J6vn@xhJaW- z6e*!XK?G$KN`>|m*k!LC_8(Zh^dPkVKqH!sXeS&bu4TT&3Bube0jgjo4hwbq)3tecS%<#48wRJ@&eEE%v36M31H0^ z1OY6|`lM-^f1N*mbt0S1eh~p!EEcbl$>ci#XJG)#S_*2l z+Enliyae!K_2q<+Q$ z!YSBCt8G^lY9qgq;6|_?S+o9~TOR zi+n!+?8a*VrL;I2jlP?v85o9f@J|{HrL@@V^`7okh+3`IU6Ej%^Pll}+yQVWtQ5Ph zJFeI3yEh|E)4uK5jA$5uX_{iq$hPeh!9rv(#>N0n!T{#;xfk7fB1MX{NxuMt3D1>! Sy!NgD00001r;P)v{rBauKkRwggK61{hjIlKU z0AuXMu6IDWO$F!tK`xj3KnOV!LY$4q<0@lp-RX3Su~@7eggu|nzx$(r>2&(pt58b0 zM+kWW03d`oyV;Jv#cwT$Mx)Psi!eS+CX*Tf82?;=uIu|=iP>!SRU(mi?Yi!AwOUn* z#iC&t#%Vkrf3t0IDWzz&TKPt!;oMq4rBb=RIX4=OUQ$Ybk{1eva{vIxaVC!Ayx+FC z>$;AV(%tEZy4~*KVzJoF=W}Z?7(Big!x#>Sr*}o}`wZLd_CX}# + images/Command-Redo-32-white.png + images/Command-Reset-32-white.png + images/Command-Undo-32-white.png + images/Decrease-Indent-32-white.png + images/Increase-Indent-32-white.png images/Command-Redo-32.png images/Command-Reset-32.png images/Command-Undo-32.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index d63c870d..0df664b4 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -210,6 +210,7 @@ + @@ -405,13 +406,12 @@ - + - diff --git a/src/mainwin.cc b/src/mainwin.cc index 6cbbee67..9646b367 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -498,6 +498,11 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); initActionIcon(designActionExportSTL, ":/images/export.png", ":/images/export-white.png"); initActionIcon(viewActionViewAll, ":/images/zoom-all.png", ":/images/zoom-all-white.png"); + initActionIcon(editActionUndo, ":/images/Command-Undo-32.png", ":/images/Command-Undo-32-white.png"); + initActionIcon(editActionRedo, ":/images/Command-Redo-32.png", ":/images/Command-Redo-32-white.png"); + initActionIcon(editActionUnindent, ":/images/Decrease-Indent-32.png", ":/images/Decrease-Indent-32-white.png"); + initActionIcon(editActionIndent, ":/images/Increase-Indent-32.png", ":/images/Increase-Indent-32-white.png"); + initActionIcon(viewActionResetView, ":/images/Command-Reset-32.png", ":/images/Command-Reset-32-white.png"); // make sure it looks nice.. QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray(); From cd5ecb5eeb83cbe46ca94bfdca5b55fdfec6ab43 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Fri, 9 Jan 2015 20:20:29 +0100 Subject: [PATCH 045/174] Make welcome screen work for dark themes. --- icons/background.png | Bin 50793 -> 44071 bytes src/MainWindow.ui | 4 +++- src/launchingscreen.cc | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/icons/background.png b/icons/background.png index c0c304c150c3850103dd1cad19ba22aefb34bc7d..db3b1134a565f7fd7ffc60876cace5a5fcb808c9 100644 GIT binary patch literal 44071 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 diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 0df664b4..81b97aa5 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -221,6 +221,7 @@ + @@ -240,7 +241,7 @@ 0 0 1397 - 35 + 33 @@ -408,6 +409,7 @@ + diff --git a/src/launchingscreen.cc b/src/launchingscreen.cc index 3a27f7e4..461ba701 100644 --- a/src/launchingscreen.cc +++ b/src/launchingscreen.cc @@ -25,8 +25,8 @@ LaunchingScreen::LaunchingScreen(QWidget *parent) : QDialog(parent) { LaunchingScreen::inst = this; setupUi(this); - this->setStyleSheet("QDialog {background-image:url(':/icons/background.png')}" - "QPushButton {color:white;}"); + + this->setStyleSheet("QDialog {background-image:url(':/icons/background.png')} QPushButton {color:white;}"); this->versionNumberLabel->setText(openscad_version.c_str()); From 9f6b7b170d71257bb326b2db11fead0d6bfa6f09 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 9 Jan 2015 18:13:43 -0500 Subject: [PATCH 046/174] #1105 Yet another testcase --- testdata/scad/bugs/issue1105d.scad | 8 ++++++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1105d-expected.png | Bin 0 -> 10042 bytes .../monotonepngtest/issue1105d-expected.png | Bin 0 -> 10057 bytes .../opencsgtest/issue1105d-expected.png | Bin 0 -> 10519 bytes 5 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue1105d.scad create mode 100644 tests/regression/cgalpngtest/issue1105d-expected.png create mode 100644 tests/regression/monotonepngtest/issue1105d-expected.png create mode 100644 tests/regression/opencsgtest/issue1105d-expected.png diff --git a/testdata/scad/bugs/issue1105d.scad b/testdata/scad/bugs/issue1105d.scad new file mode 100644 index 00000000..f37b6554 --- /dev/null +++ b/testdata/scad/bugs/issue1105d.scad @@ -0,0 +1,8 @@ +difference() { + rotate_extrude(convexity=2, $fn=8) + translate([5,0,0]) difference() { + circle(r=2); + circle(r=1); + } + translate([-5,-5,5]) cube(10, center=true); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 19bdaaff..76f21166 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1221,7 +1221,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue945d.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1105d-expected.png b/tests/regression/cgalpngtest/issue1105d-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b62fcca224864f4948db23d1961f92751b31a9b4 GIT binary patch literal 10042 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 S;Qzz{$NqA(D?IFZ`+oqaXxHli literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue1105d-expected.png b/tests/regression/monotonepngtest/issue1105d-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b5c4e5e3d8e013e2402da08fe4b3135f34e49d71 GIT binary patch literal 10057 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 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue1105d-expected.png b/tests/regression/opencsgtest/issue1105d-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..e6d2c817bc2ad9ca298934ff226f48fc36d94414 GIT binary patch literal 10519 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 literal 0 HcmV?d00001 From 670d9a0833f8f11a64477466cb773385ee761ef6 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 10 Jan 2015 00:35:45 +0100 Subject: [PATCH 047/174] Enable word wrap to prevent the message forcing a bigger viewport size. --- src/MainWindow.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 81b97aa5..2b4d5ab1 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -74,6 +74,9 @@ Message + + true + From 1ae9ed5ada72bb68a5065849ab648bdfd27170ad Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 10 Jan 2015 00:54:13 +0100 Subject: [PATCH 048/174] Allow true/false for boolean settings. --- src/Preferences.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/Preferences.cc b/src/Preferences.cc index f133ffdc..33f045ac 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include "GeometryCache.h" #include "AutoUpdater.h" #include "feature.h" @@ -49,18 +50,27 @@ class SettingsReader : public Settings::Visitor { QSettings settings; const Value getValue(const Settings::SettingsEntry& entry, const std::string& value) const { - if (value.empty()) { + std::string trimmed_value(value); + boost::trim(trimmed_value); + + if (trimmed_value.empty()) { return entry.defaultValue(); } try { switch (entry.defaultValue().type()) { case Value::STRING: - return Value(value); + return Value(trimmed_value); case Value::NUMBER: - return Value(boost::lexical_cast(value)); + return Value(boost::lexical_cast(trimmed_value)); case Value::BOOL: - return Value(boost::lexical_cast(value)); + boost::to_lower(trimmed_value); + if ("false" == trimmed_value) { + return Value(false); + } else if ("true" == trimmed_value) { + return Value(true); + } + return Value(boost::lexical_cast(trimmed_value)); default: assert(false && "invalid value type for settings"); } @@ -74,7 +84,9 @@ class SettingsReader : public Settings::Visitor std::string key = entry.category() + "/" + entry.name(); std::string value = settings.value(QString::fromStdString(key)).toString().toStdString(); - s->set(entry, getValue(entry, value)); + const Value v = getValue(entry, value); + PRINTDB("SettingsReader R: %s = '%s' => '%s'", key.c_str() % value.c_str() % v.toString()); + s->set(entry, v); } }; @@ -87,9 +99,11 @@ class SettingsWriter : public Settings::Visitor QString key = QString::fromStdString(entry.category() + "/" + entry.name()); if (entry.is_default()) { settings.remove(key); + PRINTDB("SettingsWriter D: %s", key.toStdString().c_str()); } else { Value value = s->get(entry); settings.setValue(key, QString::fromStdString(value.toString())); + PRINTDB("SettingsWriter W: %s = '%s'", key.toStdString().c_str() % value.toString().c_str()); } } }; From ddd1228a51c69ba1ec426a4236e28f00048b6431 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 10 Jan 2015 00:54:52 +0100 Subject: [PATCH 049/174] Add settings entry to enable/disable warning display in the 3D view. --- src/Preferences.cc | 7 +++++++ src/Preferences.h | 1 + src/Preferences.ui | 17 +++++++++++++++-- src/mainwin.cc | 5 +++++ src/settings.cc | 1 + src/settings.h | 1 + 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Preferences.cc b/src/Preferences.cc index 33f045ac..93900a0e 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -485,6 +485,12 @@ void Preferences::on_launcherBox_toggled(bool state) settings.setValue("launcher/showOnStartup", state); } +void Preferences::on_checkBoxShowWarningsIn3dView_toggled(bool val) +{ + Settings::Settings::inst()->set(Settings::Settings::showWarningsIn3dView, Value(val)); + writeSettings(); +} + void Preferences::on_spinBoxIndentationWidth_valueChanged(int val) { Settings::Settings::inst()->set(Settings::Settings::indentationWidth, Value(val)); @@ -683,6 +689,7 @@ void Preferences::updateGUI() this->checkBoxAutoIndent->setChecked(s->get(Settings::Settings::autoIndent).toBool()); this->checkBoxHighlightCurrentLine->setChecked(s->get(Settings::Settings::highlightCurrentLine).toBool()); this->checkBoxEnableBraceMatching->setChecked(s->get(Settings::Settings::enableBraceMatching).toBool()); + this->checkBoxShowWarningsIn3dView->setChecked(s->get(Settings::Settings::showWarningsIn3dView).toBool()); } void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry) diff --git a/src/Preferences.h b/src/Preferences.h index 82cced50..a29c5328 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -46,6 +46,7 @@ public slots: void on_launcherBox_toggled(bool); void on_editorType_editTextChanged(const QString &); + void on_checkBoxShowWarningsIn3dView_toggled(bool); // // editor settings // diff --git a/src/Preferences.ui b/src/Preferences.ui index 7c411229..2e20dc70 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -6,8 +6,8 @@ 0 0 - 621 - 413 + 675 + 476 @@ -31,6 +31,9 @@ + + 0 + @@ -75,6 +78,16 @@ + + + + Show Warnings and Errors in 3D View + + + false + + + diff --git a/src/mainwin.cc b/src/mainwin.cc index 9646b367..f46be97b 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -952,6 +952,11 @@ void MainWindow::updateCompileResult() return; } + Settings::Settings *s = Settings::Settings::inst(); + if (!s->get(Settings::Settings::showWarningsIn3dView).toBool()) { + return; + } + QString msg; if (compileErrors > 0) { if (fileName.isEmpty()) { diff --git a/src/settings.cc b/src/settings.cc index 8af5fea3..99a4ec05 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -121,6 +121,7 @@ Visitor::~Visitor() * external settings file. The second value is the display value that * can be translated. */ +SettingsEntry Settings::showWarningsIn3dView("3dview", "showWarningsIn3dView", Value(true), Value(true)); SettingsEntry Settings::indentationWidth("editor", "indentationWidth", Value(Value::RangeType(1, 16)), Value(4)); SettingsEntry Settings::tabWidth("editor", "tabWidth", Value(Value::RangeType(1, 16)), Value(8)); SettingsEntry Settings::lineWrap("editor", "lineWrap", values("None", _("None"), "Char", _("Wrap at character boundaries"), "Word", _("Wrap at word boundaries")), Value("Word")); diff --git a/src/settings.h b/src/settings.h index a3099fe8..2864bb2c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -35,6 +35,7 @@ protected: class Settings { public: + static SettingsEntry showWarningsIn3dView; static SettingsEntry indentationWidth; static SettingsEntry tabWidth; static SettingsEntry lineWrap; From 197dd5ef3bcc1f90fad4910580c293ddb60eeeca Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 10 Jan 2015 02:06:19 +0100 Subject: [PATCH 050/174] Add scale marker icon for dark theme. --- images/scalemarkers-white.png | Bin 0 -> 369 bytes images/scalemarkers.png | Bin 265 -> 348 bytes openscad.qrc | 1 + src/MainWindow.ui | 1 + src/mainwin.cc | 1 + 5 files changed, 3 insertions(+) create mode 100644 images/scalemarkers-white.png diff --git a/images/scalemarkers-white.png b/images/scalemarkers-white.png new file mode 100644 index 0000000000000000000000000000000000000000..1d6583c361ba254ef546f726128b55da2e7ae504 GIT binary patch literal 369 zcmV-%0gnEOP)K}rKb5Ji6l1fxUr z0tPqYDFV4f?xGhEavihCPO{T&5O?C%b%;aAB0M)W1coFXraKWy|4moZF!QSB_h+Q6 z2m!=C!%_j5nf=QNv=TrR*#jrsU0nC$k9spQXpABdMt6&hBnF08E8R_ALq;s#^lFA@}cTzY^ z842(u>Bj4>q|d!3kl@9Yo+S-{j--L4(Lus$Tip8ft8!rUr$4e;S#|va^*CuBe>O}J P00000NkvXXu0mjftrU=3 literal 0 HcmV?d00001 diff --git a/images/scalemarkers.png b/images/scalemarkers.png index 067b936638574f58dfdd186f9b664ffc8ba3ff09..a63013542805eacae25c5498f39c7357e0edda14 100644 GIT binary patch delta 321 zcmV-H0lxl;0^9>ILqR^9lt@!K1i+mBEi7{|1?D$jOuuV}5lC)E__!~hI{ z9^eCAp#M($BgJf30ZqwUz(RYTUj+z(g5*VDpT*7}0i3PZmXkVh5E)s_041fsM<6eG zK{}EM5Lu>&N;-fIP?Nk4te@>bn9>m*0)d=@02pO8tm4M4Z_Ruz$005RrL_t(o z!|jtz3d0}}MxUWc7xost|2gbFhsX)K$ZE2gf=Ci*v^BwbAUfbUf1hAn9Lasa6$Lo$M&G9`1AnyT+=1U*ING+Vi^72MaV+%Sy4u>cR$GZyZ(At?X= N002ovPDHLkV1k7NS)>2} diff --git a/openscad.qrc b/openscad.qrc index 5befaeaf..06abb408 100644 --- a/openscad.qrc +++ b/openscad.qrc @@ -75,5 +75,6 @@ images/crosswhite.png icons/background.png images/scalemarkers.png + images/scalemarkers-white.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 2b4d5ab1..96d31f21 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -226,6 +226,7 @@ + diff --git a/src/mainwin.cc b/src/mainwin.cc index f46be97b..0b966868 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -503,6 +503,7 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(editActionUnindent, ":/images/Decrease-Indent-32.png", ":/images/Decrease-Indent-32-white.png"); initActionIcon(editActionIndent, ":/images/Increase-Indent-32.png", ":/images/Increase-Indent-32-white.png"); initActionIcon(viewActionResetView, ":/images/Command-Reset-32.png", ":/images/Command-Reset-32-white.png"); + initActionIcon(viewActionShowScaleProportional, ":/images/scalemarkers.png", ":/images/scalemarkers-white.png"); // make sure it looks nice.. QByteArray windowState = settings.value("window/state", QByteArray()).toByteArray(); From 094bc92090f035e5d8d40611b20ba29b30e57ef5 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 10 Jan 2015 17:21:56 +0100 Subject: [PATCH 051/174] Scale icons depending on font size. --- src/MainWindow.ui | 8 ++++---- src/mainwin.cc | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 96d31f21..4762dc06 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -43,16 +43,16 @@ - 9 + 6 - 9 + 6 - 9 + 6 - 6 + 4 4 diff --git a/src/mainwin.cc b/src/mainwin.cc index 0b966868..d70f91af 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -972,6 +972,12 @@ void MainWindow::updateCompileResult() msg = QString(fmt).arg(compileWarnings); toolButtonCompileResultIcon->setIcon(QIcon(QString::fromUtf8(":/icons/information-icons-warning.png"))); } + QFontMetrics fm(labelCompileResultMessage->font()); + int sizeIcon = std::max(12, std::min(32, fm.height())); + int sizeClose = std::max(10, std::min(32, fm.height()) - 4); + toolButtonCompileResultIcon->setIconSize(QSize(sizeIcon, sizeIcon)); + toolButtonCompileResultClose->setIconSize(QSize(sizeClose, sizeClose)); + msg += _(" For details see console window."); labelCompileResultMessage->setText(msg); frameCompileResult->show(); From 668a5211ff5274b0abe0262d4d1c4c99fe5f0cb8 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 11 Jan 2015 19:31:42 +0100 Subject: [PATCH 052/174] Fix ragel URL and bump to version 6.9. --- scripts/common-build-dependencies.sh | 2 +- scripts/uni-build-dependencies.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/common-build-dependencies.sh b/scripts/common-build-dependencies.sh index 87a2bed0..8ef303df 100644 --- a/scripts/common-build-dependencies.sh +++ b/scripts/common-build-dependencies.sh @@ -161,7 +161,7 @@ build_ragel() cd "$BASEDIR"/src rm -rf "ragel-$version" if [ ! -f "ragel-$version.tar.gz" ]; then - curl --insecure -LO "http://www.complang.org/ragel/ragel-$version.tar.gz" + curl --insecure -LO "http://www.colm.net/files/ragel/ragel-$version.tar.gz" fi tar xzf "ragel-$version.tar.gz" cd "ragel-$version" diff --git a/scripts/uni-build-dependencies.sh b/scripts/uni-build-dependencies.sh index 5ee34919..eb59665e 100755 --- a/scripts/uni-build-dependencies.sh +++ b/scripts/uni-build-dependencies.sh @@ -813,7 +813,7 @@ build_glib2 2.38.2 build_freetype 2.5.0.1 --without-png build_libxml2 2.9.1 build_fontconfig 2.11.0 --with-add-fonts=/usr/X11R6/lib/X11/fonts,/usr/local/share/fonts -build_ragel 6.8 +build_ragel 6.9 build_harfbuzz 0.9.23 --with-glib=yes echo "OpenSCAD dependencies built and installed to " $BASEDIR From ce5b38d96e3d15f8df7ac6a82f45e61e0b63f777 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Sun, 11 Jan 2015 18:21:08 -0600 Subject: [PATCH 053/174] Add on-launch code to set Document Icon in windows registry Since OpenSCAD doesn't distribute with additional image files, this means a new icon needs to be built into the .exe. This is accomplished by adding a line to the end of openscad_win32.rc file consisting of something like the following: IDI_ICON2 ICON DISCARDABLE "icons/openscad_doc.ico" which will get built into the exe as icon index 1 (icon index 0 is the current app icon.) In the cmdline and gui functions in openscad.cc I added code to set the HKEY_CURRENT_USER/Software/Classes/OpenSCAD_File/DefaultIcon/Default value to the icon index 1 of openscad.exe modified: openscad_win32.rc modified: src/openscad.cc --- openscad_win32.rc | 1 + src/openscad.cc | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/openscad_win32.rc b/openscad_win32.rc index ffdc7e24..95be2192 100644 --- a/openscad_win32.rc +++ b/openscad_win32.rc @@ -33,5 +33,6 @@ VS_VERSION_INFO VERSIONINFO /* End of Version info */ IDI_ICON1 ICON DISCARDABLE "icons/openscad.ico" +IDI_ICON2 ICON DISCARDABLE "icons/openscad_doc.ico" diff --git a/src/openscad.cc b/src/openscad.cc index 0b0de394..7be03d27 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -43,6 +43,8 @@ #include "CocoaUtils.h" #include "FontCache.h" +#include + #include #include #include @@ -318,6 +320,12 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c parser_init(); localization_init(); +#ifdef Q_OS_WIN + QSettings reg_setting(QLatin1String("HKEY_CURRENT_USER"), QSettings::NativeFormat); + QString appPath = QDir::toNativeSeparators(app.applicationFilePath() + QLatin1String(",1")); + reg_setting.setValue(QLatin1String("Software/Classes/OpenSCAD_File/DefaultIcon/Default"),QVariant(appPath)); +#endif + Tree tree; #ifdef ENABLE_CGAL GeometryEvaluator geomevaluator(tree); @@ -664,6 +672,12 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha installAppleEventHandlers(); #endif +#ifdef Q_OS_WIN + QSettings reg_setting(QLatin1String("HKEY_CURRENT_USER"), QSettings::NativeFormat); + QString appPath = QDir::toNativeSeparators(app.applicationFilePath() + QLatin1String(",1")); + reg_setting.setValue(QLatin1String("Software/Classes/OpenSCAD_File/DefaultIcon/Default"),QVariant(appPath)); +#endif + #ifdef OPENSCAD_UPDATER AutoUpdater *updater = new SparkleAutoUpdater; AutoUpdater::setUpdater(updater); @@ -901,4 +915,3 @@ int main(int argc, char **argv) return rc; } - From 01a02998909008be41c4623fd16bd910ff7b65a0 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Sun, 11 Jan 2015 18:25:02 -0600 Subject: [PATCH 054/174] New multi-image icon file for Document Icon Different images for different size icons are in the same .ico file. Windows will pick the correct size one as needed. This is built into openscad.exe via the openscad_win32.rc file. new file: icons/openscad_doc.ico --- icons/openscad_doc.ico | Bin 0 -> 98534 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 icons/openscad_doc.ico diff --git a/icons/openscad_doc.ico b/icons/openscad_doc.ico new file mode 100644 index 0000000000000000000000000000000000000000..8a57e8d8720f5d6a0f256b0a7ee861e8b7526b52 GIT binary patch literal 98534 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�bZuw8$fm{@(ifEj|x( zIa*+z-%Ff71RS7dAeN9L2gHBwn17r9e=Gg7u4KgjSd+Ju|3jDmRR7&!|2xiy?Vnm; zq0i6tp{oqd+w)-R8);hlM+sWm2hjbE0bEZ}OE++kX5s)_g#*(rT-I?g@D1373&6q4 zL$p5U9DsxWNzVT{{9qozRP>PDQoTJNeklPf3oOe2FJu4J`e@Am+{OO?X8JG9|J+so z>K?#G{?Btsv4uTf==ruF*K@s2(wKJYcPCwKk8$5eOS{n@qSjN?x4?no17Jbn02r|H z0dOz~d_dcf_|^a|@r_15cMbp7U&DN2H`I@JhTO!OA@AG}pJLokc2cTZ``GmVIw4o9 z@_+wj`j6T$U%Z!LEik3~xgVm}e{Rh|BkrtKCtQ74OMb6|mU=xB<9`r%U?A7k)G=`# zn4m!aIv)(wlCKQ{AH)I!_S)e0f44rK|0IqAE`Rqh`gmP~KD4|MeEC!HT8evrjTx-! zKdkL_!n&CMZTgQ~JI~^>koOZU!un5h3o+;a=hx;R^4_Dc`!%%GYvEej^&!9k*4O=D z5O6@jbL>mI+713e6L7)*Ol)_*aTDrrTf3*Lh zE9Xj={6)8#PAz;M>wdNRx357eI3ev?HR!($bl(E<^uK+MKlmF$zLa?HgC}=5FUb4G zZaD4*jv8<4z7dwv{I3`KJ6z>=u>Y1I^q2+Xo*e!qbHsgN{uRV|#f>H}>hK3w!GHYc zg@`=j_u9t|J$4;Ux1X2ye%pbu(jqoUnne0p8ioDl`nUL@{uh{!np7d~eN~jdzjOZL zfabH7SN)G)m_O+kzd(} zw*Eix^RDBPUw596e%N*L@DkUY(WBgFWqEZeT>3wqXZx>J+;8y38V?xoaFtH2%2#vm zS{402wW0q;wY?qxUwhvjpVRsNe~eG5PmAh6?Uoj`#fl8FcOnrXMhId=kPu=f#0)`* zBsQ@Ud&d^5_N-b}QmYiDrD`SD@BO~d^E@JAv|sJ#pI=_DE9beNbDneV>$>N;@9TQM zt9{|tv=jP?4#3v#0RO)Z@c-*jyK~D9;MMSk|4(IbEmVTPa2bnX{XVf8HTZ*?sRvDd z<^Mo7|NkxjzXkp$7Qhy(WNBGikw;n)e&%0>At!oDB+8JsHhf`7YUT8FmN9L(fhk=; zKmW{lK4&^#j`M#tohQfd|JUhPAaAKVt#qOh*~MD5u*)(hccI zJw5TBN;fgw?vbV!sPXO@TBN$bU_Jc0oPGnt-89YMKvquw!fQV>m2v{>**KtfkEGtHrZ3@Sxz3kpl^}q<*B~U_q@FI>z;RBdfGb2 z1Fdu1041E`0WYRef-jtZQyL{2mHh{QBb}b(_kT5=k>mF{(=S*U`FkM^{aTck}b zjL*gOrWVLFS_sporE5caD9`Z^_J@J$XG}cWGZANq&K7^BnZ+U!t)a$ zF_0+8APB$bb-boMqzfb*G6FIIG6j-okV!ZWh44B{NLdK$%)jmzif6Lke+Fp?=`nr! z^vmYv=2E_Vd1=s~fgp{qZ?%lih9amRZIeYf(J)Sp;o12?Vn>I}{Gc#AUu4y)RX8p8+q7x(C{La|;^5%$)W*iRW_s#K}+_|HH8L{jAL-McE^{rmTqlP6CaKO@pp zE<=vP9ybdYE-cXXeq3DK6WSxE?A^Q9r2o8m^Wa4+*CDrHgQp*S@PRyh`0ymsY;)`j z{tNlH^=JKO`LlnT{OsAY%V}w85*8LFl`2(I`fS{|QD(wNn7Tn98s|Gm+V$(#*F1Re zfOY-bTeoiAC|Izdz$TKOo-SW~^_6_{4ZA>G{M~n%{O#=7vwubMd&s2;6DDx-CP$AR zJ%@BZ2>VXGkt??;hd zykfU`Na@-zw>C&ayc6N3bKm71R zdGEdV1monLCg*<~ci0B%L0UmLpBV=k1?dH80da%0g!G1R zPBR7)0bxN~L25wEAodVXh%=-Sg#DU1gk{Y6POw2ZaPm8zXaDm)sU>L@OR}P zYMVf{k^i zE;>;sX~{9OS*wl$S7}@0)GZ6FR_q>azu{0@&z+}hT**@N%lGhm>d1SukEf`6;>hur zZSbEjd&k6lc^nff6M+7lq$sbq+@uF2nCnyX_Vu}+}fc#_NBYOr6!s}LBPK>wTbMBh~7w+($ z#%HLbu@3&@M~8&+(6 zbyFO7jEx~T3OQ1~=sgs%vLjU76!DYcPpx>?$g@Chc497pqv@IT){}c}_WkJhkL#NA z0gj25(3hOM+4Ro#*?GnQ&3A1N#B|py;?b?bCtm*Xz<0|erwh5=iUHe`ynp0=BknVK z;K&0~5?CON3ubJ1IpBj3CxUnZl?IGf_+i8nt3F}2;+``D-WWM)$W_xM{mf2qTA1g| z=0B2lO!RoA-r4N|Uh2==Bqf{mnD|Ep->!<=Mq!&An^nSgWs|QX`41z z0@G6@Xx~cdc4VFO_->Q*JiS%go;r5T{@C?;@5}~{i627uK5we`1>6#cIZjBq(s~In zCl@Re?-_H&ckUv5HrQdgZigyiLr|u{3j34z|HOa&3_M`emGy#LaD^@PHbPDy_7&uV ztPt2$d>2oa)@x@;`)!M)^PXkW_0Sp#KAt8$zuzLg&TW^_A9qQgj6Krr$D{W>Pr={( zUHmyD_`XT^{LTqOoa2^UY_(vG_%B)~KC>2x`xIdACCw1;nFc#7gdI{>i_N5&z`*aP zFpx?sK0Me0JZI#^Rds@VNGN;O2V=V+H%6WQeQvhfl>A4>T}vcrKg#^rdI>qTS$dt_ zCZQM7CG653>HE`O3BS5u`dvF9A(xNe@;G(nwb)^AG>>Cqxi{&q*(F3+MlamoV$KTj zo3~P0&0j4ZQ>KYi%s6qGI4PSQ<^e}${{1=w;`S;oh~D4?LmzMAgCHjm#zox@Ixk#N z^braZ9Gn1!tsI*N?Ol<-%Yjwy!6!EEXI<}oeuso!M440XEBln*{jVRCh#Q9`;^tuq zy?)}f?Xg?`eWRYQy1*f!)tmIM)_e96pJ^%LGkuBp&Rixf(C68Y94R)#qQrjGNRu7x z$Hd+#R4-t%Rwz z?}SA{J9tAZ`UAHtqOUX=G6*{={PI7;3+1n>XSPYqY(mi&LcmnUx3v<@?0dVNrw$=!jG1dJ^5AG0nfu1xoq9&U*vngD}m zna_fWnJrS|rQPQFdR;e_`E$K#3$}y)*AGePl_S^ej@)>AUp|L~{3!dLuhaiC|AaWF zkx9>7#>@~`#C*~Y9aZ-W^0j`&&E zJsf=@`-UzTjtqR;vWM=)q5G@rzC%Jp{jm6B4#VQbX+)wpk4zGy9W28KiAA3XNPlIA z#(nxoz3$zie}GiOT2}Rta8W$kn9sj}m5lij90RB~`v=-6`24p&+aLJx?cR$W6U|>Y*DKs?>X@bx zv01i*CW+n9$>I>D+rf57Ec6}>83^46=ynM2FO7PIO5M&~q`H4wsWmcAa^;RXwzw@`tRez`II{E?j2kZ~S zFYi<1LfFOK68b~B8Yle@AMW~Ab-*#v`*n4{a$xKxtFSTBBz&B}4x;QZWU^SIj4Xh2 zVu3l1(GHgVV2{27q<;6FQo93i+-9!=hn9|;tn=qQ$4#zbXcJXO0yhbDLE+{bxUO%iZ;$3bn^ zTZ{#ci9xT^zi!Z|pBe{`5X)Yp#5!!OvV(QsF=Ej>3KFT?z+eZfevx7o5h;y&hD*J0 z9LX=f6nugy1}-_pExyWt9Y^fY`8t0D+k?Um19rTjPpBR~TwKN_ibvcW@lINd`NnDq zT)$I#pFa4!u4n93^FYoGdY;)PA>VD5?wBKXJ-k)|_pN=@bo+_YZ>$3j3B6vWe*yPt z!y0ss%xV}EDdydV0aG_xEPIX;i;!Vr(G${}0y~64@4myN>EKafA3aWNBS%T&8B4SA zDP`wU0fsX9)KIs{r>D5o*dBfHcyCh3Iva{C>r;<#l`tGCd<`>XV?&>?Z5dDmgmuydp|=rmLv z&ASa3^X|i83)KG}(7)F(VPD`pcB;5dOu~F{I`G5h>im+Mz&CH=m^Jc>fmdz;IHkZT zrf_5vfg?vwNxbi?K0(=Ff~p5K2aHtxVDmW(#BYA8_%B{5ZIj*LL8ja7e0qo!e+SA$%;8;^+M*(A3X z+e9jOb;zs5_CPG%B=G8yPba$#us%i{J)3cp#3NyvG@CwKbUQ3j@0xA!t{J#_BkKAZ z^h_O`9kFt7nMcl6YydZ2hS>=?~o-=c+&EJPilUKGU?{c(Lw-cHeh`H0>8B zR=vlg+{eHMBgB5_RPmjK_uqLd@a~8Afkmr;54lln6wesA2EjXR4eoKpJ+JD*A+BeM z`HI~-w-9+n$SY&8f#MXJV89eH^aqs(juNNwvA`__W)ke+J!6h;hXt5}Coliae|^f& z9kwr)b{mt``y%lvFlSWwH5Ln2WLj-M`TBJd$Hb!0zyC`%z`Kt1$OYH!G3Gf9pDr#V z=Za(0OtBjT+#}e*vUlvGFM^lEn~z$x&U^0q%k5TdmbMU=eHXyJdPVVWD!#ov2HsUe zT~M66&@c>a!i!hF{JaF>|aezVe~dD2>C2d_y>VFz&E^jnppwcZ8HBH$Ue zObe?z=ky}*vS%soCGs(ohZVd_cI4qb02`2Z4cwdLVaK|*ZUf-5o0EInSPzVCf#U*k zm5Hm!ITAP(h^bnw@8BnezOqOL*X2}jo=n!hw4YS4j?Yx+{nTknl-Q2$FT@Za)@$|P zAT_oW@4IG-)^f9#7I5I>H`-tk<_mpqRYa_|ciz4~ck|hL>rMbTA=)n5F8<(+@S9DZ z0N4TiBGrd(o1+CD?V+{V7gA+@#$4Bn+kmoy0LsIbs0dfH2+K0{PHDi%0xs^$zFNuTBYG`}>{d-WS_(d|lE@13_V2W-D6 zfvdiifMvU+?PAygya|4@H%jC2yH@25z7TA-`PUWTV#_2?yUxc)K1SF9JY0&G7j;4L z@F@;9v1@>nOv zTH2G+er+F>^YM`qwzl#~Q#<(#>*`!{`~q`Q>?365Z`fs`W(LgohJ8k8R*_MfEwJWo zC%)DDvD2wLGl12gxL2EB`dwO{xha09Z;DUG@8YF%@_?_Iyj&1)#40<0pV7$AsoI2r zmyz7OFWG?gfc*jH2o@V)18^@Yz7=pSn2~FTyz6KO#MmV60&%t~4H~Pk)yb`Cz}8jk zsa!`c0!~HpYjDqr+*_5Sr##ZiJI82M{eYFG_8FB6KW7p>76#=)9 ztFlM=9uZQgX44glGyG$4MA8nWOm-Oi*82bSc$(KQdO0iI9}wpoj)w+OoL%@%*@AW; z-k+gwQ2he=8kG%kQU;8O=GlHv)oP7G2U}y)Mj!9$83l#re>NdSEL>(aSvg!xM zU@X9z3FiZfU#D}ZS~ukWlIjDRIz#_<=pXw&$XnWMhW2q~19vvK(?6jd>LkJrF>k9s zc%~hxhr+VV!Fy@sEmFL;v;oeuZ75FbY&KB!;EK*$t$54NgR2;P<&NYhJqB)4)ebHw zZhEV&;GyGqkgX1IJXCxG91CK=HHUWtV;kUJ`sZ!Bs=a0IG13NVpUJn|3GfHUYoFIo z)QV%S@QJ|=>&+EYTamIk<`JD6d5iwnLQG9+6^*W*2g`pm(zR}bc&=;Uj zbj^5-`N2cQ+3t7>V*=X&=7=`?FX?=I>>okGh>C~Tj6>#$3it9f=>na zmrAwkuJ+ZqpT@l;?zI&#^P8bnbOvvx-DIt-GFeoXca=o@JRPmYo74=^sMu~GE}e<;p!a#ibf;Iev8XtMK+ zniJ^#0QjfCL0gY=BCMqu+W`FoI1X?xf&CoEd+^Aq{lp@$!N<)yozbed26teK@#ya+ zn(R=J(ZQ>)Vjd|4g9ou}*o&OG${sy^6`(aKrB{+&2m z*&9Ei{A^gB#4t5-of$bTveyNp4RkKUteg1FFz{K|^Gu#F(gk>z>Eaoi zDs2{Qm4Ky~Tk{>m@UG%VB>nqI?=1OPGdphzRgLdFM2Hv%N zrfn_7fzLJc=W)^C80ntUFs!5LS?2w_?5x|p zwN&X7P?Er6P|-n#C?(=)EZZ zPn(6QdLPJn0QJYZ0N(}5b?cAuFNnS*&)##2oT|Cbh|nD42WmF4gJ1{nNx=^0COiC} zeW)-Os)}~~K=lJT>%hJH;xcUvxK;X!#ei<$XbSiP7!13h^USZCJ3k~ZR|)WT@L18) z&ZIxCBkzas9oAudq`1Y80mtKb@t6_w#5*}w`9ic?iF|0%dD)6*1&s7e1G z0g8i)WnRJAT1r{el@bkWN?E&H^v63a`Rr^)g$p@xT;qo;jC60{kI@&z5BigLq$b-x z=E2-MqyHTH{=!~;w}M+BMDquJxZnCP&3h%*q_W##D(k~L~3z|f_C&p^O|5bz81Qd}c`>ze~V{2z-C1HN-9%yG8xJ*e5y zL*fih)_18t*ENmx-)$lHOcUgbeq--^*mM1O;A#SA6_~2TSPp@7C${pBz*IidUF&!p zxa#|Dfua15>7Kp+@VfadwArmEw_TSeOVj8u)&H6GXlH2uf4}^V`un6NO6}OB$6pN^ zn+&|!4}mTDwHA6E7^B1&HQ)^EcIXP+d4FKZz8;@4d*vK|4Q3^ zYi0hA7nZiO`cFx#28E&jrxiVHYh(Ub8}q-~Wdwbj;=V#`_zO>FGKwLsUZ@afXjaLc z{(YWT9;4I+IWv~Wl;L#4dE+rdrSn0-_V|&t$S}w#$XG}eq!Yvf@)^YRZvQR|1NUV;DD(L7<5nX_jy(PK*I!H7 zvSp=X$Bu%y#}kk(hy%S^zkYoo9suHNe?hGAId^w=#)N;5-|k(#di4*s*biH_Y}rG` znNkcm1J`k$I@N=G2zlpafP1ozez|q)*8Ygue8xEF!-o$`g$flUB_$;b@vqM+SFW73 ze*OAe!NI||h?j8V#*GI!W_9o0Ju5OYGK)A0J$v?4v9xvT*3Cj3?Y-30)CY+FloKaT ze24othp-IZ`S^%?(*9rm`s=T~5u*=A#J&f^j(@CMw@wZnIwaMqRg=@F zPu~p<4ZUk=X(<;kUc8^2oP3LQ8})uY+Qp*k)vNzjvSdj?zHj3mYY=087-f=q_3G8@ zsBeGr+`fJLcH^8U4Rd z&(Oxd#q~WPL1+(aN|h>g2l4aMkPZ$H51)tY?xPGJmMK%_UUYQyF_c3%&ap3L9OysM zewlxcH|)=yAfb@K5cZEQ5JyM=q(7uDqy>ciJI9Ac5Ie(><3oLjJESe7o#8X_3OgmY-PX=O zZNGE)zVGWzIen$<<%f^iKXM!~j%TdztTP`#*hjoG+atF2lYGue_2GkMra2}lUTfYT zLOs}@zSlN!ZjrD1MR%we9=*O&zY#ydZ~PJWfVd9I7+U&_8RAC&Y_NFCrN(Q%UDssm z$u@0|T%rzaQxx9so#h+(Eezjr9~{BiY>XF43Wraajn-zD(xYUn&SkJZI|Z=~ceqbm z0&#wfb5QZH*t;zUzklxKS7aP4d>*;BRUMp?-0$Q5Z{xN5Zo@wy&UW9ACEsNoG5G!G z?)wUVq5R&9dwm@=Y4oQqzSoWWirib|=a1~%RjdwU)wuUgAA~a01wI*!ccL#h{kG`8 zRCmTQF;Cqj)|(Drwb}ba54*$H{_@_-OM2@*i#?v(+-Q6K_`d6uk+r&yKjS)K0l2-F zNyCAo*%S*aKd#-Va;xn4BEpi<;w55{pxM-=UgJ6 zBY)(P{}g*YhBzU$=cC7yB7P8YwcH0}dDI&^Ncn-bSvMQ8lc~x-m_E|<6Yp^P=qa!7 zE`9yBS$^R<-B&VOeSdEIPg>0w=b5zpR_m1Y@LQg(d{uqtEtXb`SHN$1gVY){3Y@sT zl+Olj&3$_A+b|B6dsozhElg5cg8p{&Z9@hu~U9$ zfBfQwyuB&mnD`Ow{<5zt+V1-vNl`9wsXsBUujTyJ;yiwWxK4_L?{SifYxJ43@KK$i z6EAYzwH)dP_Z>=iV9ZjGt_NZ|i=tgnhmUMr4kBL39KPsd5sUD9ud{}DO=IkyA$~3N z+KK&$*)strzBc;~33lhOQiGBLHYuCj^ z+vnjpD`G32nqm$ae};HNW6WKz zYbU3+Jp1NY8~B;i_PNH^mg_iuhR4KtnO;-otJpf1@lz2`7OKb9p&pxu_K}+HyZ&0% zzvqGHJli_Yy7B|U9yoCY=m(+V$2?lDLHyVUh@bPt+VMI1hQAy)hnPX=(eLNO54&9Y zuBlPqR~{V`Yv*SB|F|X&Z8CIPhU?gw;yzxFk5lmvhzT=CY+R$TUQ(xXC#l&EF<~M7 zrN+d0@aLPM`gx9BSkKjcdEl=`Uk>i)lxyGRHn@?$hc9zx^F?tg_9y(xev{3!$Gb7+ zt5?Rsy*?+;zW#m8F)`QJ-tqzQbL}Iih+}kuIFFi!*ske_;bBZu1f-vs1J9~%P>@vf z_m>)jN9#U`^wpvE z(4)813J4T4#BDO}f_{ay;bY9bG~KU`-0kqQhJPvX2Z&A41U@$2NhzZG;U%+F{59jv z7<a> zMTo7k>K`eM!v?^oIYRdpPl12vf;2sb#^@u#i zs`S-e4qsj6pN6u4Zw`HR>6@YZXF&(VEz}w^Mm!T|h|lc#z(`mkt(UBkfYqC&+rdpL zR;ly86>4lothS*q5Vy2_%HJ6HA@H+23ID32CLg;7%D*TLaf-UXvGT8>e+lDH&^K9( z8i%$VkNEzX@KKnrFb@1uR{R>6zT^qxj9Raoh4wua`!wUla?z@-h&Rc7e(jiOl_UQV zHlvd7I7Lqv*U`!1h?okyfeB(67WaF(;AImVk6pd4#iETjTc+(52l$8CA(n!1HS`^~ zHu((0R}wKrDt^G|FKhG>B1a#5M7~Cwwu&Bw@fzMh{ zXyC&ATB|MK@Lt=eWZ%s(F2`>?)#Cu@>!`;<(Dz&UzatL9hQl?KGFq3DPI>!W>)Imi((i2-?~qpTJ8CgwJ>nWxNu%fuY2=_S+~>$3o1^zG z>OQOV+kNi8t^4i5UlH|5`76?A)ld$qZ<=NBRYN=%$7{aVAinou;l>`Dw9jfKYNZ>; z*Xq&z2;)>5_UWWJzAJU@A>WLfd;7g+Ga@zbWnB=f@a0Q+&;CWXD<64(d;4npO{b*8 ziapXcWry+`a-6b#fB6|V#yXvUbj|%TeJ?hI zDjg7uV(>ZT7{Pcf<$I4liE+x%A*)35z>N2+H(6V&OTaDglSu_PJ1Onujo95G-~~*$ zkN`;X6npID4mx9e!lydV6ih6m)#bN00Jx!-5d$D97K&EWe@ zUq|{$E5A>ZFF5p|-y?iK-7=maMh3p01|3v6uw5fQivG{^fmd-+%i;5fxZ%32M~EHg zyM2`rC{pfF z>T=y@k8PP{fVgSS^SA~;d?3Cr@EwTr@Q<4MZdCrsWh~-#pZ#Xz5xY<>yUnwIcKz{T zIrygjs(jPwhfbe#`XNKexo-5oY<5TY%SXLZzSw#>pf14=n|+h=L*IW%#Ve}z%z6YL ze2&qK+os)5sUEbKNadF!`~b}*Hxx#CF&+>Wh~;f z3O41l=Q;al#6{#q{^PKZD>W>%f4^C@?Z!CNx=^twH1En4;3*`%JC;Y!!8IVphtmI_@l32kUxY=f_Z_}J)8`dXpZ*YcD&fdRgDx1HM|7<$wbt&^A$|~A(clrbua639ri~*L%O!1Ce zChbypNb5!0q{V{m; zgFexkS@%&|t-!Im9^SE9CD$ss=#xq9cZAjR!|*4f;ZlVCvBWdc6LfGMgf3o1db;Il_9+d>eJ} z{S|%8tVv=ysK;&iLk$Bjmu;=iervz-L9Cu_BgN_YO>0l7+qJbci44a)bDFfkno)~+ zDOpY8=j`!Hp7NVl>U60$1NO&zP8HanYmD^y{>a(?YF_u*gEhC=n3E+8K#bp@=X!*F zl`VU3^%4HfRpHlp*{B2cXtr&wnj2ce-rx}v=9N68CCzI~DJwJi(%nXVSEsAL;;y9+ ztKHZLaX~z)=d7{fvtW|60B^X{g4t>uqu(mmdyBX1cIQ97b4O||H^NVmF~lk1h`q%- z)>P`@{Z<*ydDF0mSa(T_0m?Qrle=GmqsnewTxalhHq*UhtHwt!GJ6!AZ z9efQB!q*USz^yiiYRy+ekHu|J9*PT^GQ2FnUT>ncm~hzSr|$KdmSH1%u%)*!72QN)OC=wbncR;5S-0XMX-p8hz4# z!F4~_>-?cL#$bXa9*Pj>iKT(>ePL;Y75`U{SVC=y6dY`BVKeu+u=a0URy_6oE zwXWx_wGKz$ZY}XIDCBV?v#iVhC482pgdt20X+W!stH`ITRnPbI$?&RAIrzFjS z?_Md>V|!i64^Hea;k(!Xx>SMx=HJIHGu`ynAK;Id*I`q7nT8{W_o&vvZx`C{P4EUj zLi^3i(SEb=F7>BfOvFv6Dbc$ercDYmPncc?+`sR9pY+waef=5mVCJdR!mGsRmi6kF zvaaWf{0E><>QtwTe?X(Yom{Pk^)YK2Gq`x8q`A4jhrj;zxt^upQ4#nU(E*FjPINCa z9_jSN^xGcQ?~M1sn>O$J4A!;A5sy)6oQAWLrs1~gIXv?I={S-pAc|x|kvhMP>1b_8 zVek5kCn2sZ!Lwl(s6~*(FUl;O6f38}QIN}D85cqLn&r;Lqr&S)(1d>O6!iT@{XW0Mb z-Zu9{xxdTL??Z@V&U7J20myq0?yvJY`a$tLzk@b^?~lKQ(D%s(5(4Q4af387eC~)N zeUtc|1BAXvJs@F_&JgacGar8|5BMGTf2)C$Vi&O3g#y2u^C2N2SHR2h488^r;n#8t zzC*X+6LJn522bGk@)XF_O z;qeUTjtw6^{5$ZS{7fGW`u~vQ1333t;7zyzUWvQ#4f+Mwc|uTw{`wz&$Gz{Getv$( ziJuQ25&9)%!Y?Be-=Bj2%Ms|k#nI960rZs%7cSg{-^^`Xb7j+}P4|Goe-qcaL;ltn zgWs|Izi8XG?K0Rt6C43>S$VJyJTDiVot?Ar+^aZ0aM-Y6%iw==9iK;nFJ>>~LF2}a z@9o^VGa27igZwS~(_;87>ok2e+C%&y<`DXLu}JI z)t-?ayH3}+`!v(o9$A0?THSX@pif0V!@6sP)@+IMdoAXCiv8o>*eAYD3|78FaxH>! z%Uy%920F`SntJNO<|8o6D^0%yw)gUjFj+bsmH5g zFTM!g!5O#zsi(i%yDo>d9L9Fm8#`WH764av^9J$Ue>4&M?zykc=FFUqVf+GqbJ>nF zle}jweb^#71?%u@rRCzaQij+8So>0Y(A>Ml9&}M#cli|SNp%KB08?n1blkZ_x&vPe zIHVGE{>W}%?JB>HoR2i6^>yOj*>(S{&5Q}nXRY|tcXo=n#Z6IIR=&w8&#Dg`bB`DX zv^`^%iHXhqZ?0)I89zK0`^S5^&%wPKg?);>r`}hOZ^54NtJ{D>f<^Xc=W|XR>>Rt` zXP;@Q;u0IL_JxV1RHI|q(a!@1?@{tJ+xXeQ4Mkkc5MYLJPc)SHfF02pk9eYR--zp> zFdc@fef5&S2(}pBe;#5#erbuAC*s_y{bmE+W%$*Dk2;<|{_@_xL&7I`z6r0LSj9~S z#@%-qj`y#TiP#h5z9ujldxv5_Hb82Po2KtQac#)BKF649tdUv{pCCSSXW-o}LHQl% z_@errW!R#M(eUh*QaZIJMTw^=|Cv+TuFD^6W8*H9{8wu~x_RQmnhHHEXrb!gY$tz*xfj!;}PIOwW^+3zti~v{io)2fPii?HChg zm9n~D_UGf-+$Yxe$*@1>7_;yJF}s|iXJaoi;n&i^tH#;Ht=s0c`*apD2Z%e-1lS|Q z-Qc=&_O+gBvHDt7ouMPeaZJq9s)7AB6}1nJM;vAr_g!r9j#GEqlHBS*AJU3Ps}W*Ft9A*Lio=r+pigg(y%NkKbNqF?QqcS0FE=`@ zKa91lbn%|I^J?S$_qVBacwoAyHEgW^I-K}L?S(YmW5~nWeQIBm>%PRD;hHJ2Hn8UY zTXE;+r>eB|l~OKF@LTI6WqXa=uQeVpT(h4P0!*Qo{274*wcG33V`+Z*zIgxgMC}m} z3qfDQ)$u^M7eHJf?#B=x%o12Y=BxK&-E%YI-Ipu;Ct{=$8)vI6HNr89YnEJpDpbQ}iB_^+0x%}9C+BIK^ZCHeX~?}0u00yp zwbeQ#_89m*_Z3tgus`K|=B`=;=AIO>aNzf++9h!^*(SM%#_^fs6`xqyG;P6s0c8j5FA=+p>(E?BZwlN(i?kyOi-~Ku zoC~mDB1SL$7mL~eXT-7n4y}^gMBwVgYbEP49~E+a{x8p*sk3n{lSi(vDLdTDJnwbk z+A`NwD-h$i8vbfKq{Zs};<;j<*su8ZS)&zu9@U$lrpkbrAM`I#&$soum)AUWtX8|z z810*u3zq%Kev$2f@z$UDw9P7D-)F9dmu$@fxMKA~M`*P>zjl6vwb4S@ z130A00Q!5TEmN`XwY&J=`Kp=2)z1+Z&iL@^?YyNyXrMGj{IKhk5d#08EMh-f%uH5( zHXNf1H;Y)W`L5}sc`OXa9^(MyqZ{JdUut_f%L47-W2_7A@kKpwpEXXb5o=D&G_D_W zE%W*FI|^|coa2V_`3ig59^)W=IzQ<=ajn+nTsN)5VQ`-8=#6{?YaYpO#?>=q2C>2g zn%&Keao@V}31i*g`25-9#5W~g%qC2|ULtHxFxHAXBHpu$)&uKyUC#O0g_R=PVGU z5gYkIB_CJMl8x&Otl(lDhw@KC`Nvof?-OD-DY^mTAOF%buv8Fc1WM=Xu1Gu=oXeAeFStZu6t0U Date: Mon, 12 Jan 2015 17:13:06 +0100 Subject: [PATCH 055/174] Update translation template file. --- locale/openscad.pot | 718 ++++++++++++++++++++++++++++---------------- 1 file changed, 455 insertions(+), 263 deletions(-) diff --git a/locale/openscad.pot b/locale/openscad.pot index b3587cc0..497a471e 100644 --- a/locale/openscad.pot +++ b/locale/openscad.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: OpenSCAD 2014.12.22\n" +"Project-Id-Version: OpenSCAD 2015.01.12\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:37+0100\n" +"POT-Creation-Date: 2015-01-12 17:12+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,73 +17,11 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "" -#: objects/ui_FontListDialog.h:102 -msgid "OpenSCAD Font List" -msgstr "" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

This list shows the fonts currently registered with " -"OpenSCAD.

Example:

  text(t = "
-""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
-""Liberation Sans:style=Italic");
" -msgstr "" - -#: objects/ui_launchingscreen.h:276 -msgid "Welcome to OpenSCAD" -msgstr "" - -#: objects/ui_launchingscreen.h:277 -msgid "New" -msgstr "" - -#: objects/ui_launchingscreen.h:278 -msgid "Open" -msgstr "" - -#: objects/ui_launchingscreen.h:279 -msgid "Help" -msgstr "" - -#: objects/ui_launchingscreen.h:280 -msgid "Recents" -msgstr "" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "" - -#: objects/ui_launchingscreen.h:285 -msgid "Open Example" -msgstr "" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

This list shows the fonts currently registered with " +"OpenSCAD.

Example:

  text(t = "
+""OpenSCAD", font = "DejaVu Sans");
  text(t = "OpenSCAD", font = "
+""Liberation Sans:style=Italic");
" +msgstr "" + #: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "" + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:973 +msgid "Examples" +msgstr "" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "" @@ -109,546 +117,566 @@ msgstr "" msgid "OpenSCAD Detailed Library and Build Information" msgstr "" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:843 msgid "&New" msgstr "" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+N" msgstr "" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:845 msgid "&Open..." msgstr "" -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+O" msgstr "" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:847 msgid "&Save" msgstr "" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+S" msgstr "" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:849 msgid "Save &As..." msgstr "" -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Shift+S" msgstr "" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:851 msgid "&Reload" msgstr "" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+R" msgstr "" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:853 msgid "&Quit" msgstr "" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+Q" msgstr "" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:855 msgid "&Undo" msgstr "" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+Z" msgstr "" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:857 msgid "&Redo" msgstr "" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+Shift+Z" msgstr "" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:859 msgid "Cu&t" msgstr "" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+X" msgstr "" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:861 msgid "&Copy" msgstr "" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+C" msgstr "" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:863 msgid "&Paste" msgstr "" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+V" msgstr "" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:865 msgid "&Indent" msgstr "" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+I" msgstr "" -#: objects/ui_MainWindow.h:755 +#: objects/ui_MainWindow.h:867 msgid "U&nindent" msgstr "" -#: objects/ui_MainWindow.h:756 +#: objects/ui_MainWindow.h:868 msgid "Ctrl+Shift+I" msgstr "" -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:869 msgid "C&omment" msgstr "" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:870 msgid "Ctrl+D" msgstr "" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:871 msgid "Unco&mment" msgstr "" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+Shift+D" msgstr "" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:873 msgid "Paste viewport translation" msgstr "" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:874 msgid "Ctrl+T" msgstr "" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:875 msgid "Paste viewport rotation" msgstr "" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:876 objects/ui_MainWindow.h:955 msgid "Zoom In" msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:877 msgid "Ctrl++" msgstr "" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:878 objects/ui_MainWindow.h:957 msgid "Zoom Out" msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:879 msgid "Ctrl+-" msgstr "" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:880 msgid "Hide editor" msgstr "" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:881 msgid "&Reload and Preview" msgstr "" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:882 msgid "F4" msgstr "" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:883 msgid "&Preview" msgstr "" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:884 msgid "F5" msgstr "" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:885 msgid "&Render" msgstr "" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:886 msgid "F6" msgstr "" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:887 msgid "Check Validity" msgstr "" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:888 msgid "Display &AST..." msgstr "" -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:889 msgid "Display CSG &Tree..." msgstr "" -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:890 msgid "Display CSG &Products..." msgstr "" -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:891 msgid "Export as &STL..." msgstr "" -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:892 msgid "Export as &OFF..." msgstr "" -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:893 msgid "Preview" msgstr "" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:894 msgid "F9" msgstr "" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:895 msgid "Surfaces" msgstr "" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:896 msgid "F10" msgstr "" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:897 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:898 msgid "F11" msgstr "" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:899 msgid "Thrown Together" msgstr "" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:900 msgid "F12" msgstr "" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:901 msgid "Show Edges" msgstr "" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+1" msgstr "" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:903 msgid "Show Axes" msgstr "" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+2" msgstr "" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:905 msgid "Show Crosshairs" msgstr "" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+3" msgstr "" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:907 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:908 msgid "Animate" msgstr "" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:909 msgid "Top" msgstr "" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+4" msgstr "" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:911 msgid "Bottom" msgstr "" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+5" msgstr "" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:913 msgid "Left" msgstr "" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+6" msgstr "" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:915 msgid "Right" msgstr "" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:916 msgid "Ctrl+7" msgstr "" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:917 msgid "Front" msgstr "" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:918 msgid "Ctrl+8" msgstr "" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:919 msgid "Back" msgstr "" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:920 msgid "Ctrl+9" msgstr "" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:921 msgid "Diagonal" msgstr "" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:922 msgid "Ctrl+0" msgstr "" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:923 msgid "Center" msgstr "" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:924 msgid "Perspective" msgstr "" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:925 msgid "Orthogonal" msgstr "" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:926 msgid "Hide console" msgstr "" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:927 msgid "About" msgstr "" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:928 msgid "Documentation" msgstr "" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:929 msgid "Clear Recent" msgstr "" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:930 msgid "Export as DXF..." msgstr "" -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:931 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+W" msgstr "" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:933 objects/ui_Preferences.h:1053 msgid "Preferences" msgstr "" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:934 msgid "Find..." msgstr "" -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+F" msgstr "" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:936 msgid "Find and Replace..." msgstr "" -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:937 msgid "Ctrl+Alt+F" msgstr "" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:938 msgid "Find Next" msgstr "" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:939 msgid "Ctrl+G" msgstr "" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:940 msgid "Find Previous" msgstr "" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:941 msgid "Ctrl+Shift+G" msgstr "" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:942 msgid "Use Selection for Find" msgstr "" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:943 msgid "Ctrl+E" msgstr "" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:944 msgid "Flush Caches" msgstr "" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:945 msgid "OpenSCAD Homepage" msgstr "" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:946 msgid "Automatic Reload and Preview" msgstr "" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:947 msgid "Export as Image..." msgstr "" -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:948 msgid "Export as CSG..." msgstr "" -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:949 msgid "Library info" msgstr "" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:950 msgid "Show Library Folder..." msgstr "" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:951 msgid "Reset View" msgstr "" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:952 msgid "Font List" msgstr "" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:953 msgid "Export as SVG..." msgstr "" -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:954 msgid "Export as AMF..." msgstr "" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:956 msgid "Ctrl+]" msgstr "" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:958 msgid "Ctrl+[" msgstr "" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:959 msgid "View All" msgstr "" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:960 msgid "Convert Tabs to Spaces" msgstr "" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:961 msgid "Hide toolbars" msgstr "" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:962 +msgid "Hide parameters" +msgstr "" + +#: objects/ui_MainWindow.h:963 +msgid "Hide library" +msgstr "" + +#: objects/ui_MainWindow.h:965 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:967 msgid "Time:" msgstr "" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:968 msgid "FPS:" msgstr "" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:969 msgid "Steps:" msgstr "" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:970 msgid "Dump Pictures" msgstr "" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:971 msgid "&File" msgstr "" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:972 msgid "Recent Files" msgstr "" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:974 msgid "Export" msgstr "" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:975 msgid "&Edit" msgstr "" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:976 msgid "&Design" msgstr "" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:977 msgid "&View" msgstr "" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:978 msgid "&Help" msgstr "" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:981 msgid "Find" msgstr "" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:982 objects/ui_MainWindow.h:989 msgid "Replace" msgstr "" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:984 msgid "Search string" msgstr "" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:985 msgid "<" msgstr "" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:986 msgid ">" msgstr "" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:987 msgid "Done" msgstr "" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:988 msgid "Replacement string" msgstr "" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:990 msgid "All" msgstr "" +#: objects/ui_MainWindow.h:991 +msgid "Libraries" +msgstr "" + #: objects/ui_OpenCSGWarningDialog.h:86 msgid "OpenGL Warning" msgstr "" @@ -675,135 +703,273 @@ msgstr "" msgid "Show this message again" msgstr "" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1054 msgid "3D View" msgstr "" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1055 src/UIUtils.cc:85 msgid "Advanced" msgstr "" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1056 src/mainwin.cc:2410 msgid "Editor" msgstr "" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1057 msgid "Update" msgstr "" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1058 objects/ui_Preferences.h:1138 msgid "Features" msgstr "" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1060 msgid "Enable/Disable experimental features" msgstr "" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1062 msgid "Color scheme:" msgstr "" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1063 msgid "Editor Type" msgstr "" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1066 msgid "Simple Editor" msgstr "" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1067 msgid "QScintilla Editor" msgstr "" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1069 msgid "(requires restart)" msgstr "" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1070 msgid "Font" msgstr "" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1071 msgid "Color syntax highlighting" msgstr "" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1072 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1073 +msgid "Indentation" +msgstr "" + +#: objects/ui_Preferences.h:1074 +msgid "Auto Indent" +msgstr "" + +#: objects/ui_Preferences.h:1075 +msgid "Indent using" +msgstr "" + +#: objects/ui_Preferences.h:1078 src/settings.cc:134 +msgid "Spaces" +msgstr "" + +#: objects/ui_Preferences.h:1079 src/settings.cc:134 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1081 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1082 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1083 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1086 objects/ui_Preferences.h:1116 +#: src/settings.cc:135 +msgid "Indent" +msgstr "" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1089 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1092 src/settings.cc:131 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1093 src/settings.cc:131 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1094 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1096 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1097 +msgid "Display" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1099 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1100 objects/ui_Preferences.h:1133 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1103 objects/ui_Preferences.h:1120 +#: objects/ui_Preferences.h:1128 src/settings.cc:126 src/settings.cc:129 +#: src/settings.cc:130 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1104 src/settings.cc:126 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1105 src/settings.cc:126 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1107 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1109 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1112 src/settings.cc:127 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Indented" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1121 objects/ui_Preferences.h:1129 +#: src/settings.cc:129 src/settings.cc:130 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1122 objects/ui_Preferences.h:1130 +#: src/settings.cc:129 src/settings.cc:130 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1123 objects/ui_Preferences.h:1131 +#: src/settings.cc:129 src/settings.cc:130 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1125 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1134 msgid "Automatically check for updates" msgstr "" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1135 msgid "Include development snapshots" msgstr "" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1136 msgid "Check Now" msgstr "" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1137 msgid "Last checked: " msgstr "" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1139 msgid "OpenCSG" msgstr "" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1140 msgid "Show capability warning" msgstr "" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1141 msgid "Enable for OpenGL 1.x" msgstr "" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1142 msgid "Turn off rendering at " msgstr "" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1143 msgid "elements" msgstr "" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1144 msgid "Force Goldfeather" msgstr "" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1145 msgid "CGAL Cache size" msgstr "" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1146 objects/ui_Preferences.h:1148 msgid "bytes" msgstr "" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1147 msgid "PolySet Cache size" msgstr "" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1149 msgid "Allow to open multiple documents" msgstr "" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1150 msgid "Enable docking of Editor and Console in different places" msgstr "" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1151 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1152 msgid "Show Welcome Screen" msgstr "" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1153 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1154 msgid "toolBar" msgstr "" @@ -815,110 +981,139 @@ msgstr "" msgid "%v / %m" msgstr "" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:129 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" + +#: src/mainwin.cc:787 src/mainwin.cc:1351 msgid "Untitled.scad" msgstr "" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:975 +msgid "Compile error." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:982 +msgid "Compilation generated %1 warnings." +msgstr "" + +#: src/mainwin.cc:985 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1350 msgid "Save File" msgstr "" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1352 msgid "OpenSCAD Designs (*.scad)" msgstr "" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1362 msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1681 msgid "Application" msgstr "" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1682 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2029 src/mainwin.cc:2086 msgid "Export %1 File" msgstr "" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2030 src/mainwin.cc:2090 msgid "%1 Files (*%2)" msgstr "" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2031 msgid "Untitled" msgstr "" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2088 msgid "Untitled%1" msgstr "" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2139 msgid "Export CSG File" msgstr "" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2140 msgid "Untitled.csg" msgstr "" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2141 msgid "CSG Files (*.csg)" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2167 msgid "Export Image" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2167 msgid "PNG Files (*.png)" msgstr "" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2415 msgid "Console" msgstr "" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2547 msgid "The document has been modified." msgstr "" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2548 msgid "Do you want to save your changes?" msgstr "" -#: src/QGLView.cc:114 +#: src/openscad.cc:602 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" "\n" msgstr "" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -926,11 +1121,8 @@ msgid "" "OpenGL version %s\n" msgstr "" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:131 +msgid "After indentation" msgstr "" #: src/UIUtils.cc:85 From 7b33e9eb677594b1a981e648937520443a6456d8 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Mon, 12 Jan 2015 17:31:14 +0100 Subject: [PATCH 056/174] Highlight export warnings in console window. --- src/mainwin.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mainwin.cc b/src/mainwin.cc index d70f91af..a9a81874 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1988,7 +1988,7 @@ void MainWindow::actionExport(export_type_e, QString, QString) setCurrentOutput(); if (!this->root_geom) { - PRINT("Nothing to export! Try building first (press F6)."); + PRINT("WARNING: Nothing to export! Try building first (press F6)."); clearCurrentOutput(); return; } @@ -2068,13 +2068,13 @@ QString MainWindow::get2dExportFilename(QString format, QString extension) { setCurrentOutput(); if (!this->root_geom) { - PRINT("Nothing to export! Try building first (press F6)."); + PRINT("WARNING: Nothing to export! Try building first (press F6)."); clearCurrentOutput(); return QString(); } if (this->root_geom->getDimension() != 2) { - PRINT("Current top level object is not a 2D object."); + PRINT("WARNING: Current top level object is not a 2D object."); clearCurrentOutput(); return QString(); } @@ -2127,7 +2127,7 @@ void MainWindow::actionExportCSG() setCurrentOutput(); if (!this->root_node) { - PRINT("Nothing to export. Please try compiling first..."); + PRINT("WARNING: Nothing to export. Please try compiling first..."); clearCurrentOutput(); return; } From 47254dd021bc86d6c6fead5a0f0ba54814d8e933 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Mon, 12 Jan 2015 17:31:43 +0100 Subject: [PATCH 057/174] Update STL export icons. --- images/export-white.png | Bin 425 -> 529 bytes images/export.png | Bin 500 -> 503 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/export-white.png b/images/export-white.png index 9aeeade8c11446e104d349aa56d47c5485a63de9..f89a27b30d9a58487fc99214942190ad6f1e76ab 100644 GIT binary patch delta 504 zcmVj{7c5 z00057NklW zVr40flGK%G+&^GaR)$$%8j@pk7T0utJdb(0Bi&Qq`gWf4oPX#2JkRHx@2N$Em9!Bn zY(sz{z-Y<%8gAf7kC-`J$CE+{OO#;^mv90vdc^I_7n{J3zF8xp=sF(}t%!KpCvGz1 z#){-Es(~{&o%`>7Vt-XF!cz&LAV8&6a1s}m_`VDZ;1Di%@INk?du};ZFp4HVV6wyY zW@VqCi#qEOF@F;g;}J0u5mWJ}%}2!1h}aapZAU~*=l*`DXBBBg$5RUnxP^n*iz#fz zvy9u04fuq2>HAhiCtTB}{`a`prk&3?ko!jo+r;52%kTkSVIA(^IqqR>P>0b1#&Ha{ zF^jDUwq+0iS22w}IGa5l>Lmd-=DibbISOfD7FVzz4RNeZ|3|zj0no_Rez+9^xQlJs zl6R-?X^OF3gTGd4}t)f-Z?HBySJa*w)NvM5T#Mk9c uM2$QLR+j`=#7#V`dL$c;C> delta 400 zcmV;B0dM}11gQg%BYy#KNklF;2rU7=`U9N+YK`8(e~!NSvYr0|OI6%!nN^ zcSLH%RJ_5`p2*u_zt__0t4Mbu5&rUS~i#d-4o{^!^+AvHBMYcLoL zoH&j-ENHFYgb=M&bJ4QJhr^*0hT&bK(Kt<#EyHC<=!NSED5`jF2KOL{N~}TyxN-P9{VcP7Tr2 z65r2yOx0EqyK1h|EqlPCIR<;qbx+9^(oI1F9GEk=Kvo_<^qxTW?o91>kVT{Yx0n zcxMHdV?GzKHC!w58ot119Kkbuz)WhRDFR?4yl@jw(ZJ~dJGCDG55h?2aW8uOwo&r{ zoQSnUnHotRXkZeTP(@F~zvD{|fNG4tT0jcGbM!?^K35m9w_(Pt%j-BA*Eg$$PWr%; zy>2*N9j-sPgJ+U|$CVcG`2c*M6Y4_rj*Hmrp0Q#9v UE-8f9P5=M^07*qoM6N<$g0Ldm?*IS* delta 475 zcmV<10VMwS1M~xsBYy$ANklv2WTy6vp2@4qU9TRqEIo-G;$zLCVs90ih06 zgJdBOR7(AAK7Z%; zd+**^4)v^Ht}Y z&*w!#NTyIIJn3{gQ!QvzfPTOKK}uOi#K~YVc&76)#y%>gUV5JQ7yy3id>AEou~>X3 zgm?`AkV>VlZ?Okqz8M;zR4Tm@LL4uj7mLNOT{K}R0Nb_?r_<^Cm5qp#djTky%g;T} zJ6T^(r_)C9oi0%mD zu0T7V&p*`#j}72=z%~HXV?BbfW!}lJI4(U5fLg6)##C|*bGh7%5ORr#`<7*Ob-wX< z43=fBtogowpp=@Krg^p1L}c4`RS0n&1i@aUS&xueHk& Date: Mon, 12 Jan 2015 17:48:24 +0100 Subject: [PATCH 058/174] Always set both height and viewer_distance (fixes #1153). The only exception is the initialization in the Constructor which seems to matter for the test suite where the Camera is initialized with type NONE. This still needs some investigation as unifying both variables into a single one does break tests on Travis (but not locally). --- src/Camera.cc | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Camera.cc b/src/Camera.cc index 7e53d363..a386aef6 100644 --- a/src/Camera.cc +++ b/src/Camera.cc @@ -26,8 +26,7 @@ void Camera::setup(std::vector params) type = Camera::GIMBAL; object_trans << params[0], params[1], params[2]; object_rot << params[3], params[4], params[5]; - viewer_distance = params[6]; - height = params[6]; + height = viewer_distance = params[6]; } else if (params.size() == 6) { type = Camera::VECTOR; eye << params[0], params[1], params[2]; @@ -74,13 +73,13 @@ void Camera::viewAll(const BoundingBox &bbox, float scalefactor) switch (this->projection) { case Camera::ORTHOGONAL: - this->height = bbox.diagonal().norm(); + this->height = this->viewer_distance = bbox.diagonal().norm(); break; case Camera::PERSPECTIVE: { double radius = bbox.diagonal().norm()/2; switch (this->type) { case Camera::GIMBAL: - this->viewer_distance = radius / tan(this->fov*M_PI/360); + this->height = this->viewer_distance = radius / tan(this->fov*M_PI/360); break; case Camera::VECTOR: { Vector3d cameradir = (this->center - this->eye).normalized(); @@ -101,8 +100,7 @@ void Camera::viewAll(const BoundingBox &bbox, float scalefactor) void Camera::zoom(int delta) { - this->viewer_distance *= pow(0.9, delta / 120.0); - this->height = this->viewer_distance; + this->height = this->viewer_distance *= pow(0.9, delta / 120.0); } void Camera::setProjection(ProjectionType type) @@ -115,8 +113,7 @@ void Camera::resetView() type = Camera::GIMBAL; object_rot << 35, 0, -25; object_trans << 0, 0, 0; - height = 140; - viewer_distance = 140; + height = viewer_distance = 140; } double Camera::zoomValue() From 366663610f57e7d705dffadeb80110eea03385b9 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Tue, 13 Jan 2015 02:26:12 +0100 Subject: [PATCH 059/174] Clarify editor zoom to be font size change and add proper icons. --- images/zoom-text-in-white.png | Bin 0 -> 581 bytes images/zoom-text-in.png | Bin 0 -> 530 bytes images/zoom-text-out-white.png | Bin 0 -> 582 bytes images/zoom-text-out.png | Bin 0 -> 535 bytes openscad.qrc | 4 ++++ src/MainWindow.ui | 12 ++++++------ src/mainwin.cc | 10 +++++----- 7 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 images/zoom-text-in-white.png create mode 100644 images/zoom-text-in.png create mode 100644 images/zoom-text-out-white.png create mode 100644 images/zoom-text-out.png diff --git a/images/zoom-text-in-white.png b/images/zoom-text-in-white.png new file mode 100644 index 0000000000000000000000000000000000000000..2be2fafe43ee9aa10c340aecd28c5983f36da8f8 GIT binary patch literal 581 zcmV-L0=oT)P)%W70X5Qe|b7@|>d z5EqdwL@{1Kw}K#udvOu)78eTR?EzfsN?$;5tDD3JaFvasC?SGz9v~oQ;Rw1=#49R( zZb}#qbI$Zk$dJX<=5$y8U0wB8b@hRvtY=YO>oZ0w4xfqdwY7901n%YwTs1t4a?dmV}y*k>D;hpMlb*c;QL{L57VeMh8P4|<6E5I}0Y8PKG6)0!b zX;4R_8}1Ey$4YP$!O|CXyi;#bKSg>bdtqQ2SV$=?15bccCAf>g24D;Dtwa0%3DkjF zV6z!`sveE;VfA?lZrOZ!t)`sA52&vSx<&P1L3b<+x71pNy%BXKu*Y*8xKk3r-2!el z^tUr?-VE$qH{iJXLETo+Z;kuBIp%fsdvw2D84gTFA^uS7RYiCXc$rfASa^Uw1ByGz4R6vls5OQ8xD zaj0|<#V6=02!gnaL-9oy3sn$Z9d%MS7r|AR>aIu;1W^#tLHh?3gbr5F#la^k*5w;Q zXwoFm(4hw|x%Zs!o>$H}3Dl^{saRzxxMez_^^y zpaDPZH3L@B&N$GwU~o3&wFZhFYbFFd0(s%Ofi~dHjRQ`+-nHqP17KBp*QIaIuev!? z_IiOX?XUbY-U<8xSp)AzPV{*lL~bahw5JWcv|lY;4-|l3AZp;Z0^h(B5cHzB9r#f- z+tIjEeNsYpBw5^x1Dh(WtunYn8A+6oO-hz=YdolF*rW7@EO1d}=@kfD%!U`eo|u~= zjH`umz&S8wflC4nKojs@VtjuA5!Ff3O$IK25$%V7OAB1Cgi)(?@ARwM58Rn}*T8^@ zH!8&iMQGRRd11$#IIwLI!Hx-+7JtKm&NX58%K^i{Gtgq;l;b&dcZntmM)9Ehn9 zKXuo3qGfE_ZC?9jMRe+-u8wtQ$qsZ2%vs20B}X&A2u!J!=$E6o#LhHAJJ} z5>iA`h+_NzZ3RIPd$EWZqA3(MD*gyNe}ICm)mjTyX(9$CL@@3T2#6_MK?_CvM8(JE zi0d%BJG1VB;Jz@-%(?G9_uTiKd$=&f|Blpehia|sqAA@TSO5`(9Txv%&5;2qy9hLM z?DM_u=!m~@tl*p%W{}4#s=y`SmxEftIX7}tDPM%@81NF<4E_wTE2Z?IOf6({Uq*p5 zzyxqNo*lqkK@}F_ef4iD`hKMFfVwZfSNm}yicH?C{!kk&w#N~~!G0W&4 zddXt!dG{5yseV_dTI`eRSM`-TI>-P{h15$qWA|cgwu_J5>Nj3YRd7kq8^X$qw1rgi=PO`O|{a2H==F^_he@5koq)ZTT>4g37{TMuNUB6 z3+|na{bn1rZgq25RX;`d+fyKb=_tg{YBg-*>T7i(!`&IZV|%9}TmZHK%PFPj1+G?2 zUB$A6~_W7~-G8Py2r7 U@UUFNmH+?%07*qoM6N<$f@!M&cK`qY literal 0 HcmV?d00001 diff --git a/images/zoom-text-out.png b/images/zoom-text-out.png new file mode 100644 index 0000000000000000000000000000000000000000..db745e9bab983e54db167318d9269bd72fa9424c GIT binary patch literal 535 zcmV+y0_gpTP) zgW(WGpHOQM1koN1Rw6YdXhZckwAI#7(As2k6d^$n1rarre}E7;WKc^(pHyVa6I|q8 zeXl75`M|}?`FP&*9-nhA)bQWosRC!*AZDwY1pwqtFYT>T0SO>yV~>_gIH+6Yfnmd( z8%s{!sVk-(n70tb4Rh9Qx>A-1{lG1dReU$l20Xdcf~VXLOad*yj-DnUV%UXQ{Vx1Q zP)E8+FVLm;vkFZ_Npu2VK-yxv5NTf}#>H!}R6Ib^VoSOdW7(+FEPnz)i@gA7~;awouu-iLrw)5Awa zoYM`9jc``6V+Fo`;HtoO4h)zSkQC{PLF}?(w+rkW4&B-;MHm2HwEa2^3J6JvugXQD zz1R1{ie~MO#$tp^s`Su>UiOu + images/zoom-text-in-white.png + images/zoom-text-in.png + images/zoom-text-out-white.png + images/zoom-text-out.png images/Command-Redo-32-white.png images/Command-Reset-32-white.png images/Command-Undo-32-white.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 4762dc06..927c38bf 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -317,8 +317,8 @@ - - + + @@ -714,17 +714,17 @@ Paste viewport rotation - + - Zoom In + Increase Font Size Ctrl++ - + - Zoom Out + Decrease Font Size Ctrl+- diff --git a/src/mainwin.cc b/src/mainwin.cc index a9a81874..214206c2 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -256,7 +256,7 @@ MainWindow::MainWindow(const QString &filename) knownFileExtensions["scad"] = ""; knownFileExtensions["csg"] = ""; - editActionZoomIn->setShortcuts(QList() << editActionZoomIn->shortcuts() << QKeySequence("CTRL+=")); + editActionZoomTextIn->setShortcuts(QList() << editActionZoomTextIn->shortcuts() << QKeySequence("CTRL+=")); connect(this, SIGNAL(highlightError(int)), editor, SLOT(highlightError(int))); connect(this, SIGNAL(unhighlightLastError()), editor, SLOT(unhighlightLastError())); @@ -330,8 +330,8 @@ MainWindow::MainWindow(const QString &filename) connect(this->editActionConvertTabsToSpaces, SIGNAL(triggered()), this, SLOT(convertTabsToSpaces())); connect(this->editActionPasteVPT, SIGNAL(triggered()), this, SLOT(pasteViewportTranslation())); connect(this->editActionPasteVPR, SIGNAL(triggered()), this, SLOT(pasteViewportRotation())); - connect(this->editActionZoomIn, SIGNAL(triggered()), editor, SLOT(zoomIn())); - connect(this->editActionZoomOut, SIGNAL(triggered()), editor, SLOT(zoomOut())); + connect(this->editActionZoomTextIn, SIGNAL(triggered()), editor, SLOT(zoomIn())); + connect(this->editActionZoomTextOut, SIGNAL(triggered()), editor, SLOT(zoomOut())); connect(this->editActionPreferences, SIGNAL(triggered()), this, SLOT(preferences())); // Edit->Find connect(this->editActionFind, SIGNAL(triggered()), this, SLOT(find())); @@ -476,8 +476,8 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(fileActionNew, ":/images/blackNew.png", ":/images/Document-New-128.png"); initActionIcon(fileActionOpen, ":/images/Open-32.png", ":/images/Open-128.png"); initActionIcon(fileActionSave, ":/images/Save-32.png", ":/images/Save-128.png"); - initActionIcon(editActionZoomIn, ":/images/zoomin.png", ":/images/Zoom-In-32.png"); - initActionIcon(editActionZoomOut, ":/images/zoomout.png", ":/images/Zoom-Out-32.png"); + initActionIcon(editActionZoomTextIn, ":/images/zoom-text-in.png", ":/images/zoom-text-in-white.png"); + initActionIcon(editActionZoomTextOut, ":/images/zoom-text-out.png", ":/images/zoom-text-out-white.png"); initActionIcon(designActionRender, ":/images/blackRender.png", ":/images/Arrowhead-Right-32.png"); initActionIcon(viewActionShowAxes, ":/images/blackaxes.png", ":/images/axes.png"); initActionIcon(viewActionShowEdges, ":/images/Rotation-32.png", ":/images/grid.png"); From df2dae4e59228025b9061b71c44c5c75a9d0e7eb Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 13:14:09 -0500 Subject: [PATCH 060/174] Added new tessellator using libtess2 instead of CGAL --- cgal/polyhole-tessellator-libtess2.cpp | 147 +++ cgal/polyhole-tessellator-libtess2.pro | 105 ++ openscad.pro | 20 +- src/cgalutils-tess2.cc | 87 ++ src/cgalutils.cc | 2 +- src/cgalutils.h | 6 +- src/libtess2/Include/tesselator.h | 226 ++++ src/libtess2/Source/bucketalloc.c | 191 ++++ src/libtess2/Source/bucketalloc.h | 51 + src/libtess2/Source/dict.c | 109 ++ src/libtess2/Source/dict.h | 74 ++ src/libtess2/Source/geom.c | 286 +++++ src/libtess2/Source/geom.h | 78 ++ src/libtess2/Source/mesh.c | 922 +++++++++++++++++ src/libtess2/Source/mesh.h | 269 +++++ src/libtess2/Source/priorityq.c | 514 +++++++++ src/libtess2/Source/priorityq.h | 104 ++ src/libtess2/Source/sweep.c | 1323 ++++++++++++++++++++++++ src/libtess2/Source/sweep.h | 74 ++ src/libtess2/Source/tess.c | 1085 +++++++++++++++++++ src/libtess2/Source/tess.h | 90 ++ tests/CMakeLists.txt | 13 +- 22 files changed, 5768 insertions(+), 8 deletions(-) create mode 100644 cgal/polyhole-tessellator-libtess2.cpp create mode 100644 cgal/polyhole-tessellator-libtess2.pro create mode 100644 src/cgalutils-tess2.cc create mode 100755 src/libtess2/Include/tesselator.h create mode 100755 src/libtess2/Source/bucketalloc.c create mode 100755 src/libtess2/Source/bucketalloc.h create mode 100755 src/libtess2/Source/dict.c create mode 100755 src/libtess2/Source/dict.h create mode 100755 src/libtess2/Source/geom.c create mode 100755 src/libtess2/Source/geom.h create mode 100755 src/libtess2/Source/mesh.c create mode 100755 src/libtess2/Source/mesh.h create mode 100755 src/libtess2/Source/priorityq.c create mode 100755 src/libtess2/Source/priorityq.h create mode 100755 src/libtess2/Source/sweep.c create mode 100755 src/libtess2/Source/sweep.h create mode 100755 src/libtess2/Source/tess.c create mode 100755 src/libtess2/Source/tess.h diff --git a/cgal/polyhole-tessellator-libtess2.cpp b/cgal/polyhole-tessellator-libtess2.cpp new file mode 100644 index 00000000..f157f586 --- /dev/null +++ b/cgal/polyhole-tessellator-libtess2.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include + +#include "cgalutils.h" +#include "linalg.h" + +#include +typedef CGAL::Epick K; +typedef CGAL::Point_3 Vertex3K; +typedef std::vector PolygonK; +typedef std::vector PolyholeK; + + +// Nef polyhedron are using CGAL_Kernel3 (Cartesian) +// Triangulation will use Epick + +static void export_stl(const Polygons &triangles, std::ostream &output) +{ + setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output + output << "solid OpenSCAD_Model\n"; + BOOST_FOREACH(const Polygon &p, triangles) { + assert(p.size() == 3); // STL only allows triangles + std::stringstream stream; + stream << p[0][0] << " " << p[0][1] << " " << p[0][2]; + std::string vs1 = stream.str(); + stream.str(""); + stream << p[1][0] << " " << p[1][1] << " " << p[1][2]; + std::string vs2 = stream.str(); + stream.str(""); + stream << p[2][0] << " " << p[2][1] << " " << p[2][2]; + std::string vs3 = stream.str(); + // if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) { + // The above condition ensures that there are 3 distinct vertices, but + // they may be collinear. If they are, the unit normal is meaningless + // so the default value of "1 0 0" can be used. If the vertices are not + // collinear then the unit normal must be calculated from the + // components. + Vector3d normal = (p[1] - p[0]).cross(p[2] - p[0]); + normal.normalize(); + output << " facet normal " << normal[0] << " " << normal[1] << " " << normal[2] << "\n"; + output << " outer loop\n"; + + BOOST_FOREACH(const Vector3d &v, p) { + output << " vertex " << v[0] << " " << v[1] << " " << v[2] << "\n"; + } + output << " endloop\n"; + output << " endfacet\n"; + // } + } + output << "endsolid OpenSCAD_Model\n"; + setlocale(LC_NUMERIC, ""); // Set default locale +} + + +/*! + file format: + 1. polygon coordinates (x,y,z) are comma separated (+/- spaces) and + each coordinate is on a separate line + 2. each polygon is separated by one or more blank lines +*/ +bool import_polygon(PolyholeK &polyhole, const std::string &filename) +{ + std::ifstream ifs(filename.c_str()); + if (!ifs) return false; + + std::string line; + PolygonK polygon; + while (std::getline(ifs, line)) { + std::stringstream ss(line); + double X = 0.0, Y = 0.0, Z = 0.0; + if (!(ss >> X)) { + //ie blank lines => flag start of next polygon + if (polygon.size() > 0) polyhole.push_back(polygon); + polygon.clear(); + continue; + } + char c = ss.peek(); + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces before comma + if (c == ',') {ss.read(&c, 1); c = ss.peek();} //gobble comma + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces after comma + if (!(ss >> Y)) { + std::cerr << "Y error\n"; + return false; + } + c = ss.peek(); + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces before comma + if (c == ',') {ss.read(&c, 1); c = ss.peek();} //gobble comma + while (c == ' ') {ss.read(&c, 1); c = ss.peek();} //gobble spaces after comma + if (!(ss >> Z)) { + std::cerr << "Z error\n"; + return false; + } + polygon.push_back(Vertex3K(X, Y, Z)); + } + if (polygon.size() > 0) polyhole.push_back(polygon); + ifs.close(); + return true; +} + +int main(int argc, char *argv[]) +{ + PolyholeK polyhole; + K::Vector_3 *normal = NULL; + if (argc >= 2) { + if (!import_polygon(polyhole, argv[1])) { + std::cerr << "Error importing polygon" << std::endl; + exit(1); + } + std::cerr << "Imported " << polyhole.size() << " polygons" << std::endl; + + if (argc == 3) { + std::vector strs; + std::vector normalvec; + std::string arg(argv[2]); + boost::split(strs, arg, boost::is_any_of(",")); + assert(strs.size() == 3); + BOOST_FOREACH(const std::string &s, strs) normalvec.push_back(boost::lexical_cast(s)); + normal = new K::Vector_3(normalvec[0], normalvec[1], normalvec[2]); + + } + } + else { + //construct two non-intersecting nested polygons + PolygonK polygon1; + polygon1.push_back(Vertex3K(0,0,0)); + polygon1.push_back(Vertex3K(2,0,0)); + polygon1.push_back(Vertex3K(2,2,0)); + polygon1.push_back(Vertex3K(0,2,0)); + PolygonK polygon2; + polygon2.push_back(Vertex3K(0.5,0.5,0)); + polygon2.push_back(Vertex3K(1.5,0.5,0)); + polygon2.push_back(Vertex3K(1.5,1.5,0)); + polygon2.push_back(Vertex3K(0.5,1.5,0)); + polyhole.push_back(polygon1); + polyhole.push_back(polygon2); + } + + Polygons triangles; + bool ok = CGALUtils::tessellatePolygonWithHolesNew(polyhole, triangles, normal); + std::cerr << "Tessellated into " << triangles.size() << " triangles" << std::endl; + + export_stl(triangles, std::cout); +} diff --git a/cgal/polyhole-tessellator-libtess2.pro b/cgal/polyhole-tessellator-libtess2.pro new file mode 100644 index 00000000..d8697f8d --- /dev/null +++ b/cgal/polyhole-tessellator-libtess2.pro @@ -0,0 +1,105 @@ +debug: DEFINES += DEBUG + +TEMPLATE = app + +INCLUDEPATH += ../src ../src/libtess2/Include +DEPENDPATH += ../src + +# Handle custom library location. +# Used when manually installing 3rd party libraries +isEmpty(OPENSCAD_LIBDIR) OPENSCAD_LIBDIR = $$(OPENSCAD_LIBRARIES) +macx:isEmpty(OPENSCAD_LIBDIR) { + exists(/opt/local):exists(/usr/local/Cellar) { + error("It seems you might have libraries in both /opt/local and /usr/local. Please specify which one to use with qmake OPENSCAD_LIBDIR=") + } else { + exists(/opt/local) { + #Default to MacPorts on Mac OS X + message("Automatically searching for libraries in /opt/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /opt/local + } else:exists(/usr/local/Cellar) { + message("Automatically searching for libraries in /usr/local. To override, use qmake OPENSCAD_LIBDIR=") + OPENSCAD_LIBDIR = /usr/local + } + } +} +!isEmpty(OPENSCAD_LIBDIR) { + QMAKE_INCDIR = $$OPENSCAD_LIBDIR/include + QMAKE_LIBDIR = $$OPENSCAD_LIBDIR/lib +} + +TARGET = polyhole-tessellator-libtess2 +mac { + CONFIG -= app_bundle +} + +macx { + # Mac needs special care to link against the correct C++ library + # We attempt to auto-detect it by inspecting Boost + dirs = $${BOOSTDIR} $${QMAKE_LIBDIR} + for(dir, dirs) { + system(grep -q __112basic_string $${dir}/libboost_thread* >& /dev/null) { + message("Detected libc++-linked boost in $${dir}") + CONFIG += libc++ + } + } + + libc++ { + QMAKE_CXXFLAGS += -stdlib=libc++ + QMAKE_LFLAGS += -stdlib=libc++ + QMAKE_OBJECTIVE_CFLAGS += -stdlib=libc++ + # libc++ on requires Mac OS X 10.7+ + QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7 + } +} + +# See Dec 2011 OpenSCAD mailing list, re: CGAL/GCC bugs. +*g++* { + QMAKE_CXXFLAGS *= -fno-strict-aliasing + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedefs # ignored before 4.8 +} + +*clang* { + # http://llvm.org/bugs/show_bug.cgi?id=9182 + QMAKE_CXXFLAGS_WARN_ON += -Wno-overloaded-virtual + # disable enormous amount of warnings about CGAL / boost / etc + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function + QMAKE_CXXFLAGS_WARN_ON += -Wno-c++11-extensions + # might want to actually turn this on once in a while + QMAKE_CXXFLAGS_WARN_ON += -Wno-format-security +} + + + +# Application configuration +CONFIG += cgal +CONFIG += boost +CONFIG += eigen +CONFIG += gettext + +include(../common.pri) + +HEADERS += ../src/cgal.h \ + ../src/cgalutils.h \ + ../src/linalg.h \ + ../src/printutils.h \ + ../src/libtess2/Include/tesselator.h \ + ../src/libtess2/Source/bucketalloc.h \ + ../src/libtess2/Source/dict.h \ + ../src/libtess2/Source/geom.h \ + ../src/libtess2/Source/mesh.h \ + ../src/libtess2/Source/priorityq.h \ + ../src/libtess2/Source/sweep.h \ + ../src/libtess2/Source/tess.h + +SOURCES += polyhole-tessellator-libtess2.cpp \ + ../src/cgalutils-tess2.cc \ + ../src/printutils.cc \ + ../src/libtess2/Source/bucketalloc.c \ + ../src/libtess2/Source/dict.c \ + ../src/libtess2/Source/geom.c \ + ../src/libtess2/Source/mesh.c \ + ../src/libtess2/Source/priorityq.c \ + ../src/libtess2/Source/sweep.c \ + ../src/libtess2/Source/tess.c diff --git a/openscad.pro b/openscad.pro index e25639f4..3327c331 100644 --- a/openscad.pro +++ b/openscad.pro @@ -441,6 +441,24 @@ SOURCES += src/version_check.cc \ SOURCES += src/polyclipping/clipper.cpp HEADERS += src/polyclipping/clipper.hpp +# libtess2 +INCLUDEPATH += src/libtess2/Include +SOURCES += src/libtess2/Source/bucketalloc.c \ + src/libtess2/Source/dict.c \ + src/libtess2/Source/geom.c \ + src/libtess2/Source/mesh.c \ + src/libtess2/Source/priorityq.c \ + src/libtess2/Source/sweep.c \ + src/libtess2/Source/tess.c +HEADERS += src/libtess2/Include/tesselator.h \ + src/libtess2/Source/bucketalloc.h \ + src/libtess2/Source/dict.h \ + src/libtess2/Source/geom.h \ + src/libtess2/Source/mesh.h \ + src/libtess2/Source/priorityq.h \ + src/libtess2/Source/sweep.h \ + src/libtess2/Source/tess.h + unix:!macx { SOURCES += src/imageutils-lodepng.cc SOURCES += src/OffscreenContextGLX.cc @@ -474,8 +492,8 @@ HEADERS += src/cgal.h \ SOURCES += src/cgalutils.cc \ src/cgalutils-tess.cc \ + src/cgalutils-tess2.cc \ src/cgalutils-polyhedron.cc \ - src/cgalutils-tess-old.cc \ src/CGALCache.cc \ src/CGALRenderer.cc \ src/CGAL_Nef_polyhedron.cc \ diff --git a/src/cgalutils-tess2.cc b/src/cgalutils-tess2.cc new file mode 100644 index 00000000..aee7f111 --- /dev/null +++ b/src/cgalutils-tess2.cc @@ -0,0 +1,87 @@ +#include "cgalutils.h" +#include "linalg.h" +#include "tesselator.h" + +#include + +static void *stdAlloc(void* userData, unsigned int size) { + int* allocated = ( int*)userData; + TESS_NOTUSED(userData); + *allocated += (int)size; + return malloc(size); +} + +static void stdFree(void* userData, void* ptr) { + TESS_NOTUSED(userData); + free(ptr); +} + +namespace CGALUtils { + +bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, + Polygons &triangles, + const K::Vector_3 *normal) +{ + // No polygon. FIXME: Will this ever happen or can we assert here? + if (polygons.empty()) return false; + + TESSreal *normalvec = NULL; + TESSreal passednormal[3]; + if (normal) { + passednormal[0] = normal->x(); + passednormal[1] = normal->y(); + passednormal[2] = normal->z(); + normalvec = passednormal; + } + + int allocated = 0; + TESSalloc ma; + TESStesselator* tess = 0; + + memset(&ma, 0, sizeof(ma)); + ma.memalloc = stdAlloc; + ma.memfree = stdFree; + ma.userData = (void*)&allocated; + ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices. + + tess = tessNewTess(&ma); + if (!tess) return -1; + + std::vector contour; + std::vector outputvertices; + BOOST_FOREACH(const PolygonK &poly, polygons) { + contour.clear(); + BOOST_FOREACH(const Vertex3K &v, poly) { + outputvertices.push_back(Vector3d(v.x(), v.y(), v.z())); + contour.push_back(v.x()); + contour.push_back(v.y()); + contour.push_back(v.z()); + } + tessAddContour(tess, 3, &contour.front(), sizeof(TESSreal) * 3, poly.size()); + } + + if (!tessTesselate(tess, TESS_WINDING_ODD, TESS_CONSTRAINED_DELAUNAY_TRIANGLES, 3, 3, normalvec)) return -1; + // printf("Memory used: %.1f kB\n", allocated/1024.0f); + + const TESSindex *vindices = tessGetVertexIndices(tess); + const TESSindex *elements = tessGetElements(tess); + int numelems = tessGetElementCount(tess); + + Polygon tri; + for (int t=0;t nvec = plane.orthogonal_vector(); // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); std::vector triangles; - bool err = CGALUtils::tessellatePolygonWithHoles(polyholes, triangles, NULL); + bool err = CGALUtils::tessellatePolygonWithHolesNew(polyholes, triangles, NULL); if (!err) { BOOST_FOREACH(const Polygon &p, triangles) { if (p.size() != 3) { diff --git a/src/cgalutils.h b/src/cgalutils.h index 92c909dd..fa4917f5 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -36,9 +36,9 @@ namespace CGALUtils { bool tessellatePolygonWithHoles(const PolyholeK &polygons, Polygons &triangles, const K::Vector_3 *normal = NULL); - bool tessellate3DFaceWithHolesNew(std::vector &polygons, - Polygons &triangles, - CGAL::Plane_3 &plane); + bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, + Polygons &triangles, + const K::Vector_3 *normal = NULL); bool tessellate3DFaceWithHoles(std::vector &polygons, std::vector &triangles, CGAL::Plane_3 &plane); diff --git a/src/libtess2/Include/tesselator.h b/src/libtess2/Include/tesselator.h new file mode 100755 index 00000000..1cc41665 --- /dev/null +++ b/src/libtess2/Include/tesselator.h @@ -0,0 +1,226 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#ifndef TESSELATOR_H +#define TESSELATOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +// See OpenGL Red Book for description of the winding rules +// http://www.glprogramming.com/red/chapter11.html +enum TessWindingRule +{ + TESS_WINDING_ODD, + TESS_WINDING_NONZERO, + TESS_WINDING_POSITIVE, + TESS_WINDING_NEGATIVE, + TESS_WINDING_ABS_GEQ_TWO, +}; + +// The contents of the tessGetElements() depends on element type being passed to tessTesselate(). +// Tesselation result element types: +// TESS_POLYGONS +// Each element in the element array is polygon defined as 'polySize' number of vertex indices. +// If a polygon has than 'polySize' vertices, the remaining indices are stored as TESS_UNDEF. +// Example, drawing a polygon: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// for (int i = 0; i < nelems; i++) { +// const TESSindex* poly = &elems[i * polySize]; +// glBegin(GL_POLYGON); +// for (int j = 0; j < polySize; j++) { +// if (poly[j] == TESS_UNDEF) break; +// glVertex2fv(&verts[poly[j]*vertexSize]); +// } +// glEnd(); +// } +// +// TESS_CONNECTED_POLYGONS +// Each element in the element array is polygon defined as 'polySize' number of vertex indices, +// followed by 'polySize' indices to neighour polygons, that is each element is 'polySize' * 2 indices. +// If a polygon has than 'polySize' vertices, the remaining indices are stored as TESS_UNDEF. +// If a polygon edge is a boundary, that is, not connected to another polygon, the neighbour index is TESS_UNDEF. +// Example, flood fill based on seed polygon: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// unsigned char* visited = (unsigned char*)calloc(nelems); +// TESSindex stack[50]; +// int nstack = 0; +// stack[nstack++] = seedPoly; +// visited[startPoly] = 1; +// while (nstack > 0) { +// TESSindex idx = stack[--nstack]; +// const TESSindex* poly = &elems[idx * polySize * 2]; +// const TESSindex* nei = &poly[polySize]; +// for (int i = 0; i < polySize; i++) { +// if (poly[i] == TESS_UNDEF) break; +// if (nei[i] != TESS_UNDEF && !visited[nei[i]]) +// stack[nstack++] = nei[i]; +// visited[nei[i]] = 1; +// } +// } +// } +// +// TESS_BOUNDARY_CONTOURS +// Each element in the element array is [base index, count] pair defining a range of vertices for a contour. +// The first value is index to first vertex in contour and the second value is number of vertices in the contour. +// Example, drawing contours: +// const int nelems = tessGetElementCount(tess); +// const TESSindex* elems = tessGetElements(tess); +// for (int i = 0; i < nelems; i++) { +// const TESSindex base = elems[i * 2]; +// const TESSindex count = elems[i * 2 + 1]; +// glBegin(GL_LINE_LOOP); +// for (int j = 0; j < count; j++) { +// glVertex2fv(&verts[(base+j) * vertexSize]); +// } +// glEnd(); +// } +// +// TESS_CONSTRAINED_DELAUNAY_TRIANGLES +// Similar to TESS_POLYGONS, but we output only triangles and we attempt to provide a valid +// Constrained Delaunay triangulation. + +enum TessElementType +{ + TESS_POLYGONS, + TESS_CONNECTED_POLYGONS, + TESS_BOUNDARY_CONTOURS, + TESS_CONSTRAINED_DELAUNAY_TRIANGLES, +}; + +typedef float TESSreal; +typedef int TESSindex; +typedef struct TESStesselator TESStesselator; +typedef struct TESSalloc TESSalloc; + +#define TESS_UNDEF (~(TESSindex)0) + +#define TESS_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) + +// Custom memory allocator interface. +// The internal memory allocator allocates mesh edges, vertices and faces +// as well as dictionary nodes and active regions in buckets and uses simple +// freelist to speed up the allocation. The bucket size should roughly match your +// expected input data. For example if you process only hundreds of vertices, +// a bucket size of 128 might be ok, where as when processing thousands of vertices +// bucket size of 1024 might be approproate. The bucket size is a compromise between +// how often to allocate memory from the system versus how much extra space the system +// should allocate. Reasonable defaults are show in commects below, they will be used if +// the bucket sizes are zero. +// +// The use may left the memrealloc to be null. In that case, the tesselator will not try to +// dynamically grow int's internal arrays. The tesselator only needs the reallocation when it +// has found intersecting segments and needs to add new vertex. This defency can be cured by +// allocating some extra vertices beforehand. The 'extraVertices' variable allows to specify +// number of expected extra vertices. +struct TESSalloc +{ + void *(*memalloc)( void *userData, unsigned int size ); + void *(*memrealloc)( void *userData, void* ptr, unsigned int size ); + void (*memfree)( void *userData, void *ptr ); + void* userData; // User data passed to the allocator functions. + int meshEdgeBucketSize; // 512 + int meshVertexBucketSize; // 512 + int meshFaceBucketSize; // 256 + int dictNodeBucketSize; // 512 + int regionBucketSize; // 256 + int extraVertices; // Number of extra vertices allocated for the priority queue. +}; + + +// +// Example use: +// +// +// +// + +// tessNewTess() - Creates a new tesselator. +// Use tessDeleteTess() to delete the tesselator. +// Parameters: +// alloc - pointer to a filled TESSalloc struct or NULL to use default malloc based allocator. +// Returns: +// new tesselator object. +TESStesselator* tessNewTess( TESSalloc* alloc ); + +// tessDeleteTess() - Deletes a tesselator. +// Parameters: +// tess - pointer to tesselator object to be deleted. +void tessDeleteTess( TESStesselator *tess ); + +// tessAddContour() - Adds a contour to be tesselated. +// The type of the vertex coordinates is assumed to be TESSreal. +// Parameters: +// tess - pointer to tesselator object. +// size - number of coordinates per vertex. Must be 2 or 3. +// pointer - pointer to the first coordinate of the first vertex in the array. +// stride - defines offset in bytes between consecutive vertices. +// count - number of vertices in contour. +void tessAddContour( TESStesselator *tess, int size, const void* pointer, int stride, int count ); + +// tessTesselate() - tesselate contours. +// Parameters: +// tess - pointer to tesselator object. +// windingRule - winding rules used for tesselation, must be one of TessWindingRule. +// elementType - defines the tesselation result element type, must be one of TessElementType. +// polySize - defines maximum vertices per polygons if output is polygons. If elementType is TESS_CONSTRAINED_DELAUNAY_TRIANGLES, this parameter is ignored. +// vertexSize - defines the number of coordinates in tesselation result vertex, must be 2 or 3. +// normal - defines the normal of the input contours, of null the normal is calculated automatically. +// Returns: +// 1 if succeed, 0 if failed. +int tessTesselate( TESStesselator *tess, int windingRule, int elementType, int polySize, int vertexSize, const TESSreal* normal ); + +// tessGetVertexCount() - Returns number of vertices in the tesselated output. +int tessGetVertexCount( TESStesselator *tess ); + +// tessGetVertices() - Returns pointer to first coordinate of first vertex. +const TESSreal* tessGetVertices( TESStesselator *tess ); + +// tessGetVertexIndices() - Returns pointer to first vertex index. +// Vertex indices can be used to map the generated vertices to the original vertices. +// Every point added using tessAddContour() will get a new index starting at 0. +// New vertices generated at the intersections of segments are assigned value TESS_UNDEF. +const TESSindex* tessGetVertexIndices( TESStesselator *tess ); + +// tessGetElementCount() - Returns number of elements in the the tesselated output. +int tessGetElementCount( TESStesselator *tess ); + +// tessGetElements() - Returns pointer to the first element. +const TESSindex* tessGetElements( TESStesselator *tess ); + +#ifdef __cplusplus +}; +#endif + +#endif // TESSELATOR_H diff --git a/src/libtess2/Source/bucketalloc.c b/src/libtess2/Source/bucketalloc.c new file mode 100755 index 00000000..420ebab5 --- /dev/null +++ b/src/libtess2/Source/bucketalloc.c @@ -0,0 +1,191 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#include +#include +#include "../Include/tesselator.h" + +//#define CHECK_BOUNDS + +typedef struct BucketAlloc BucketAlloc; +typedef struct Bucket Bucket; + +struct Bucket +{ + Bucket *next; +}; + +struct BucketAlloc +{ + void *freelist; + Bucket *buckets; + unsigned int itemSize; + unsigned int bucketSize; + const char *name; + TESSalloc* alloc; +}; + +static int CreateBucket( struct BucketAlloc* ba ) +{ + size_t size; + Bucket* bucket; + void* freelist; + unsigned char* head; + unsigned char* it; + + // Allocate memory for the bucket + size = sizeof(Bucket) + ba->itemSize * ba->bucketSize; + bucket = (Bucket*)ba->alloc->memalloc( ba->alloc->userData, size ); + if ( !bucket ) + return 0; + bucket->next = 0; + + // Add the bucket into the list of buckets. + bucket->next = ba->buckets; + ba->buckets = bucket; + + // Add new items to the free list. + freelist = ba->freelist; + head = (unsigned char*)bucket + sizeof(Bucket); + it = head + ba->itemSize * ba->bucketSize; + do + { + it -= ba->itemSize; + // Store pointer to next free item. + *((void**)it) = freelist; + // Pointer to next location containing a free item. + freelist = (void*)it; + } + while ( it != head ); + // Update pointer to next location containing a free item. + ba->freelist = (void*)it; + + return 1; +} + +static void *NextFreeItem( struct BucketAlloc *ba ) +{ + return *(void**)ba->freelist; +} + +struct BucketAlloc* createBucketAlloc( TESSalloc* alloc, const char* name, + unsigned int itemSize, unsigned int bucketSize ) +{ + BucketAlloc* ba = (BucketAlloc*)alloc->memalloc( alloc->userData, sizeof(BucketAlloc) ); + + ba->alloc = alloc; + ba->name = name; + ba->itemSize = itemSize; + if ( ba->itemSize < sizeof(void*) ) + ba->itemSize = sizeof(void*); + ba->bucketSize = bucketSize; + ba->freelist = 0; + ba->buckets = 0; + + if ( !CreateBucket( ba ) ) + { + alloc->memfree( alloc->userData, ba ); + return 0; + } + + return ba; +} + +void* bucketAlloc( struct BucketAlloc *ba ) +{ + void *it; + + // If running out of memory, allocate new bucket and update the freelist. + if ( !ba->freelist || !NextFreeItem( ba ) ) + { + if ( !CreateBucket( ba ) ) + return 0; + } + + // Pop item from in front of the free list. + it = ba->freelist; + ba->freelist = NextFreeItem( ba ); + + return it; +} + +void bucketFree( struct BucketAlloc *ba, void *ptr ) +{ +#ifdef CHECK_BOUNDS + int inBounds = 0; + Bucket *bucket; + + // Check that the pointer is allocated with this allocator. + bucket = ba->buckets; + while ( bucket ) + { + void *bucketMin = (void*)((unsigned char*)bucket + sizeof(Bucket)); + void *bucketMax = (void*)((unsigned char*)bucket + sizeof(Bucket) + ba->itemSize * ba->bucketSize); + if ( ptr >= bucketMin && ptr < bucketMax ) + { + inBounds = 1; + break; + } + bucket = bucket->next; + } + + if ( inBounds ) + { + // Add the node in front of the free list. + *(void**)ptr = ba->freelist; + ba->freelist = ptr; + } + else + { + printf("ERROR! pointer 0x%p does not belong to allocator '%s'\n", ba->name); + } +#else + // Add the node in front of the free list. + *(void**)ptr = ba->freelist; + ba->freelist = ptr; +#endif +} + +void deleteBucketAlloc( struct BucketAlloc *ba ) +{ + TESSalloc* alloc = ba->alloc; + Bucket *bucket = ba->buckets; + Bucket *next; + while ( bucket ) + { + next = bucket->next; + alloc->memfree( alloc->userData, bucket ); + bucket = next; + } + ba->freelist = 0; + ba->buckets = 0; + alloc->memfree( alloc->userData, ba ); +} diff --git a/src/libtess2/Source/bucketalloc.h b/src/libtess2/Source/bucketalloc.h new file mode 100755 index 00000000..c540951e --- /dev/null +++ b/src/libtess2/Source/bucketalloc.h @@ -0,0 +1,51 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Mikko Mononen, July 2009. +*/ + +#ifndef MEMALLOC_H +#define MEMALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tesselator.h" + +struct BucketAlloc *createBucketAlloc( TESSalloc* alloc, const char *name, + unsigned int itemSize, unsigned int bucketSize ); +void *bucketAlloc( struct BucketAlloc *ba); +void bucketFree( struct BucketAlloc *ba, void *ptr ); +void deleteBucketAlloc( struct BucketAlloc *ba ); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/libtess2/Source/dict.c b/src/libtess2/Source/dict.c new file mode 100755 index 00000000..650adda2 --- /dev/null +++ b/src/libtess2/Source/dict.c @@ -0,0 +1,109 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include "../Include/tesselator.h" +#include "bucketalloc.h" +#include "dict.h" + +/* really tessDictListNewDict */ +Dict *dictNewDict( TESSalloc* alloc, void *frame, int (*leq)(void *frame, DictKey key1, DictKey key2) ) +{ + Dict *dict = (Dict *)alloc->memalloc( alloc->userData, sizeof( Dict )); + DictNode *head; + + if (dict == NULL) return NULL; + + head = &dict->head; + + head->key = NULL; + head->next = head; + head->prev = head; + + dict->frame = frame; + dict->leq = leq; + + if (alloc->dictNodeBucketSize < 16) + alloc->dictNodeBucketSize = 16; + if (alloc->dictNodeBucketSize > 4096) + alloc->dictNodeBucketSize = 4096; + dict->nodePool = createBucketAlloc( alloc, "Dict", sizeof(DictNode), alloc->dictNodeBucketSize ); + + return dict; +} + +/* really tessDictListDeleteDict */ +void dictDeleteDict( TESSalloc* alloc, Dict *dict ) +{ + deleteBucketAlloc( dict->nodePool ); + alloc->memfree( alloc->userData, dict ); +} + +/* really tessDictListInsertBefore */ +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ) +{ + DictNode *newNode; + + do { + node = node->prev; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key)); + + newNode = (DictNode *)bucketAlloc( dict->nodePool ); + if (newNode == NULL) return NULL; + + newNode->key = key; + newNode->next = node->next; + node->next->prev = newNode; + newNode->prev = node; + node->next = newNode; + + return newNode; +} + +/* really tessDictListDelete */ +void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/ +{ + node->next->prev = node->prev; + node->prev->next = node->next; + bucketFree( dict->nodePool, node ); +} + +/* really tessDictListSearch */ +DictNode *dictSearch( Dict *dict, DictKey key ) +{ + DictNode *node = &dict->head; + + do { + node = node->next; + } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key)); + + return node; +} diff --git a/src/libtess2/Source/dict.h b/src/libtess2/Source/dict.h new file mode 100755 index 00000000..4cf32265 --- /dev/null +++ b/src/libtess2/Source/dict.h @@ -0,0 +1,74 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef DICT_LIST_H +#define DICT_LIST_H + +typedef void *DictKey; +typedef struct Dict Dict; +typedef struct DictNode DictNode; + +Dict *dictNewDict( TESSalloc* alloc, void *frame, int (*leq)(void *frame, DictKey key1, DictKey key2) ); + +void dictDeleteDict( TESSalloc* alloc, Dict *dict ); + +/* Search returns the node with the smallest key greater than or equal +* to the given key. If there is no such key, returns a node whose +* key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc. +*/ +DictNode *dictSearch( Dict *dict, DictKey key ); +DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key ); +void dictDelete( Dict *dict, DictNode *node ); + +#define dictKey(n) ((n)->key) +#define dictSucc(n) ((n)->next) +#define dictPred(n) ((n)->prev) +#define dictMin(d) ((d)->head.next) +#define dictMax(d) ((d)->head.prev) +#define dictInsert(d,k) (dictInsertBefore((d),&(d)->head,(k))) + + +/*** Private data structures ***/ + +struct DictNode { + DictKey key; + DictNode *next; + DictNode *prev; +}; + +struct Dict { + DictNode head; + void *frame; + struct BucketAlloc *nodePool; + int (*leq)(void *frame, DictKey key1, DictKey key2); +}; + +#endif diff --git a/src/libtess2/Source/geom.c b/src/libtess2/Source/geom.c new file mode 100755 index 00000000..21da0c2d --- /dev/null +++ b/src/libtess2/Source/geom.c @@ -0,0 +1,286 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include "mesh.h" +#include "geom.h" +#include + +int tesvertLeq( TESSvertex *u, TESSvertex *v ) +{ + /* Returns TRUE if u is lexicographically <= v. */ + + return VertLeq( u, v ); +} + +TESSreal tesedgeEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + TESSreal gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR)); + } else { + return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +TESSreal tesedgeSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Returns a number whose sign matches EdgeEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + TESSreal gapL, gapR; + + assert( VertLeq( u, v ) && VertLeq( v, w )); + + gapL = v->s - u->s; + gapR = w->s - v->s; + + if( gapL + gapR > 0 ) { + return (v->t - w->t) * gapL + (v->t - u->t) * gapR; + } + /* vertical line */ + return 0; +} + + +/*********************************************************************** +* Define versions of EdgeSign, EdgeEval with s and t transposed. +*/ + +TESSreal testransEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + TESSreal gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + if( gapL < gapR ) { + return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR)); + } else { + return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; +} + +TESSreal testransSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + TESSreal gapL, gapR; + + assert( TransLeq( u, v ) && TransLeq( v, w )); + + gapL = v->t - u->t; + gapR = w->t - v->t; + + if( gapL + gapR > 0 ) { + return (v->s - w->s) * gapL + (v->s - u->s) * gapR; + } + /* vertical line */ + return 0; +} + + +int tesvertCCW( TESSvertex *u, TESSvertex *v, TESSvertex *w ) +{ + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0; +} + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), +* or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces +* this in the rare case that one argument is slightly negative. +* The implementation is extremely stable numerically. +* In particular it guarantees that the result r satisfies +* MIN(x,y) <= r <= MAX(x,y), and the results are very accurate +* even when a and b differ greatly in magnitude. +*/ +#define RealInterpolate(a,x,b,y) \ + (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \ + ((a <= b) ? ((b == 0) ? ((x+y) / 2) \ + : (x + (y-x) * (a/(a+b)))) \ + : (y + (x-y) * (b/(a+b))))) + +#ifndef FOR_TRITE_TEST_PROGRAM +#define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y) +#else + +/* Claim: the ONLY property the sweep algorithm relies on is that +* MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that. +*/ +#include +extern int RandomInterpolate; + +double Interpolate( double a, double x, double b, double y) +{ + printf("*********************%d\n",RandomInterpolate); + if( RandomInterpolate ) { + a = 1.2 * drand48() - 0.1; + a = (a < 0) ? 0 : ((a > 1) ? 1 : a); + b = 1.0 - a; + } + return RealInterpolate(a,x,b,y); +} + +#endif + +#define Swap(a,b) if (1) { TESSvertex *t = a; a = b; b = t; } else + +void tesedgeIntersect( TESSvertex *o1, TESSvertex *d1, + TESSvertex *o2, TESSvertex *d2, + TESSvertex *v ) + /* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ +{ + TESSreal z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! VertLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->s = (o2->s + d1->s) / 2; + } else if( VertLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval( o1, o2, d1 ); + z2 = EdgeEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d1->s ); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign( o1, o2, d1 ); + z2 = -EdgeSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->s = Interpolate( z1, o2->s, z2, d2->s ); + } + + /* Now repeat the process for t */ + + if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); } + if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); } + if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); } + + if( ! TransLeq( o2, d1 )) { + /* Technically, no intersection -- do our best */ + v->t = (o2->t + d1->t) / 2; + } else if( TransLeq( d1, d2 )) { + /* Interpolate between o2 and d1 */ + z1 = TransEval( o1, o2, d1 ); + z2 = TransEval( o2, d1, d2 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d1->t ); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign( o1, o2, d1 ); + z2 = -TransSign( o1, d2, d1 ); + if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; } + v->t = Interpolate( z1, o2->t, z2, d2->t ); + } +} + +/* + Calculate the angle between v1-v2 and v1-v0 + */ +TESSreal calcAngle( TESSvertex *v0, TESSvertex *v1, TESSvertex *v2 ) +{ + TESSreal a[2] = { v2->s - v1->s, v2->t - v1->t }; + TESSreal b[2] = { v0->s - v1->s, v0->t - v1->t }; + TESSreal num = a[0] * b[0] + a[1] * b[1]; + TESSreal den = sqrt( a[0] * a[0] + a[1] * a[1] ) * sqrt( b[0] * b[0] + b[1] * b[1] ); + if ( den > 0.0 ) num /= den; + if ( num < -1.0 ) num = -1.0; + if ( num > 1.0 ) num = 1.0; + return acos( num ); +} + +/* + Returns 1 is edge is locally delaunay + */ +int tesedgeIsLocallyDelaunay( TESShalfEdge *e ) +{ + return (calcAngle(e->Lnext->Org, e->Lnext->Lnext->Org, e->Org) + + calcAngle(e->Sym->Lnext->Org, e->Sym->Lnext->Lnext->Org, e->Sym->Org)) < (M_PI + 0.01); +} diff --git a/src/libtess2/Source/geom.h b/src/libtess2/Source/geom.h new file mode 100755 index 00000000..1b93fd64 --- /dev/null +++ b/src/libtess2/Source/geom.h @@ -0,0 +1,78 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef GEOM_H +#define GEOM_H + +#include "mesh.h" + +#ifdef NO_BRANCH_CONDITIONS +/* MIPS architecture has special instructions to evaluate boolean +* conditions -- more efficient than branching, IF you can get the +* compiler to generate the right instructions (SGI compiler doesn't) +*/ +#define VertEq(u,v) (((u)->s == (v)->s) & ((u)->t == (v)->t)) +#define VertLeq(u,v) (((u)->s < (v)->s) | \ + ((u)->s == (v)->s & (u)->t <= (v)->t)) +#else +#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t) +#define VertLeq(u,v) (((u)->s < (v)->s) || ((u)->s == (v)->s && (u)->t <= (v)->t)) +#endif + +#define EdgeEval(u,v,w) tesedgeEval(u,v,w) +#define EdgeSign(u,v,w) tesedgeSign(u,v,w) + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + +#define TransLeq(u,v) (((u)->t < (v)->t) || ((u)->t == (v)->t && (u)->s <= (v)->s)) +#define TransEval(u,v,w) testransEval(u,v,w) +#define TransSign(u,v,w) testransSign(u,v,w) + + +#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org ) +#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst ) +#define EdgeIsInternal(e) e->Rface && e->Rface->inside + +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t)) + +#define VertCCW(u,v,w) tesvertCCW(u,v,w) + +int tesvertLeq( TESSvertex *u, TESSvertex *v ); +TESSreal tesedgeEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal tesedgeSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal testransEval( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +TESSreal testransSign( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +int tesvertCCW( TESSvertex *u, TESSvertex *v, TESSvertex *w ); +void tesedgeIntersect( TESSvertex *o1, TESSvertex *d1, TESSvertex *o2, TESSvertex *d2, TESSvertex *v ); +int tesedgeIsLocallyDelaunay( TESShalfEdge *e ); + +#endif diff --git a/src/libtess2/Source/mesh.c b/src/libtess2/Source/mesh.c new file mode 100755 index 00000000..20c52ff6 --- /dev/null +++ b/src/libtess2/Source/mesh.c @@ -0,0 +1,922 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include +#include "mesh.h" +#include "geom.h" +#include "bucketalloc.h" + +#define TRUE 1 +#define FALSE 0 + +/************************ Utility Routines ************************/ + +/* Allocate and free half-edges in pairs for efficiency. +* The *only* place that should use this fact is allocation/free. +*/ +typedef struct { TESShalfEdge e, eSym; } EdgePair; + +/* MakeEdge creates a new pair of half-edges which form their own loop. +* No vertex or face structures are allocated, but these must be assigned +* before the current edge operation is completed. +*/ +static TESShalfEdge *MakeEdge( TESSmesh* mesh, TESShalfEdge *eNext ) +{ + TESShalfEdge *e; + TESShalfEdge *eSym; + TESShalfEdge *ePrev; + EdgePair *pair = (EdgePair *)bucketAlloc( mesh->edgeBucket ); + if (pair == NULL) return NULL; + + e = &pair->e; + eSym = &pair->eSym; + + /* Make sure eNext points to the first edge of the edge pair */ + if( eNext->Sym < eNext ) { eNext = eNext->Sym; } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext->Sym->next; + eSym->next = ePrev; + ePrev->Sym->next = e; + e->next = eNext; + eNext->Sym->next = eSym; + + e->Sym = eSym; + e->Onext = e; + e->Lnext = eSym; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + e->mark = 0; + + eSym->Sym = e; + eSym->Onext = eSym; + eSym->Lnext = e; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + eSym->mark = 0; + + return e; +} + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the +* CS348a notes (see mesh.h). Basically it modifies the mesh so that +* a->Onext and b->Onext are exchanged. This can have various effects +* depending on whether a and b belong to different face or vertex rings. +* For more explanation see tessMeshSplice() below. +*/ +static void Splice( TESShalfEdge *a, TESShalfEdge *b ) +{ + TESShalfEdge *aOnext = a->Onext; + TESShalfEdge *bOnext = b->Onext; + + aOnext->Sym->Lnext = b; + bOnext->Sym->Lnext = a; + a->Onext = bOnext; + b->Onext = aOnext; +} + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the +* origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives +* a place to insert the new vertex in the global vertex list. We insert +* the new vertex *before* vNext so that algorithms which walk the vertex +* list will not see the newly created vertices. +*/ +static void MakeVertex( TESSvertex *newVertex, + TESShalfEdge *eOrig, TESSvertex *vNext ) +{ + TESShalfEdge *e; + TESSvertex *vPrev; + TESSvertex *vNew = newVertex; + + assert(vNew != NULL); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext->prev; + vNew->prev = vPrev; + vPrev->next = vNew; + vNew->next = vNext; + vNext->prev = vNew; + + vNew->anEdge = eOrig; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e->Org = vNew; + e = e->Onext; + } while( e != eOrig ); +} + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left +* face of all edges in the face loop to which eOrig belongs. "fNext" gives +* a place to insert the new face in the global face list. We insert +* the new face *before* fNext so that algorithms which walk the face +* list will not see the newly created faces. +*/ +static void MakeFace( TESSface *newFace, TESShalfEdge *eOrig, TESSface *fNext ) +{ + TESShalfEdge *e; + TESSface *fPrev; + TESSface *fNew = newFace; + + assert(fNew != NULL); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext->prev; + fNew->prev = fPrev; + fPrev->next = fNew; + fNew->next = fNext; + fNext->prev = fNew; + + fNew->anEdge = eOrig; + fNew->trail = NULL; + fNew->marked = FALSE; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew->inside = fNext->inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e->Lface = fNew; + e = e->Lnext; + } while( e != eOrig ); +} + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), +* and removes from the global edge list. +*/ +static void KillEdge( TESSmesh *mesh, TESShalfEdge *eDel ) +{ + TESShalfEdge *ePrev, *eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if( eDel->Sym < eDel ) { eDel = eDel->Sym; } + + /* delete from circular doubly-linked list */ + eNext = eDel->next; + ePrev = eDel->Sym->next; + eNext->Sym->next = ePrev; + ePrev->Sym->next = eNext; + + bucketFree( mesh->edgeBucket, eDel ); +} + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global +* vertex list. It updates the vertex loop to point to a given new vertex. +*/ +static void KillVertex( TESSmesh *mesh, TESSvertex *vDel, TESSvertex *newOrg ) +{ + TESShalfEdge *e, *eStart = vDel->anEdge; + TESSvertex *vPrev, *vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e->Org = newOrg; + e = e->Onext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + vPrev = vDel->prev; + vNext = vDel->next; + vNext->prev = vPrev; + vPrev->next = vNext; + + bucketFree( mesh->vertexBucket, vDel ); +} + +/* KillFace( fDel ) destroys a face and removes it from the global face +* list. It updates the face loop to point to a given new face. +*/ +static void KillFace( TESSmesh *mesh, TESSface *fDel, TESSface *newLface ) +{ + TESShalfEdge *e, *eStart = fDel->anEdge; + TESSface *fPrev, *fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e->Lface = newLface; + e = e->Lnext; + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fDel->prev; + fNext = fDel->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + bucketFree( mesh->faceBucket, fDel ); +} + + +/****************** Basic Edge Operations **********************/ + +/* tessMeshMakeEdge creates one edge, two vertices, and a loop (face). +* The loop consists of the two new half-edges. +*/ +TESShalfEdge *tessMeshMakeEdge( TESSmesh *mesh ) +{ + TESSvertex *newVertex1 = (TESSvertex*)bucketAlloc(mesh->vertexBucket); + TESSvertex *newVertex2 = (TESSvertex*)bucketAlloc(mesh->vertexBucket); + TESSface *newFace = (TESSface*)bucketAlloc(mesh->faceBucket); + TESShalfEdge *e; + + /* if any one is null then all get freed */ + if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) { + if (newVertex1 != NULL) bucketFree( mesh->vertexBucket, newVertex1 ); + if (newVertex2 != NULL) bucketFree( mesh->vertexBucket, newVertex2 ); + if (newFace != NULL) bucketFree( mesh->faceBucket, newFace ); + return NULL; + } + + e = MakeEdge( mesh, &mesh->eHead ); + if (e == NULL) return NULL; + + MakeVertex( newVertex1, e, &mesh->vHead ); + MakeVertex( newVertex2, e->Sym, &mesh->vHead ); + MakeFace( newFace, e, &mesh->fHead ); + return e; +} + + +/* tessMeshSplice( eOrg, eDst ) is the basic operation for changing the +* mesh connectivity and topology. It changes the mesh so that +* eOrg->Onext <- OLD( eDst->Onext ) +* eDst->Onext <- OLD( eOrg->Onext ) +* where OLD(...) means the value before the meshSplice operation. +* +* This can have two effects on the vertex structure: +* - if eOrg->Org != eDst->Org, the two vertices are merged together +* - if eOrg->Org == eDst->Org, the origin is split into two vertices +* In both cases, eDst->Org is changed and eOrg->Org is untouched. +* +* Similarly (and independently) for the face structure, +* - if eOrg->Lface == eDst->Lface, one loop is split into two +* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one +* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. +* +* Some special cases: +* If eDst == eOrg, the operation has no effect. +* If eDst == eOrg->Lnext, the new face will have a single edge. +* If eDst == eOrg->Lprev, the old face will have a single edge. +* If eDst == eOrg->Onext, the new vertex will have a single edge. +* If eDst == eOrg->Oprev, the old vertex will have a single edge. +*/ +int tessMeshSplice( TESSmesh* mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ) +{ + int joiningLoops = FALSE; + int joiningVertices = FALSE; + + if( eOrg == eDst ) return 1; + + if( eDst->Org != eOrg->Org ) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = TRUE; + KillVertex( mesh, eDst->Org, eOrg->Org ); + } + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( mesh, eDst->Lface, eOrg->Lface ); + } + + /* Change the edge structure */ + Splice( eDst, eOrg ); + + if( ! joiningVertices ) { + TESSvertex *newVertex = (TESSvertex*)bucketAlloc( mesh->vertexBucket ); + if (newVertex == NULL) return 0; + + /* We split one vertex into two -- the new vertex is eDst->Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex( newVertex, eDst, eOrg->Org ); + eOrg->Org->anEdge = eOrg; + } + if( ! joiningLoops ) { + TESSface *newFace = (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return 0; + + /* We split one loop into two -- the new loop is eDst->Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace( newFace, eDst, eOrg->Lface ); + eOrg->Lface->anEdge = eOrg; + } + + return 1; +} + + +/* tessMeshDelete( eDel ) removes the edge eDel. There are several cases: +* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop +* eDel->Lface is deleted. Otherwise, we are splitting one loop into two; +* the newly created loop will contain eDel->Dst. If the deletion of eDel +* would create isolated vertices, those are deleted as well. +* +* This function could be implemented as two calls to tessMeshSplice +* plus a few calls to memFree, but this would allocate and delete +* unnecessary vertices and faces. +*/ +int tessMeshDelete( TESSmesh *mesh, TESShalfEdge *eDel ) +{ + TESShalfEdge *eDelSym = eDel->Sym; + int joiningLoops = FALSE; + + /* First step: disconnect the origin vertex eDel->Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if( eDel->Lface != eDel->Rface ) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = TRUE; + KillFace( mesh, eDel->Lface, eDel->Rface ); + } + + if( eDel->Onext == eDel ) { + KillVertex( mesh, eDel->Org, NULL ); + } else { + /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */ + eDel->Rface->anEdge = eDel->Oprev; + eDel->Org->anEdge = eDel->Onext; + + Splice( eDel, eDel->Oprev ); + if( ! joiningLoops ) { + TESSface *newFace= (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return 0; + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace( newFace, eDel, eDel->Lface ); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel->Org + * may have been deleted. Now we disconnect eDel->Dst. + */ + if( eDelSym->Onext == eDelSym ) { + KillVertex( mesh, eDelSym->Org, NULL ); + KillFace( mesh, eDelSym->Lface, NULL ); + } else { + /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */ + eDel->Lface->anEdge = eDelSym->Oprev; + eDelSym->Org->anEdge = eDelSym->Onext; + Splice( eDelSym, eDelSym->Oprev ); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge( mesh, eDel ); + + return 1; +} + + +/******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge +* operations above. They are provided for convenience and efficiency. +*/ + + +/* tessMeshAddEdgeVertex( eOrg ) creates a new edge eNew such that +* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. +* eOrg and eNew will have the same left face. +*/ +TESShalfEdge *tessMeshAddEdgeVertex( TESSmesh *mesh, TESShalfEdge *eOrg ) +{ + TESShalfEdge *eNewSym; + TESShalfEdge *eNew = MakeEdge( mesh, eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + { + TESSvertex *newVertex= (TESSvertex*)bucketAlloc( mesh->vertexBucket ); + if (newVertex == NULL) return NULL; + + MakeVertex( newVertex, eNewSym, eNew->Org ); + } + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + return eNew; +} + + +/* tessMeshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, +* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. +* eOrg and eNew will have the same left face. +*/ +TESShalfEdge *tessMeshSplitEdge( TESSmesh *mesh, TESShalfEdge *eOrg ) +{ + TESShalfEdge *eNew; + TESShalfEdge *tempHalfEdge= tessMeshAddEdgeVertex( mesh, eOrg ); + if (tempHalfEdge == NULL) return NULL; + + eNew = tempHalfEdge->Sym; + + /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */ + Splice( eOrg->Sym, eOrg->Sym->Oprev ); + Splice( eOrg->Sym, eNew ); + + /* Set the vertex and face information */ + eOrg->Dst = eNew->Org; + eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */ + eNew->Rface = eOrg->Rface; + eNew->winding = eOrg->winding; /* copy old winding information */ + eNew->Sym->winding = eOrg->Sym->winding; + + return eNew; +} + + +/* tessMeshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst +* to eDst->Org, and returns the corresponding half-edge eNew. +* If eOrg->Lface == eDst->Lface, this splits one loop into two, +* and the newly created loop is eNew->Lface. Otherwise, two disjoint +* loops are merged into one, and the loop eDst->Lface is destroyed. +* +* If (eOrg == eDst), the new face will have only two edges. +* If (eOrg->Lnext == eDst), the old face is reduced to a single edge. +* If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges. +*/ +TESShalfEdge *tessMeshConnect( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ) +{ + TESShalfEdge *eNewSym; + int joiningLoops = FALSE; + TESShalfEdge *eNew = MakeEdge( mesh, eOrg ); + if (eNew == NULL) return NULL; + + eNewSym = eNew->Sym; + + if( eDst->Lface != eOrg->Lface ) { + /* We are connecting two disjoint loops -- destroy eDst->Lface */ + joiningLoops = TRUE; + KillFace( mesh, eDst->Lface, eOrg->Lface ); + } + + /* Connect the new edge appropriately */ + Splice( eNew, eOrg->Lnext ); + Splice( eNewSym, eDst ); + + /* Set the vertex and face information */ + eNew->Org = eOrg->Dst; + eNewSym->Org = eDst->Org; + eNew->Lface = eNewSym->Lface = eOrg->Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg->Lface->anEdge = eNewSym; + + if( ! joiningLoops ) { + TESSface *newFace= (TESSface*)bucketAlloc( mesh->faceBucket ); + if (newFace == NULL) return NULL; + + /* We split one loop into two -- the new loop is eNew->Lface */ + MakeFace( newFace, eNew, eOrg->Lface ); + } + return eNew; +} + + +/******************** Other Operations **********************/ + +/* tessMeshZapFace( fZap ) destroys a face and removes it from the +* global face list. All edges of fZap will have a NULL pointer as their +* left face. Any edges which also have a NULL pointer as their right face +* are deleted entirely (along with any isolated vertices this produces). +* An entire mesh can be deleted by zapping its faces, one at a time, +* in any order. Zapped faces cannot be used in further mesh operations! +*/ +void tessMeshZapFace( TESSmesh *mesh, TESSface *fZap ) +{ + TESShalfEdge *eStart = fZap->anEdge; + TESShalfEdge *e, *eNext, *eSym; + TESSface *fPrev, *fNext; + + /* walk around face, deleting edges whose right face is also NULL */ + eNext = eStart->Lnext; + do { + e = eNext; + eNext = e->Lnext; + + e->Lface = NULL; + if( e->Rface == NULL ) { + /* delete the edge -- see TESSmeshDelete above */ + + if( e->Onext == e ) { + KillVertex( mesh, e->Org, NULL ); + } else { + /* Make sure that e->Org points to a valid half-edge */ + e->Org->anEdge = e->Onext; + Splice( e, e->Oprev ); + } + eSym = e->Sym; + if( eSym->Onext == eSym ) { + KillVertex( mesh, eSym->Org, NULL ); + } else { + /* Make sure that eSym->Org points to a valid half-edge */ + eSym->Org->anEdge = eSym->Onext; + Splice( eSym, eSym->Oprev ); + } + KillEdge( mesh, e ); + } + } while( e != eStart ); + + /* delete from circular doubly-linked list */ + fPrev = fZap->prev; + fNext = fZap->next; + fNext->prev = fPrev; + fPrev->next = fNext; + + bucketFree( mesh->faceBucket, fZap ); +} + + +/* tessMeshNewMesh() creates a new mesh with no edges, no vertices, +* and no loops (what we usually call a "face"). +*/ +TESSmesh *tessMeshNewMesh( TESSalloc* alloc ) +{ + TESSvertex *v; + TESSface *f; + TESShalfEdge *e; + TESShalfEdge *eSym; + TESSmesh *mesh = (TESSmesh *)alloc->memalloc( alloc->userData, sizeof( TESSmesh )); + if (mesh == NULL) { + return NULL; + } + + if (alloc->meshEdgeBucketSize < 16) + alloc->meshEdgeBucketSize = 16; + if (alloc->meshEdgeBucketSize > 4096) + alloc->meshEdgeBucketSize = 4096; + + if (alloc->meshVertexBucketSize < 16) + alloc->meshVertexBucketSize = 16; + if (alloc->meshVertexBucketSize > 4096) + alloc->meshVertexBucketSize = 4096; + + if (alloc->meshFaceBucketSize < 16) + alloc->meshFaceBucketSize = 16; + if (alloc->meshFaceBucketSize > 4096) + alloc->meshFaceBucketSize = 4096; + + mesh->edgeBucket = createBucketAlloc( alloc, "Mesh Edges", sizeof(EdgePair), alloc->meshEdgeBucketSize ); + mesh->vertexBucket = createBucketAlloc( alloc, "Mesh Vertices", sizeof(TESSvertex), alloc->meshVertexBucketSize ); + mesh->faceBucket = createBucketAlloc( alloc, "Mesh Faces", sizeof(TESSface), alloc->meshFaceBucketSize ); + + v = &mesh->vHead; + f = &mesh->fHead; + e = &mesh->eHead; + eSym = &mesh->eHeadSym; + + v->next = v->prev = v; + v->anEdge = NULL; + + f->next = f->prev = f; + f->anEdge = NULL; + f->trail = NULL; + f->marked = FALSE; + f->inside = FALSE; + + e->next = e; + e->Sym = eSym; + e->Onext = NULL; + e->Lnext = NULL; + e->Org = NULL; + e->Lface = NULL; + e->winding = 0; + e->activeRegion = NULL; + + eSym->next = eSym; + eSym->Sym = e; + eSym->Onext = NULL; + eSym->Lnext = NULL; + eSym->Org = NULL; + eSym->Lface = NULL; + eSym->winding = 0; + eSym->activeRegion = NULL; + + return mesh; +} + + +/* tessMeshUnion( mesh1, mesh2 ) forms the union of all structures in +* both meshes, and returns the new mesh (the old meshes are destroyed). +*/ +TESSmesh *tessMeshUnion( TESSalloc* alloc, TESSmesh *mesh1, TESSmesh *mesh2 ) +{ + TESSface *f1 = &mesh1->fHead; + TESSvertex *v1 = &mesh1->vHead; + TESShalfEdge *e1 = &mesh1->eHead; + TESSface *f2 = &mesh2->fHead; + TESSvertex *v2 = &mesh2->vHead; + TESShalfEdge *e2 = &mesh2->eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if( f2->next != f2 ) { + f1->prev->next = f2->next; + f2->next->prev = f1->prev; + f2->prev->next = f1; + f1->prev = f2->prev; + } + + if( v2->next != v2 ) { + v1->prev->next = v2->next; + v2->next->prev = v1->prev; + v2->prev->next = v1; + v1->prev = v2->prev; + } + + if( e2->next != e2 ) { + e1->Sym->next->Sym->next = e2->next; + e2->next->Sym->next = e1->Sym->next; + e2->Sym->next->Sym->next = e1; + e1->Sym->next = e2->Sym->next; + } + + alloc->memfree( alloc->userData, mesh2 ); + return mesh1; +} + + +static int CountFaceVerts( TESSface *f ) +{ + TESShalfEdge *eCur = f->anEdge; + int n = 0; + do + { + n++; + eCur = eCur->Lnext; + } + while (eCur != f->anEdge); + return n; +} + +int tessMeshMergeConvexFaces( TESSmesh *mesh, int maxVertsPerFace ) +{ + TESSface *f; + TESShalfEdge *eCur, *eNext, *eSym; + TESSvertex *vStart; + int curNv, symNv; + + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + // Skip faces which are outside the result. + if( !f->inside ) + continue; + + eCur = f->anEdge; + vStart = eCur->Org; + + while (1) + { + eNext = eCur->Lnext; + eSym = eCur->Sym; + + // Try to merge if the neighbour face is valid. + if( eSym && eSym->Lface && eSym->Lface->inside ) + { + // Try to merge the neighbour faces if the resulting polygons + // does not exceed maximum number of vertices. + curNv = CountFaceVerts( f ); + symNv = CountFaceVerts( eSym->Lface ); + if( (curNv+symNv-2) <= maxVertsPerFace ) + { + // Merge if the resulting poly is convex. + if( VertCCW( eCur->Lprev->Org, eCur->Org, eSym->Lnext->Lnext->Org ) && + VertCCW( eSym->Lprev->Org, eSym->Org, eCur->Lnext->Lnext->Org ) ) + { + eNext = eSym->Lnext; + if( !tessMeshDelete( mesh, eSym ) ) + return 0; + eCur = 0; + } + } + } + + if( eCur && eCur->Lnext->Org == vStart ) + break; + + // Continue to next edge. + eCur = eNext; + } + } + + return 1; +} + +void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ) +{ + assert(EdgeIsInternal(edge)); + + TESShalfEdge *a0 = edge; + TESShalfEdge *a1 = a0->Lnext; + TESShalfEdge *a2 = a1->Lnext; + assert(a2->Lnext == a0); + TESShalfEdge *b0 = edge->Sym; + TESShalfEdge *b1 = b0->Lnext; + TESShalfEdge *b2 = b1->Lnext; + assert(b2->Lnext == b0); + + TESSvertex *aOrg = a0->Org; + TESSvertex *aOpp = a2->Org; + TESSvertex *bOrg = b0->Org; + TESSvertex *bOpp = b2->Org; + + TESSface *fa = a0->Lface; + TESSface *fb = b0->Lface; + + a0->Org = bOpp; + a0->Onext = b1->Sym; + b0->Org = aOpp; + b0->Onext = a1->Sym; + a2->Onext = b0; + b2->Onext = a0; + b1->Onext = a2->Sym; + a1->Onext = b2->Sym; + + a0->Lnext = a2; + a2->Lnext = b1; + b1->Lnext = a0; + + b0->Lnext = b2; + b2->Lnext = a1; + a1->Lnext = b0; + + a1->Lface = fb; + b1->Lface = fa; + + fa->anEdge = a0; + fb->anEdge = b0; + + if (aOrg->anEdge == a0) aOrg->anEdge = b1; + if (bOrg->anEdge == b0) bOrg->anEdge = a1; + + assert( a0->Lnext->Onext->Sym == a0 ); + assert( a0->Onext->Sym->Lnext == a0 ); + assert( a0->Org->anEdge->Org == a0->Org ); + + + assert( a1->Lnext->Onext->Sym == a1 ); + assert( a1->Onext->Sym->Lnext == a1 ); + assert( a1->Org->anEdge->Org == a1->Org ); + + assert( a2->Lnext->Onext->Sym == a2 ); + assert( a2->Onext->Sym->Lnext == a2 ); + assert( a2->Org->anEdge->Org == a2->Org ); + + assert( b0->Lnext->Onext->Sym == b0 ); + assert( b0->Onext->Sym->Lnext == b0 ); + assert( b0->Org->anEdge->Org == b0->Org ); + + assert( b1->Lnext->Onext->Sym == b1 ); + assert( b1->Onext->Sym->Lnext == b1 ); + assert( b1->Org->anEdge->Org == b1->Org ); + + assert( b2->Lnext->Onext->Sym == b2 ); + assert( b2->Onext->Sym->Lnext == b2 ); + assert( b2->Org->anEdge->Org == b2->Org ); + + assert(aOrg->anEdge->Org == aOrg); + assert(bOrg->anEdge->Org == bOrg); + + assert(a0->Oprev->Onext->Org == a0->Org); +} + +#ifdef DELETE_BY_ZAPPING + +/* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +*/ +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ) +{ + TESSface *fHead = &mesh->fHead; + + while( fHead->next != fHead ) { + tessMeshZapFace( fHead->next ); + } + assert( mesh->vHead.next == &mesh->vHead ); + + alloc->memfree( alloc->userData, mesh ); +} + +#else + +/* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +*/ +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ) +{ + deleteBucketAlloc(mesh->edgeBucket); + deleteBucketAlloc(mesh->vertexBucket); + deleteBucketAlloc(mesh->faceBucket); + + alloc->memfree( alloc->userData, mesh ); +} + +#endif + +#ifndef NDEBUG + +/* tessMeshCheckMesh( mesh ) checks a mesh for self-consistency. +*/ +void tessMeshCheckMesh( TESSmesh *mesh ) +{ + TESSface *fHead = &mesh->fHead; + TESSvertex *vHead = &mesh->vHead; + TESShalfEdge *eHead = &mesh->eHead; + TESSface *f, *fPrev; + TESSvertex *v, *vPrev; + TESShalfEdge *e, *ePrev; + + fPrev = fHead; + for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) { + assert( f->prev == fPrev ); + e = f->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Lface == f ); + e = e->Lnext; + } while( e != f->anEdge ); + } + assert( f->prev == fPrev && f->anEdge == NULL ); + + vPrev = vHead; + for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) { + assert( v->prev == vPrev ); + e = v->anEdge; + do { + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + assert( e->Org == v ); + e = e->Onext; + } while( e != v->anEdge ); + } + assert( v->prev == vPrev && v->anEdge == NULL ); + + ePrev = eHead; + for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) { + assert( e->Sym->next == ePrev->Sym ); + assert( e->Sym != e ); + assert( e->Sym->Sym == e ); + assert( e->Org != NULL ); + assert( e->Dst != NULL ); + assert( e->Lnext->Onext->Sym == e ); + assert( e->Onext->Sym->Lnext == e ); + } + assert( e->Sym->next == ePrev->Sym + && e->Sym == &mesh->eHeadSym + && e->Sym->Sym == e + && e->Org == NULL && e->Dst == NULL + && e->Lface == NULL && e->Rface == NULL ); +} + +#endif diff --git a/src/libtess2/Source/mesh.h b/src/libtess2/Source/mesh.h new file mode 100755 index 00000000..479c66f3 --- /dev/null +++ b/src/libtess2/Source/mesh.h @@ -0,0 +1,269 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef MESH_H +#define MESH_H + +#include "../Include/tesselator.h" + +typedef struct TESSmesh TESSmesh; +typedef struct TESSvertex TESSvertex; +typedef struct TESSface TESSface; +typedef struct TESShalfEdge TESShalfEdge; +typedef struct ActiveRegion ActiveRegion; + +/* The mesh structure is similar in spirit, notation, and operations +* to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives +* for the manipulation of general subdivisions and the computation of +* Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985). +* For a simplified description, see the course notes for CS348a, +* "Mathematical Foundations of Computer Graphics", available at the +* Stanford bookstore (and taught during the fall quarter). +* The implementation also borrows a tiny subset of the graph-based approach +* use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction +* to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988). +* +* The fundamental data structure is the "half-edge". Two half-edges +* go together to make an edge, but they point in opposite directions. +* Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym), +* its origin vertex (Org), the face on its left side (Lface), and the +* adjacent half-edges in the CCW direction around the origin vertex +* (Onext) and around the left face (Lnext). There is also a "next" +* pointer for the global edge list (see below). +* +* The notation used for mesh navigation: +* Sym = the mate of a half-edge (same edge, but opposite direction) +* Onext = edge CCW around origin vertex (keep same origin) +* Dnext = edge CCW around destination vertex (keep same dest) +* Lnext = edge CCW around left face (dest becomes new origin) +* Rnext = edge CCW around right face (origin becomes new dest) +* +* "prev" means to substitute CW for CCW in the definitions above. +* +* The mesh keeps global lists of all vertices, faces, and edges, +* stored as doubly-linked circular lists with a dummy header node. +* The mesh stores pointers to these dummy headers (vHead, fHead, eHead). +* +* The circular edge list is special; since half-edges always occur +* in pairs (e and e->Sym), each half-edge stores a pointer in only +* one direction. Starting at eHead and following the e->next pointers +* will visit each *edge* once (ie. e or e->Sym, but not both). +* e->Sym stores a pointer in the opposite direction, thus it is +* always true that e->Sym->next->Sym->next == e. +* +* Each vertex has a pointer to next and previous vertices in the +* circular list, and a pointer to a half-edge with this vertex as +* the origin (NULL if this is the dummy header). There is also a +* field "data" for client data. +* +* Each face has a pointer to the next and previous faces in the +* circular list, and a pointer to a half-edge with this face as +* the left face (NULL if this is the dummy header). There is also +* a field "data" for client data. +* +* Note that what we call a "face" is really a loop; faces may consist +* of more than one loop (ie. not simply connected), but there is no +* record of this in the data structure. The mesh may consist of +* several disconnected regions, so it may not be possible to visit +* the entire mesh by starting at a half-edge and traversing the edge +* structure. +* +* The mesh does NOT support isolated vertices; a vertex is deleted along +* with its last edge. Similarly when two faces are merged, one of the +* faces is deleted (see tessMeshDelete below). For mesh operations, +* all face (loop) and vertex pointers must not be NULL. However, once +* mesh manipulation is finished, TESSmeshZapFace can be used to delete +* faces of the mesh, one at a time. All external faces can be "zapped" +* before the mesh is returned to the client; then a NULL face indicates +* a region which is not part of the output polygon. +*/ + +struct TESSvertex { + TESSvertex *next; /* next vertex (never NULL) */ + TESSvertex *prev; /* previous vertex (never NULL) */ + TESShalfEdge *anEdge; /* a half-edge with this origin */ + + /* Internal data (keep hidden) */ + TESSreal coords[3]; /* vertex location in 3D */ + TESSreal s, t; /* projection onto the sweep plane */ + int pqHandle; /* to allow deletion from priority queue */ + TESSindex n; /* to allow identify unique vertices */ + TESSindex idx; /* to allow map result to original verts */ +}; + +struct TESSface { + TESSface *next; /* next face (never NULL) */ + TESSface *prev; /* previous face (never NULL) */ + TESShalfEdge *anEdge; /* a half edge with this left face */ + + /* Internal data (keep hidden) */ + TESSface *trail; /* "stack" for conversion to strips */ + TESSindex n; /* to allow identiy unique faces */ + char marked; /* flag for conversion to strips */ + char inside; /* this face is in the polygon interior */ +}; + +struct TESShalfEdge { + TESShalfEdge *next; /* doubly-linked list (prev==Sym->next) */ + TESShalfEdge *Sym; /* same edge, opposite direction */ + TESShalfEdge *Onext; /* next edge CCW around origin */ + TESShalfEdge *Lnext; /* next edge CCW around left face */ + TESSvertex *Org; /* origin vertex (Overtex too long) */ + TESSface *Lface; /* left face */ + + /* Internal data (keep hidden) */ + ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */ + int winding; /* change in winding number when crossing + from the right face to the left face */ + int mark; /* Used by the Edge Flip algorithm */ +}; + +#define Rface Sym->Lface +#define Dst Sym->Org + +#define Oprev Sym->Lnext +#define Lprev Onext->Sym +#define Dprev Lnext->Sym +#define Rprev Sym->Onext +#define Dnext Rprev->Sym /* 3 pointers */ +#define Rnext Oprev->Sym /* 3 pointers */ + +struct TESSmesh { + TESSvertex vHead; /* dummy header for vertex list */ + TESSface fHead; /* dummy header for face list */ + TESShalfEdge eHead; /* dummy header for edge list */ + TESShalfEdge eHeadSym; /* and its symmetric counterpart */ + + struct BucketAlloc* edgeBucket; + struct BucketAlloc* vertexBucket; + struct BucketAlloc* faceBucket; +}; + +/* The mesh operations below have three motivations: completeness, +* convenience, and efficiency. The basic mesh operations are MakeEdge, +* Splice, and Delete. All the other edge operations can be implemented +* in terms of these. The other operations are provided for convenience +* and/or efficiency. +* +* When a face is split or a vertex is added, they are inserted into the +* global list *before* the existing vertex or face (ie. e->Org or e->Lface). +* This makes it easier to process all vertices or faces in the global lists +* without worrying about processing the same data twice. As a convenience, +* when a face is split, the "inside" flag is copied from the old face. +* Other internal data (v->data, v->activeRegion, f->data, f->marked, +* f->trail, e->winding) is set to zero. +* +* ********************** Basic Edge Operations ************************** +* +* tessMeshMakeEdge( mesh ) creates one edge, two vertices, and a loop. +* The loop (face) consists of the two new half-edges. +* +* tessMeshSplice( eOrg, eDst ) is the basic operation for changing the +* mesh connectivity and topology. It changes the mesh so that +* eOrg->Onext <- OLD( eDst->Onext ) +* eDst->Onext <- OLD( eOrg->Onext ) +* where OLD(...) means the value before the meshSplice operation. +* +* This can have two effects on the vertex structure: +* - if eOrg->Org != eDst->Org, the two vertices are merged together +* - if eOrg->Org == eDst->Org, the origin is split into two vertices +* In both cases, eDst->Org is changed and eOrg->Org is untouched. +* +* Similarly (and independently) for the face structure, +* - if eOrg->Lface == eDst->Lface, one loop is split into two +* - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one +* In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. +* +* tessMeshDelete( eDel ) removes the edge eDel. There are several cases: +* if (eDel->Lface != eDel->Rface), we join two loops into one; the loop +* eDel->Lface is deleted. Otherwise, we are splitting one loop into two; +* the newly created loop will contain eDel->Dst. If the deletion of eDel +* would create isolated vertices, those are deleted as well. +* +* ********************** Other Edge Operations ************************** +* +* tessMeshAddEdgeVertex( eOrg ) creates a new edge eNew such that +* eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex. +* eOrg and eNew will have the same left face. +* +* tessMeshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, +* such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org. +* eOrg and eNew will have the same left face. +* +* tessMeshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst +* to eDst->Org, and returns the corresponding half-edge eNew. +* If eOrg->Lface == eDst->Lface, this splits one loop into two, +* and the newly created loop is eNew->Lface. Otherwise, two disjoint +* loops are merged into one, and the loop eDst->Lface is destroyed. +* +* ************************ Other Operations ***************************** +* +* tessMeshNewMesh() creates a new mesh with no edges, no vertices, +* and no loops (what we usually call a "face"). +* +* tessMeshUnion( mesh1, mesh2 ) forms the union of all structures in +* both meshes, and returns the new mesh (the old meshes are destroyed). +* +* tessMeshDeleteMesh( mesh ) will free all storage for any valid mesh. +* +* tessMeshZapFace( fZap ) destroys a face and removes it from the +* global face list. All edges of fZap will have a NULL pointer as their +* left face. Any edges which also have a NULL pointer as their right face +* are deleted entirely (along with any isolated vertices this produces). +* An entire mesh can be deleted by zapping its faces, one at a time, +* in any order. Zapped faces cannot be used in further mesh operations! +* +* tessMeshCheckMesh( mesh ) checks a mesh for self-consistency. +*/ + +TESShalfEdge *tessMeshMakeEdge( TESSmesh *mesh ); +int tessMeshSplice( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ); +int tessMeshDelete( TESSmesh *mesh, TESShalfEdge *eDel ); + +TESShalfEdge *tessMeshAddEdgeVertex( TESSmesh *mesh, TESShalfEdge *eOrg ); +TESShalfEdge *tessMeshSplitEdge( TESSmesh *mesh, TESShalfEdge *eOrg ); +TESShalfEdge *tessMeshConnect( TESSmesh *mesh, TESShalfEdge *eOrg, TESShalfEdge *eDst ); + +TESSmesh *tessMeshNewMesh( TESSalloc* alloc ); +TESSmesh *tessMeshUnion( TESSalloc* alloc, TESSmesh *mesh1, TESSmesh *mesh2 ); +int tessMeshMergeConvexFaces( TESSmesh *mesh, int maxVertsPerFace ); +void tessMeshDeleteMesh( TESSalloc* alloc, TESSmesh *mesh ); +void tessMeshZapFace( TESSmesh *mesh, TESSface *fZap ); + +void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ); + +#ifdef NDEBUG +#define tessMeshCheckMesh( mesh ) +#else +void tessMeshCheckMesh( TESSmesh *mesh ); +#endif + +#endif diff --git a/src/libtess2/Source/priorityq.c b/src/libtess2/Source/priorityq.c new file mode 100755 index 00000000..62a66545 --- /dev/null +++ b/src/libtess2/Source/priorityq.c @@ -0,0 +1,514 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +//#include "tesos.h" +#include +#include +#include "../Include/tesselator.h" +#include "priorityq.h" + + +#define INIT_SIZE 32 + +#define TRUE 1 +#define FALSE 0 + +#ifdef FOR_TRITE_TEST_PROGRAM +#define LEQ(x,y) (*pq->leq)(x,y) +#else +/* Violates modularity, but a little faster */ +#include "geom.h" +#define LEQ(x,y) VertLeq((TESSvertex *)x, (TESSvertex *)y) +#endif + + +/* Include all the code for the regular heap-based queue here. */ + +/* The basic operations are insertion of a new key (pqInsert), +* and examination/extraction of a key whose value is minimum +* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); +* for this purpose pqInsert returns a "handle" which is supplied +* as the argument. +* +* An initial heap may be created efficiently by calling pqInsert +* repeatedly, then calling pqInit. In any case pqInit must be called +* before any operations other than pqInsert are used. +* +* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. +* This may also be tested with pqIsEmpty. +*/ + + +/* Since we support deletion the data structure is a little more +* complicated than an ordinary heap. "nodes" is the heap itself; +* active nodes are stored in the range 1..pq->size. When the +* heap exceeds its allocated size (pq->max), its size doubles. +* The children of node i are nodes 2i and 2i+1. +* +* Each node stores an index into an array "handles". Each handle +* stores a key, plus a pointer back to the node which currently +* represents that key (ie. nodes[handles[i].node].handle == i). +*/ + + +#define pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key) +#define pqHeapIsEmpty(pq) ((pq)->size == 0) + + + +/* really pqHeapNewPriorityQHeap */ +PriorityQHeap *pqHeapNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQHeap *pq = (PriorityQHeap *)alloc->memalloc( alloc->userData, sizeof( PriorityQHeap )); + if (pq == NULL) return NULL; + + pq->size = 0; + pq->max = size; + pq->nodes = (PQnode *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->nodes[0]) ); + if (pq->nodes == NULL) { + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->handles = (PQhandleElem *)alloc->memalloc( alloc->userData, (size + 1) * sizeof(pq->handles[0]) ); + if (pq->handles == NULL) { + alloc->memfree( alloc->userData, pq->nodes ); + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->initialized = FALSE; + pq->freeList = 0; + pq->leq = leq; + + pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */ + pq->handles[1].key = NULL; + return pq; +} + +/* really pqHeapDeletePriorityQHeap */ +void pqHeapDeletePriorityQ( TESSalloc* alloc, PriorityQHeap *pq ) +{ + alloc->memfree( alloc->userData, pq->handles ); + alloc->memfree( alloc->userData, pq->nodes ); + alloc->memfree( alloc->userData, pq ); +} + + +static void FloatDown( PriorityQHeap *pq, int curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hChild; + int child; + + hCurr = n[curr].handle; + for( ;; ) { + child = curr << 1; + if( child < pq->size && LEQ( h[n[child+1].handle].key, + h[n[child].handle].key )) { + ++child; + } + + assert(child <= pq->max); + + hChild = n[child].handle; + if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } +} + + +static void FloatUp( PriorityQHeap *pq, int curr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hCurr, hParent; + int parent; + + hCurr = n[curr].handle; + for( ;; ) { + parent = curr >> 1; + hParent = n[parent].handle; + if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } +} + +/* really pqHeapInit */ +void pqHeapInit( PriorityQHeap *pq ) +{ + int i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for( i = pq->size; i >= 1; --i ) { + FloatDown( pq, i ); + } + pq->initialized = TRUE; +} + +/* really pqHeapInsert */ +/* returns INV_HANDLE iff out of memory */ +PQhandle pqHeapInsert( TESSalloc* alloc, PriorityQHeap *pq, PQkey keyNew ) +{ + int curr; + PQhandle free; + + curr = ++ pq->size; + if( (curr*2) > pq->max ) { + if (!alloc->memrealloc) + { + return INV_HANDLE; + } + else + { + PQnode *saveNodes= pq->nodes; + PQhandleElem *saveHandles= pq->handles; + + // If the heap overflows, double its size. + pq->max <<= 1; + pq->nodes = (PQnode *)alloc->memrealloc( alloc->userData, pq->nodes, + (size_t)((pq->max + 1) * sizeof( pq->nodes[0] ))); + if (pq->nodes == NULL) { + pq->nodes = saveNodes; // restore ptr to free upon return + return INV_HANDLE; + } + pq->handles = (PQhandleElem *)alloc->memrealloc( alloc->userData, pq->handles, + (size_t) ((pq->max + 1) * sizeof( pq->handles[0] ))); + if (pq->handles == NULL) { + pq->handles = saveHandles; // restore ptr to free upon return + return INV_HANDLE; + } + } + } + + if( pq->freeList == 0 ) { + free = curr; + } else { + free = pq->freeList; + pq->freeList = pq->handles[free].node; + } + + pq->nodes[curr].handle = free; + pq->handles[free].node = curr; + pq->handles[free].key = keyNew; + + if( pq->initialized ) { + FloatUp( pq, curr ); + } + assert(free != INV_HANDLE); + return free; +} + +/* really pqHeapExtractMin */ +PQkey pqHeapExtractMin( PriorityQHeap *pq ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + PQhandle hMin = n[1].handle; + PQkey min = h[hMin].key; + + if( pq->size > 0 ) { + n[1].handle = n[pq->size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = NULL; + h[hMin].node = pq->freeList; + pq->freeList = hMin; + + if( -- pq->size > 0 ) { + FloatDown( pq, 1 ); + } + } + return min; +} + +/* really pqHeapDelete */ +void pqHeapDelete( PriorityQHeap *pq, PQhandle hCurr ) +{ + PQnode *n = pq->nodes; + PQhandleElem *h = pq->handles; + int curr; + + assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL ); + + curr = h[hCurr].node; + n[curr].handle = n[pq->size].handle; + h[n[curr].handle].node = curr; + + if( curr <= -- pq->size ) { + if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) { + FloatDown( pq, curr ); + } else { + FloatUp( pq, curr ); + } + } + h[hCurr].key = NULL; + h[hCurr].node = pq->freeList; + pq->freeList = hCurr; +} + + + +/* Now redefine all the function names to map to their "Sort" versions. */ + +/* really tessPqSortNewPriorityQ */ +PriorityQ *pqNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ) +{ + PriorityQ *pq = (PriorityQ *)alloc->memalloc( alloc->userData, sizeof( PriorityQ )); + if (pq == NULL) return NULL; + + pq->heap = pqHeapNewPriorityQ( alloc, size, leq ); + if (pq->heap == NULL) { + alloc->memfree( alloc->userData, pq ); + return NULL; + } + +// pq->keys = (PQkey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) ); + pq->keys = (PQkey *)alloc->memalloc( alloc->userData, size * sizeof(pq->keys[0]) ); + if (pq->keys == NULL) { + pqHeapDeletePriorityQ( alloc, pq->heap ); + alloc->memfree( alloc->userData, pq ); + return NULL; + } + + pq->size = 0; + pq->max = size; //INIT_SIZE; + pq->initialized = FALSE; + pq->leq = leq; + + return pq; +} + +/* really tessPqSortDeletePriorityQ */ +void pqDeletePriorityQ( TESSalloc* alloc, PriorityQ *pq ) +{ + assert(pq != NULL); + if (pq->heap != NULL) pqHeapDeletePriorityQ( alloc, pq->heap ); + if (pq->order != NULL) alloc->memfree( alloc->userData, pq->order ); + if (pq->keys != NULL) alloc->memfree( alloc->userData, pq->keys ); + alloc->memfree( alloc->userData, pq ); +} + + +#define LT(x,y) (! LEQ(y,x)) +#define GT(x,y) (! LEQ(x,y)) +#define Swap(a,b) if(1){PQkey *tmp = *a; *a = *b; *b = tmp;}else + +/* really tessPqSortInit */ +int pqInit( TESSalloc* alloc, PriorityQ *pq ) +{ + PQkey **p, **r, **i, **j, *piv; + struct { PQkey **p, **r; } Stack[50], *top = Stack; + unsigned int seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ + /* + pq->order = (PQkey **)memAlloc( (size_t) + (pq->size * sizeof(pq->order[0])) ); + */ + pq->order = (PQkey **)alloc->memalloc( alloc->userData, + (size_t)((pq->size+1) * sizeof(pq->order[0])) ); + /* the previous line is a patch to compensate for the fact that IBM */ + /* machines return a null on a malloc of zero bytes (unlike SGI), */ + /* so we have to put in this defense to guard against a memory */ + /* fault four lines down. from fossum@austin.ibm.com. */ + if (pq->order == NULL) return 0; + + p = pq->order; + r = p + pq->size - 1; + for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) { + *i = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + top->p = p; top->r = r; ++top; + while( --top >= Stack ) { + p = top->p; + r = top->r; + while( r > p + 10 ) { + seed = seed * 1539415821 + 1; + i = p + seed % (r - p + 1); + piv = *i; + *i = *p; + *p = piv; + i = p - 1; + j = r + 1; + do { + do { ++i; } while( GT( **i, *piv )); + do { --j; } while( LT( **j, *piv )); + Swap( i, j ); + } while( i < j ); + Swap( i, j ); /* Undo last swap */ + if( i - p < r - j ) { + top->p = j+1; top->r = r; ++top; + r = i-1; + } else { + top->p = p; top->r = i-1; ++top; + p = j+1; + } + } + /* Insertion sort small lists */ + for( i = p+1; i <= r; ++i ) { + piv = *i; + for( j = i; j > p && LT( **(j-1), *piv ); --j ) { + *j = *(j-1); + } + *j = piv; + } + } + pq->max = pq->size; + pq->initialized = TRUE; + pqHeapInit( pq->heap ); /* always succeeds */ + +#ifndef NDEBUG + p = pq->order; + r = p + pq->size - 1; + for( i = p; i < r; ++i ) { + assert( LEQ( **(i+1), **i )); + } +#endif + + return 1; +} + +/* really tessPqSortInsert */ +/* returns INV_HANDLE iff out of memory */ +PQhandle pqInsert( TESSalloc* alloc, PriorityQ *pq, PQkey keyNew ) +{ + int curr; + + if( pq->initialized ) { + return pqHeapInsert( alloc, pq->heap, keyNew ); + } + curr = pq->size; + if( ++ pq->size >= pq->max ) { + if (!alloc->memrealloc) + { + return INV_HANDLE; + } + else + { + PQkey *saveKey= pq->keys; + // If the heap overflows, double its size. + pq->max <<= 1; + pq->keys = (PQkey *)alloc->memrealloc( alloc->userData, pq->keys, + (size_t)(pq->max * sizeof( pq->keys[0] ))); + if (pq->keys == NULL) { + pq->keys = saveKey; // restore ptr to free upon return + return INV_HANDLE; + } + } + } + assert(curr != INV_HANDLE); + pq->keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr+1); +} + +/* really tessPqSortExtractMin */ +PQkey pqExtractMin( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return pqHeapExtractMin( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! pqHeapIsEmpty( pq->heap )) { + heapMin = pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return pqHeapExtractMin( pq->heap ); + } + } + do { + -- pq->size; + } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ); + return sortMin; +} + +/* really tessPqSortMinimum */ +PQkey pqMinimum( PriorityQ *pq ) +{ + PQkey sortMin, heapMin; + + if( pq->size == 0 ) { + return pqHeapMinimum( pq->heap ); + } + sortMin = *(pq->order[pq->size-1]); + if( ! pqHeapIsEmpty( pq->heap )) { + heapMin = pqHeapMinimum( pq->heap ); + if( LEQ( heapMin, sortMin )) { + return heapMin; + } + } + return sortMin; +} + +/* really tessPqSortIsEmpty */ +int pqIsEmpty( PriorityQ *pq ) +{ + return (pq->size == 0) && pqHeapIsEmpty( pq->heap ); +} + +/* really tessPqSortDelete */ +void pqDelete( PriorityQ *pq, PQhandle curr ) +{ + if( curr >= 0 ) { + pqHeapDelete( pq->heap, curr ); + return; + } + curr = -(curr+1); + assert( curr < pq->max && pq->keys[curr] != NULL ); + + pq->keys[curr] = NULL; + while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) { + -- pq->size; + } +} diff --git a/src/libtess2/Source/priorityq.h b/src/libtess2/Source/priorityq.h new file mode 100755 index 00000000..6ef1c05f --- /dev/null +++ b/src/libtess2/Source/priorityq.h @@ -0,0 +1,104 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef PRIORITYQ_H +#define PRIORITYQ_H + +/* The basic operations are insertion of a new key (pqInsert), +* and examination/extraction of a key whose value is minimum +* (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete); +* for this purpose pqInsert returns a "handle" which is supplied +* as the argument. +* +* An initial heap may be created efficiently by calling pqInsert +* repeatedly, then calling pqInit. In any case pqInit must be called +* before any operations other than pqInsert are used. +* +* If the heap is empty, pqMinimum/pqExtractMin will return a NULL key. +* This may also be tested with pqIsEmpty. +*/ + +/* Since we support deletion the data structure is a little more +* complicated than an ordinary heap. "nodes" is the heap itself; +* active nodes are stored in the range 1..pq->size. When the +* heap exceeds its allocated size (pq->max), its size doubles. +* The children of node i are nodes 2i and 2i+1. +* +* Each node stores an index into an array "handles". Each handle +* stores a key, plus a pointer back to the node which currently +* represents that key (ie. nodes[handles[i].node].handle == i). +*/ + +typedef void *PQkey; +typedef int PQhandle; +typedef struct PriorityQHeap PriorityQHeap; + +#define INV_HANDLE 0x0fffffff + +typedef struct { PQhandle handle; } PQnode; +typedef struct { PQkey key; PQhandle node; } PQhandleElem; + +struct PriorityQHeap { + + PQnode *nodes; + PQhandleElem *handles; + int size, max; + PQhandle freeList; + int initialized; + + int (*leq)(PQkey key1, PQkey key2); +}; + +typedef struct PriorityQ PriorityQ; + +struct PriorityQ { + PriorityQHeap *heap; + + PQkey *keys; + PQkey **order; + PQhandle size, max; + int initialized; + + int (*leq)(PQkey key1, PQkey key2); +}; + +PriorityQ *pqNewPriorityQ( TESSalloc* alloc, int size, int (*leq)(PQkey key1, PQkey key2) ); +void pqDeletePriorityQ( TESSalloc* alloc, PriorityQ *pq ); + +int pqInit( TESSalloc* alloc, PriorityQ *pq ); +PQhandle pqInsert( TESSalloc* alloc, PriorityQ *pq, PQkey key ); +PQkey pqExtractMin( PriorityQ *pq ); +void pqDelete( PriorityQ *pq, PQhandle handle ); + +PQkey pqMinimum( PriorityQ *pq ); +int pqIsEmpty( PriorityQ *pq ); + +#endif diff --git a/src/libtess2/Source/sweep.c b/src/libtess2/Source/sweep.c new file mode 100755 index 00000000..73da9353 --- /dev/null +++ b/src/libtess2/Source/sweep.c @@ -0,0 +1,1323 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include +#include /* longjmp */ + +#include "mesh.h" +#include "geom.h" +#include "tess.h" +#include "dict.h" +#include "priorityq.h" +#include "bucketalloc.h" +#include "sweep.h" + +#define TRUE 1 +#define FALSE 0 + +#ifdef FOR_TRITE_TEST_PROGRAM +extern void DebugEvent( TESStesselator *tess ); +#else +#define DebugEvent( tess ) +#endif + +/* +* Invariants for the Edge Dictionary. +* - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) +* at any valid location of the sweep event +* - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 +* share a common endpoint +* - for each e, e->Dst has been processed, but not e->Org +* - each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org) +* where "event" is the current sweep line event. +* - no edge e has zero length +* +* Invariants for the Mesh (the processed portion). +* - the portion of the mesh left of the sweep line is a planar graph, +* ie. there is *some* way to embed it in the plane +* - no processed edge has zero length +* - no two processed vertices have identical coordinates +* - each "inside" region is monotone, ie. can be broken into two chains +* of monotonically increasing vertices according to VertLeq(v1,v2) +* - a non-invariant: these chains may intersect (very slightly) +* +* Invariants for the Sweep. +* - if none of the edges incident to the event vertex have an activeRegion +* (ie. none of these edges are in the edge dictionary), then the vertex +* has only right-going edges. +* - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced +* by ConnectRightVertex), then it is the only right-going edge from +* its associated vertex. (This says that these edges exist only +* when it is necessary.) +*/ + +#define MAX(x,y) ((x) >= (y) ? (x) : (y)) +#define MIN(x,y) ((x) <= (y) ? (x) : (y)) + +/* When we merge two edges into one, we need to compute the combined +* winding of the new edge. +*/ +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +static void SweepEvent( TESStesselator *tess, TESSvertex *vEvent ); +static void WalkDirtyRegions( TESStesselator *tess, ActiveRegion *regUp ); +static int CheckForRightSplice( TESStesselator *tess, ActiveRegion *regUp ); + +static int EdgeLeq( TESStesselator *tess, ActiveRegion *reg1, ActiveRegion *reg2 ) +/* +* Both edges must be directed from right to left (this is the canonical +* direction for the upper edge of each region). +* +* The strategy is to evaluate a "t" value for each edge at the +* current sweep line position, given by tess->event. The calculations +* are designed to be very stable, but of course they are not perfect. +* +* Special case: if both edge destinations are at the sweep event, +* we sort the edges by slope (they would otherwise compare equally). +*/ +{ + TESSvertex *event = tess->event; + TESShalfEdge *e1, *e2; + TESSreal t1, t2; + + e1 = reg1->eUp; + e2 = reg2->eUp; + + if( e1->Dst == event ) { + if( e2->Dst == event ) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if( VertLeq( e1->Org, e2->Org )) { + return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0; + } + return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0; + } + return EdgeSign( e2->Dst, event, e2->Org ) <= 0; + } + if( e2->Dst == event ) { + return EdgeSign( e1->Dst, event, e1->Org ) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = EdgeEval( e1->Dst, event, e1->Org ); + t2 = EdgeEval( e2->Dst, event, e2->Org ); + return (t1 >= t2); +} + + +static void DeleteRegion( TESStesselator *tess, ActiveRegion *reg ) +{ + if( reg->fixUpperEdge ) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert( reg->eUp->winding == 0 ); + } + reg->eUp->activeRegion = NULL; + dictDelete( tess->dict, reg->nodeUp ); + bucketFree( tess->regionPool, reg ); +} + + +static int FixUpperEdge( TESStesselator *tess, ActiveRegion *reg, TESShalfEdge *newEdge ) +/* +* Replace an upper edge which needs fixing (see ConnectRightVertex). +*/ +{ + assert( reg->fixUpperEdge ); + if ( !tessMeshDelete( tess->mesh, reg->eUp ) ) return 0; + reg->fixUpperEdge = FALSE; + reg->eUp = newEdge; + newEdge->activeRegion = reg; + + return 1; +} + +static ActiveRegion *TopLeftRegion( TESStesselator *tess, ActiveRegion *reg ) +{ + TESSvertex *org = reg->eUp->Org; + TESShalfEdge *e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Org == org ); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if( reg->fixUpperEdge ) { + e = tessMeshConnect( tess->mesh, RegionBelow(reg)->eUp->Sym, reg->eUp->Lnext ); + if (e == NULL) return NULL; + if ( !FixUpperEdge( tess, reg, e ) ) return NULL; + reg = RegionAbove( reg ); + } + return reg; +} + +static ActiveRegion *TopRightRegion( ActiveRegion *reg ) +{ + TESSvertex *dst = reg->eUp->Dst; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove( reg ); + } while( reg->eUp->Dst == dst ); + return reg; +} + +static ActiveRegion *AddRegionBelow( TESStesselator *tess, + ActiveRegion *regAbove, + TESShalfEdge *eNewUp ) +/* +* Add a new active region to the sweep line, *somewhere* below "regAbove" +* (according to where the new edge belongs in the sweep-line dictionary). +* The upper edge of the new region will be "eNewUp". +* Winding number and "inside" flag are not updated. +*/ +{ + ActiveRegion *regNew = (ActiveRegion *)bucketAlloc( tess->regionPool ); + if (regNew == NULL) longjmp(tess->env,1); + + regNew->eUp = eNewUp; + regNew->nodeUp = dictInsertBefore( tess->dict, regAbove->nodeUp, regNew ); + if (regNew->nodeUp == NULL) longjmp(tess->env,1); + regNew->fixUpperEdge = FALSE; + regNew->sentinel = FALSE; + regNew->dirty = FALSE; + + eNewUp->activeRegion = regNew; + return regNew; +} + +static int IsWindingInside( TESStesselator *tess, int n ) +{ + switch( tess->windingRule ) { + case TESS_WINDING_ODD: + return (n & 1); + case TESS_WINDING_NONZERO: + return (n != 0); + case TESS_WINDING_POSITIVE: + return (n > 0); + case TESS_WINDING_NEGATIVE: + return (n < 0); + case TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ + assert( FALSE ); + /*NOTREACHED*/ + + return( FALSE ); +} + + +static void ComputeWinding( TESStesselator *tess, ActiveRegion *reg ) +{ + reg->windingNumber = RegionAbove(reg)->windingNumber + reg->eUp->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); +} + + +static void FinishRegion( TESStesselator *tess, ActiveRegion *reg ) +/* +* Delete a region from the sweep line. This happens when the upper +* and lower chains of a region meet (at a vertex on the sweep line). +* The "inside" flag is copied to the appropriate mesh face (we could +* not do this before -- since the structure of the mesh is always +* changing, this face may not have even existed until now). +*/ +{ + TESShalfEdge *e = reg->eUp; + TESSface *f = e->Lface; + + f->inside = reg->inside; + f->anEdge = e; /* optimization for tessMeshTessellateMonoRegion() */ + DeleteRegion( tess, reg ); +} + + +static TESShalfEdge *FinishLeftRegions( TESStesselator *tess, + ActiveRegion *regFirst, ActiveRegion *regLast ) +/* +* We are given a vertex with one or more left-going edges. All affected +* edges should be in the edge dictionary. Starting at regFirst->eUp, +* we walk down deleting all regions where both edges have the same +* origin vOrg. At the same time we copy the "inside" flag from the +* active region to the face, since at this point each face will belong +* to at most one region (this was not necessarily true until this point +* in the sweep). The walk stops at the region above regLast; if regLast +* is NULL we walk as far as possible. At the same time we relink the +* mesh if necessary, so that the ordering of edges around vOrg is the +* same as in the dictionary. +*/ +{ + ActiveRegion *reg, *regPrev; + TESShalfEdge *e, *ePrev; + + regPrev = regFirst; + ePrev = regFirst->eUp; + while( regPrev != regLast ) { + regPrev->fixUpperEdge = FALSE; /* placement was OK */ + reg = RegionBelow( regPrev ); + e = reg->eUp; + if( e->Org != ePrev->Org ) { + if( ! reg->fixUpperEdge ) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion( tess, regPrev ); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = tessMeshConnect( tess->mesh, ePrev->Lprev, e->Sym ); + if (e == NULL) longjmp(tess->env,1); + if ( !FixUpperEdge( tess, reg, e ) ) longjmp(tess->env,1); + } + + /* Relink edges so that ePrev->Onext == e */ + if( ePrev->Onext != e ) { + if ( !tessMeshSplice( tess->mesh, e->Oprev, e ) ) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, ePrev, e ) ) longjmp(tess->env,1); + } + FinishRegion( tess, regPrev ); /* may change reg->eUp */ + ePrev = reg->eUp; + regPrev = reg; + } + return ePrev; +} + + +static void AddRightEdges( TESStesselator *tess, ActiveRegion *regUp, + TESShalfEdge *eFirst, TESShalfEdge *eLast, TESShalfEdge *eTopLeft, + int cleanUp ) +/* +* Purpose: insert right-going edges into the edge dictionary, and update +* winding numbers and mesh connectivity appropriately. All right-going +* edges share a common origin vOrg. Edges are inserted CCW starting at +* eFirst; the last edge inserted is eLast->Oprev. If vOrg has any +* left-going edges already processed, then eTopLeft must be the edge +* such that an imaginary upward vertical segment from vOrg would be +* contained between eTopLeft->Oprev and eTopLeft; otherwise eTopLeft +* should be NULL. +*/ +{ + ActiveRegion *reg, *regPrev; + TESShalfEdge *e, *ePrev; + int firstTime = TRUE; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert( VertLeq( e->Org, e->Dst )); + AddRegionBelow( tess, regUp, e->Sym ); + e = e->Onext; + } while ( e != eLast ); + + /* Walk *all* right-going edges from e->Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if( eTopLeft == NULL ) { + eTopLeft = RegionBelow( regUp )->eUp->Rprev; + } + regPrev = regUp; + ePrev = eTopLeft; + for( ;; ) { + reg = RegionBelow( regPrev ); + e = reg->eUp->Sym; + if( e->Org != ePrev->Org ) break; + + if( e->Onext != ePrev ) { + /* Unlink e from its current position, and relink below ePrev */ + if ( !tessMeshSplice( tess->mesh, e->Oprev, e ) ) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, ePrev->Oprev, e ) ) longjmp(tess->env,1); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg->windingNumber = regPrev->windingNumber - e->winding; + reg->inside = IsWindingInside( tess, reg->windingNumber ); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in tessComputeInterior). + */ + regPrev->dirty = TRUE; + if( ! firstTime && CheckForRightSplice( tess, regPrev )) { + AddWinding( e, ePrev ); + DeleteRegion( tess, regPrev ); + if ( !tessMeshDelete( tess->mesh, ePrev ) ) longjmp(tess->env,1); + } + firstTime = FALSE; + regPrev = reg; + ePrev = e; + } + regPrev->dirty = TRUE; + assert( regPrev->windingNumber - e->winding == reg->windingNumber ); + + if( cleanUp ) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions( tess, regPrev ); + } +} + + +static void SpliceMergeVertices( TESStesselator *tess, TESShalfEdge *e1, + TESShalfEdge *e2 ) +/* +* Two vertices with idential coordinates are combined into one. +* e1->Org is kept, while e2->Org is discarded. +*/ +{ + if ( !tessMeshSplice( tess->mesh, e1, e2 ) ) longjmp(tess->env,1); +} + +static void VertexWeights( TESSvertex *isect, TESSvertex *org, TESSvertex *dst, + TESSreal *weights ) +/* +* Find some weights which describe how the intersection vertex is +* a linear combination of "org" and "dest". Each of the two edges +* which generated "isect" is allocated 50% of the weight; each edge +* splits the weight between its org and dst according to the +* relative distance to "isect". +*/ +{ + TESSreal t1 = VertL1dist( org, isect ); + TESSreal t2 = VertL1dist( dst, isect ); + + weights[0] = (TESSreal)0.5 * t2 / (t1 + t2); + weights[1] = (TESSreal)0.5 * t1 / (t1 + t2); + isect->coords[0] += weights[0]*org->coords[0] + weights[1]*dst->coords[0]; + isect->coords[1] += weights[0]*org->coords[1] + weights[1]*dst->coords[1]; + isect->coords[2] += weights[0]*org->coords[2] + weights[1]*dst->coords[2]; +} + + +static void GetIntersectData( TESStesselator *tess, TESSvertex *isect, + TESSvertex *orgUp, TESSvertex *dstUp, + TESSvertex *orgLo, TESSvertex *dstLo ) + /* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ +{ + TESSreal weights[4]; + TESS_NOTUSED( tess ); + + isect->coords[0] = isect->coords[1] = isect->coords[2] = 0; + isect->idx = TESS_UNDEF; + VertexWeights( isect, orgUp, dstUp, &weights[0] ); + VertexWeights( isect, orgLo, dstLo, &weights[2] ); +} + +static int CheckForRightSplice( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edge of "regUp", to make sure that the +* eUp->Org is above eLo, or eLo->Org is below eUp (depending on which +* origin is leftmost). +* +* The main purpose is to splice right-going edges with the same +* dest vertex and nearly identical slopes (ie. we can't distinguish +* the slopes numerically). However the splicing can also help us +* to recover from numerical errors. For example, suppose at one +* point we checked eUp and eLo, and decided that eUp->Org is barely +* above eLo. Then later, we split eLo into two edges (eg. from +* a splice operation like this one). This can change the result of +* our test so that now eUp->Org is incident to eLo, or barely below it. +* We must correct this condition to maintain the dictionary invariants. +* +* One possibility is to check these edges for intersection again +* (ie. CheckForIntersect). This is what we do if possible. However +* CheckForIntersect requires that tess->event lies between eUp and eLo, +* so that it has something to fall back on when the intersection +* calculation gives us an unusable answer. So, for those cases where +* we can't check for intersection, this routine fixes the problem +* by just splicing the offending vertex into the other edge. +* This is a guaranteed solution, no matter how degenerate things get. +* Basically this is a combinatorial solution to a numerical problem. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + + if( VertLeq( eUp->Org, eLo->Org )) { + if( EdgeSign( eLo->Dst, eUp->Org, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Org appears to be below eLo */ + if( ! VertEq( eUp->Org, eLo->Org )) { + /* Splice eUp->Org into eLo */ + if ( tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp, eLo->Oprev ) ) longjmp(tess->env,1); + regUp->dirty = regLo->dirty = TRUE; + + } else if( eUp->Org != eLo->Org ) { + /* merge the two vertices, discarding eUp->Org */ + pqDelete( tess->pq, eUp->Org->pqHandle ); + SpliceMergeVertices( tess, eLo->Oprev, eUp ); + } + } else { + if( EdgeSign( eUp->Dst, eLo->Org, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Org appears to be above eUp, so splice eLo->Org into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); + } + return TRUE; +} + +static int CheckForLeftSplice( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edge of "regUp", to make sure that the +* eUp->Dst is above eLo, or eLo->Dst is below eUp (depending on which +* destination is rightmost). +* +* Theoretically, this should always be true. However, splitting an edge +* into two pieces can change the results of previous tests. For example, +* suppose at one point we checked eUp and eLo, and decided that eUp->Dst +* is barely above eLo. Then later, we split eLo into two edges (eg. from +* a splice operation like this one). This can change the result of +* the test so that now eUp->Dst is incident to eLo, or barely below it. +* We must correct this condition to maintain the dictionary invariants +* (otherwise new edges might get inserted in the wrong place in the +* dictionary, and bad stuff will happen). +* +* We fix the problem by just splicing the offending vertex into the +* other edge. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + TESShalfEdge *e; + + assert( ! VertEq( eUp->Dst, eLo->Dst )); + + if( VertLeq( eUp->Dst, eLo->Dst )) { + if( EdgeSign( eUp->Dst, eLo->Dst, eUp->Org ) < 0 ) return FALSE; + + /* eLo->Dst is above eUp, so splice eLo->Dst into eUp */ + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + e = tessMeshSplitEdge( tess->mesh, eUp ); + if (e == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Sym, e ) ) longjmp(tess->env,1); + e->Lface->inside = regUp->inside; + } else { + if( EdgeSign( eLo->Dst, eUp->Dst, eLo->Org ) > 0 ) return FALSE; + + /* eUp->Dst is below eLo, so splice eUp->Dst into eLo */ + regUp->dirty = regLo->dirty = TRUE; + e = tessMeshSplitEdge( tess->mesh, eLo ); + if (e == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Sym ) ) longjmp(tess->env,1); + e->Rface->inside = regUp->inside; + } + return TRUE; +} + + +static int CheckForIntersect( TESStesselator *tess, ActiveRegion *regUp ) +/* +* Check the upper and lower edges of the given region to see if +* they intersect. If so, create the intersection and add it +* to the data structures. +* +* Returns TRUE if adding the new intersection resulted in a recursive +* call to AddRightEdges(); in this case all "dirty" regions have been +* checked for intersections, and possibly regUp has been deleted. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + TESSvertex *orgUp = eUp->Org; + TESSvertex *orgLo = eLo->Org; + TESSvertex *dstUp = eUp->Dst; + TESSvertex *dstLo = eLo->Dst; + TESSreal tMinUp, tMaxLo; + TESSvertex isect, *orgMin; + TESShalfEdge *e; + + assert( ! VertEq( dstLo, dstUp )); + assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 ); + assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 ); + assert( orgUp != tess->event && orgLo != tess->event ); + assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge ); + + if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */ + + tMinUp = MIN( orgUp->t, dstUp->t ); + tMaxLo = MAX( orgLo->t, dstLo->t ); + if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */ + + if( VertLeq( orgUp, orgLo )) { + if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE; + } else { + if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent( tess ); + + tesedgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect ); + /* The following properties are guaranteed: */ + assert( MIN( orgUp->t, dstUp->t ) <= isect.t ); + assert( isect.t <= MAX( orgLo->t, dstLo->t )); + assert( MIN( dstLo->s, dstUp->s ) <= isect.s ); + assert( isect.s <= MAX( orgLo->s, orgUp->s )); + + if( VertLeq( &isect, tess->event )) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess->event. + */ + isect.s = tess->event->s; + isect.t = tess->event->t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo; + if( VertLeq( orgMin, &isect )) { + isect.s = orgMin->s; + isect.t = orgMin->t; + } + + if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) { + /* Easy case -- intersection at one of the right endpoints */ + (void) CheckForRightSplice( tess, regUp ); + return FALSE; + } + + if( (! VertEq( dstUp, tess->event ) + && EdgeSign( dstUp, tess->event, &isect ) >= 0) + || (! VertEq( dstLo, tess->event ) + && EdgeSign( dstLo, tess->event, &isect ) <= 0 )) + { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if( dstLo == tess->event ) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Sym, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( tess, regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eUp = RegionBelow(regUp)->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE ); + return TRUE; + } + if( dstUp == tess->event ) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1); + regLo = regUp; + regUp = TopRightRegion( regUp ); + e = RegionBelow(regUp)->eUp->Rprev; + regLo->eUp = eLo->Oprev; + eLo = FinishLeftRegions( tess, regLo, NULL ); + AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE ); + return TRUE; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess->event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) { + RegionAbove(regUp)->dirty = regUp->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + eUp->Org->s = tess->event->s; + eUp->Org->t = tess->event->t; + } + if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) { + regUp->dirty = regLo->dirty = TRUE; + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + eLo->Org->s = tess->event->s; + eLo->Org->t = tess->event->t; + } + /* leave the rest for ConnectRightVertex */ + return FALSE; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp->Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo->Oprev->Lface). + */ + if (tessMeshSplitEdge( tess->mesh, eUp->Sym ) == NULL) longjmp(tess->env,1); + if (tessMeshSplitEdge( tess->mesh, eLo->Sym ) == NULL) longjmp(tess->env,1); + if ( !tessMeshSplice( tess->mesh, eLo->Oprev, eUp ) ) longjmp(tess->env,1); + eUp->Org->s = isect.s; + eUp->Org->t = isect.t; + eUp->Org->pqHandle = pqInsert( &tess->alloc, tess->pq, eUp->Org ); + if (eUp->Org->pqHandle == INV_HANDLE) { + pqDeletePriorityQ( &tess->alloc, tess->pq ); + tess->pq = NULL; + longjmp(tess->env,1); + } + GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo ); + RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE; + return FALSE; +} + +static void WalkDirtyRegions( TESStesselator *tess, ActiveRegion *regUp ) +/* +* When the upper or lower edge of any region changes, the region is +* marked "dirty". This routine walks through all the dirty regions +* and makes sure that the dictionary invariants are satisfied +* (see the comments at the beginning of this file). Of course +* new dirty regions can be created as we make changes to restore +* the invariants. +*/ +{ + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp, *eLo; + + for( ;; ) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while( regLo->dirty ) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if( ! regUp->dirty ) { + regLo = regUp; + regUp = RegionAbove( regUp ); + if( regUp == NULL || ! regUp->dirty ) { + /* We've walked all the dirty regions */ + return; + } + } + regUp->dirty = FALSE; + eUp = regUp->eUp; + eLo = regLo->eUp; + + if( eUp->Dst != eLo->Dst ) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if( CheckForLeftSplice( tess, regUp )) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if( regLo->fixUpperEdge ) { + DeleteRegion( tess, regLo ); + if ( !tessMeshDelete( tess->mesh, eLo ) ) longjmp(tess->env,1); + regLo = RegionBelow( regUp ); + eLo = regLo->eUp; + } else if( regUp->fixUpperEdge ) { + DeleteRegion( tess, regUp ); + if ( !tessMeshDelete( tess->mesh, eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + eUp = regUp->eUp; + } + } + } + if( eUp->Org != eLo->Org ) { + if( eUp->Dst != eLo->Dst + && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge + && (eUp->Dst == tess->event || eLo->Dst == tess->event) ) + { + /* When all else fails in CheckForIntersect(), it uses tess->event + * as the intersection location. To make this possible, it requires + * that tess->event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess->event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if( CheckForIntersect( tess, regUp )) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + (void) CheckForRightSplice( tess, regUp ); + } + } + if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding( eLo, eUp ); + DeleteRegion( tess, regUp ); + if ( !tessMeshDelete( tess->mesh, eUp ) ) longjmp(tess->env,1); + regUp = RegionAbove( regLo ); + } + } +} + + +static void ConnectRightVertex( TESStesselator *tess, ActiveRegion *regUp, + TESShalfEdge *eBottomLeft ) +/* +* Purpose: connect a "right" vertex vEvent (one where all edges go left) +* to the unprocessed portion of the mesh. Since there are no right-going +* edges, two regions (one above vEvent and one below) are being merged +* into one. "regUp" is the upper of these two regions. +* +* There are two reasons for doing this (adding a right-going edge): +* - if the two regions being merged are "inside", we must add an edge +* to keep them separated (the combined region would not be monotone). +* - in any case, we must leave some record of vEvent in the dictionary, +* so that we can merge vEvent with features that we have not seen yet. +* For example, maybe there is a vertical edge which passes just to +* the right of vEvent; we would like to splice vEvent into this edge. +* +* However, we don't want to connect vEvent to just any vertex. We don''t +* want the new edge to cross any other edges; otherwise we will create +* intersection vertices even when the input data had no self-intersections. +* (This is a bad thing; if the user's input data has no intersections, +* we don't want to generate any false intersections ourselves.) +* +* Our eventual goal is to connect vEvent to the leftmost unprocessed +* vertex of the combined region (the union of regUp and regLo). +* But because of unseen vertices with all right-going edges, and also +* new vertices which may be created by edge intersections, we don''t +* know where that leftmost unprocessed vertex is. In the meantime, we +* connect vEvent to the closest vertex of either chain, and mark the region +* as "fixUpperEdge". This flag says to delete and reconnect this edge +* to the next processed vertex on the boundary of the combined region. +* Quite possibly the vertex we connected to will turn out to be the +* closest one, in which case we won''t need to make any changes. +*/ +{ + TESShalfEdge *eNew; + TESShalfEdge *eTopLeft = eBottomLeft->Onext; + ActiveRegion *regLo = RegionBelow(regUp); + TESShalfEdge *eUp = regUp->eUp; + TESShalfEdge *eLo = regLo->eUp; + int degenerate = FALSE; + + if( eUp->Dst != eLo->Dst ) { + (void) CheckForIntersect( tess, regUp ); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if( VertEq( eUp->Org, tess->event )) { + if ( !tessMeshSplice( tess->mesh, eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1); + regUp = TopLeftRegion( tess, regUp ); + if (regUp == NULL) longjmp(tess->env,1); + eTopLeft = RegionBelow( regUp )->eUp; + FinishLeftRegions( tess, RegionBelow(regUp), regLo ); + degenerate = TRUE; + } + if( VertEq( eLo->Org, tess->event )) { + if ( !tessMeshSplice( tess->mesh, eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1); + eBottomLeft = FinishLeftRegions( tess, regLo, NULL ); + degenerate = TRUE; + } + if( degenerate ) { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo->Org, eUp->Org. + */ + if( VertLeq( eLo->Org, eUp->Org )) { + eNew = eLo->Oprev; + } else { + eNew = eUp; + } + eNew = tessMeshConnect( tess->mesh, eBottomLeft->Lprev, eNew ); + if (eNew == NULL) longjmp(tess->env,1); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE ); + eNew->Sym->activeRegion->fixUpperEdge = TRUE; + WalkDirtyRegions( tess, regUp ); +} + +/* Because vertices at exactly the same location are merged together +* before we process the sweep event, some degenerate cases can't occur. +* However if someone eventually makes the modifications required to +* merge features which are close together, the cases below marked +* TOLERANCE_NONZERO will be useful. They were debugged before the +* code to merge identical vertices in the main loop was added. +*/ +#define TOLERANCE_NONZERO FALSE + +static void ConnectLeftDegenerate( TESStesselator *tess, + ActiveRegion *regUp, TESSvertex *vEvent ) +/* +* The event vertex lies exacty on an already-processed edge or vertex. +* Adding the new vertex involves splicing it into the already-processed +* part of the mesh. +*/ +{ + TESShalfEdge *e, *eTopLeft, *eTopRight, *eLast; + ActiveRegion *reg; + + e = regUp->eUp; + if( VertEq( e->Org, vEvent )) { + /* e->Org is an unprocessed vertex - just combine them, and wait + * for e->Org to be pulled from the queue + */ + assert( TOLERANCE_NONZERO ); + SpliceMergeVertices( tess, e, vEvent->anEdge ); + return; + } + + if( ! VertEq( e->Dst, vEvent )) { + /* General case -- splice vEvent into edge e which passes through it */ + if (tessMeshSplitEdge( tess->mesh, e->Sym ) == NULL) longjmp(tess->env,1); + if( regUp->fixUpperEdge ) { + /* This edge was fixable -- delete unused portion of original edge */ + if ( !tessMeshDelete( tess->mesh, e->Onext ) ) longjmp(tess->env,1); + regUp->fixUpperEdge = FALSE; + } + if ( !tessMeshSplice( tess->mesh, vEvent->anEdge, e ) ) longjmp(tess->env,1); + SweepEvent( tess, vEvent ); /* recurse */ + return; + } + + /* vEvent coincides with e->Dst, which has already been processed. + * Splice in the additional right-going edges. + */ + assert( TOLERANCE_NONZERO ); + regUp = TopRightRegion( regUp ); + reg = RegionBelow( regUp ); + eTopRight = reg->eUp->Sym; + eTopLeft = eLast = eTopRight->Onext; + if( reg->fixUpperEdge ) { + /* Here e->Dst has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert( eTopLeft != eTopRight ); /* there are some left edges too */ + DeleteRegion( tess, reg ); + if ( !tessMeshDelete( tess->mesh, eTopRight ) ) longjmp(tess->env,1); + eTopRight = eTopLeft->Oprev; + } + if ( !tessMeshSplice( tess->mesh, vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1); + if( ! EdgeGoesLeft( eTopLeft )) { + /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = NULL; + } + AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE ); +} + + +static void ConnectLeftVertex( TESStesselator *tess, TESSvertex *vEvent ) +/* +* Purpose: connect a "left" vertex (one where both edges go right) +* to the processed portion of the mesh. Let R be the active region +* containing vEvent, and let U and L be the upper and lower edge +* chains of R. There are two possibilities: +* +* - the normal case: split R into two regions, by connecting vEvent to +* the rightmost vertex of U or L lying to the left of the sweep line +* +* - the degenerate case: if vEvent is close enough to U or L, we +* merge vEvent into that edge chain. The subcases are: +* - merging with the rightmost vertex of U or L +* - merging with the active edge of U or L +* - merging with an already-processed portion of U or L +*/ +{ + ActiveRegion *regUp, *regLo, *reg; + TESShalfEdge *eUp, *eLo, *eNew; + ActiveRegion tmp; + + /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent->anEdge->Sym; + /* __GL_DICTLISTKEY */ /* tessDictListSearch */ + regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp )); + regLo = RegionBelow( regUp ); + if( !regLo ) { + // This may happen if the input polygon is coplanar. + return; + } + eUp = regUp->eUp; + eLo = regLo->eUp; + + /* Try merging with U or L first */ + if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) { + ConnectLeftDegenerate( tess, regUp, vEvent ); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e->Dst is the vertex that we will connect to vEvent. + */ + reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo; + + if( regUp->inside || reg->fixUpperEdge) { + if( reg == regUp ) { + eNew = tessMeshConnect( tess->mesh, vEvent->anEdge->Sym, eUp->Lnext ); + if (eNew == NULL) longjmp(tess->env,1); + } else { + TESShalfEdge *tempHalfEdge= tessMeshConnect( tess->mesh, eLo->Dnext, vEvent->anEdge); + if (tempHalfEdge == NULL) longjmp(tess->env,1); + + eNew = tempHalfEdge->Sym; + } + if( reg->fixUpperEdge ) { + if ( !FixUpperEdge( tess, reg, eNew ) ) longjmp(tess->env,1); + } else { + ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew )); + } + SweepEvent( tess, vEvent ); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE ); + } +} + + +static void SweepEvent( TESStesselator *tess, TESSvertex *vEvent ) +/* +* Does everything necessary when the sweep line crosses a vertex. +* Updates the mesh and the edge dictionary. +*/ +{ + ActiveRegion *regUp, *reg; + TESShalfEdge *e, *eTopLeft, *eBottomLeft; + + tess->event = vEvent; /* for access in EdgeLeq() */ + DebugEvent( tess ); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent->anEdge; + while( e->activeRegion == NULL ) { + e = e->Onext; + if( e == vEvent->anEdge ) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex( tess, vEvent ); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion( tess, e->activeRegion ); + if (regUp == NULL) longjmp(tess->env,1); + reg = RegionBelow( regUp ); + eTopLeft = reg->eUp; + eBottomLeft = FinishLeftRegions( tess, reg, NULL ); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if( eBottomLeft->Onext == eTopLeft ) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex( tess, regUp, eBottomLeft ); + } else { + AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE ); + } +} + + +/* Make the sentinel coordinates big enough that they will never be +* merged with real input features. +*/ + +static void AddSentinel( TESStesselator *tess, TESSreal smin, TESSreal smax, TESSreal t ) +/* +* We add two sentinel edges above and below all other edges, +* to avoid special cases at the top and bottom. +*/ +{ + TESShalfEdge *e; + ActiveRegion *reg = (ActiveRegion *)bucketAlloc( tess->regionPool ); + if (reg == NULL) longjmp(tess->env,1); + + e = tessMeshMakeEdge( tess->mesh ); + if (e == NULL) longjmp(tess->env,1); + + e->Org->s = smax; + e->Org->t = t; + e->Dst->s = smin; + e->Dst->t = t; + tess->event = e->Dst; /* initialize it */ + + reg->eUp = e; + reg->windingNumber = 0; + reg->inside = FALSE; + reg->fixUpperEdge = FALSE; + reg->sentinel = TRUE; + reg->dirty = FALSE; + reg->nodeUp = dictInsert( tess->dict, reg ); + if (reg->nodeUp == NULL) longjmp(tess->env,1); +} + + +static void InitEdgeDict( TESStesselator *tess ) +/* +* We maintain an ordering of edge intersections with the sweep line. +* This order is maintained in a dynamic dictionary. +*/ +{ + TESSreal w, h; + TESSreal smin, smax, tmin, tmax; + + tess->dict = dictNewDict( &tess->alloc, tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq ); + if (tess->dict == NULL) longjmp(tess->env,1); + + w = (tess->bmax[0] - tess->bmin[0]); + h = (tess->bmax[1] - tess->bmin[1]); + + smin = tess->bmin[0] - w; + smax = tess->bmax[0] + w; + tmin = tess->bmin[1] - h; + tmax = tess->bmax[1] + h; + + AddSentinel( tess, smin, smax, tmin ); + AddSentinel( tess, smin, smax, tmax ); +} + + +static void DoneEdgeDict( TESStesselator *tess ) +{ + ActiveRegion *reg; + int fixedEdges = 0; + + while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if( ! reg->sentinel ) { + assert( reg->fixUpperEdge ); + assert( ++fixedEdges == 1 ); + } + assert( reg->windingNumber == 0 ); + DeleteRegion( tess, reg ); + /* tessMeshDelete( reg->eUp );*/ + } + dictDeleteDict( &tess->alloc, tess->dict ); +} + + +static void RemoveDegenerateEdges( TESStesselator *tess ) +/* +* Remove zero-length edges, and contours with fewer than 3 vertices. +*/ +{ + TESShalfEdge *e, *eNext, *eLnext; + TESShalfEdge *eHead = &tess->mesh->eHead; + + /*LINTED*/ + for( e = eHead->next; e != eHead; e = eNext ) { + eNext = e->next; + eLnext = e->Lnext; + + if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices( tess, eLnext, e ); /* deletes e->Org */ + if ( !tessMeshDelete( tess->mesh, e ) ) longjmp(tess->env,1); /* e is a self-loop */ + e = eLnext; + eLnext = e->Lnext; + } + if( eLnext->Lnext == e ) { + /* Degenerate contour (one or two edges) */ + + if( eLnext != e ) { + if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; } + if ( !tessMeshDelete( tess->mesh, eLnext ) ) longjmp(tess->env,1); + } + if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; } + if ( !tessMeshDelete( tess->mesh, e ) ) longjmp(tess->env,1); + } + } +} + +static int InitPriorityQ( TESStesselator *tess ) +/* +* Insert all vertices into the priority queue which determines the +* order in which vertices cross the sweep line. +*/ +{ + PriorityQ *pq; + TESSvertex *v, *vHead; + int vertexCount = 0; + + vHead = &tess->mesh->vHead; + for( v = vHead->next; v != vHead; v = v->next ) { + vertexCount++; + } + /* Make sure there is enough space for sentinels. */ + vertexCount += MAX( 8, tess->alloc.extraVertices ); + + pq = tess->pq = pqNewPriorityQ( &tess->alloc, vertexCount, (int (*)(PQkey, PQkey)) tesvertLeq ); + if (pq == NULL) return 0; + + vHead = &tess->mesh->vHead; + for( v = vHead->next; v != vHead; v = v->next ) { + v->pqHandle = pqInsert( &tess->alloc, pq, v ); + if (v->pqHandle == INV_HANDLE) + break; + } + if (v != vHead || !pqInit( &tess->alloc, pq ) ) { + pqDeletePriorityQ( &tess->alloc, tess->pq ); + tess->pq = NULL; + return 0; + } + + return 1; +} + + +static void DonePriorityQ( TESStesselator *tess ) +{ + pqDeletePriorityQ( &tess->alloc, tess->pq ); +} + + +static int RemoveDegenerateFaces( TESStesselator *tess, TESSmesh *mesh ) +/* +* Delete any degenerate faces with only two edges. WalkDirtyRegions() +* will catch almost all of these, but it won't catch degenerate faces +* produced by splice operations on already-processed edges. +* The two places this can happen are in FinishLeftRegions(), when +* we splice in a "temporary" edge produced by ConnectRightVertex(), +* and in CheckForLeftSplice(), where we splice already-processed +* edges to ensure that our dictionary invariants are not violated +* by numerical errors. +* +* In both these cases it is *very* dangerous to delete the offending +* edge at the time, since one of the routines further up the stack +* will sometimes be keeping a pointer to that edge. +*/ +{ + TESSface *f, *fNext; + TESShalfEdge *e; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) { + fNext = f->next; + e = f->anEdge; + assert( e->Lnext != e ); + + if( e->Lnext->Lnext == e ) { + /* A face with only two edges */ + AddWinding( e->Onext, e ); + if ( !tessMeshDelete( tess->mesh, e ) ) return 0; + } + } + return 1; +} + +int tessComputeInterior( TESStesselator *tess ) +/* +* tessComputeInterior( tess ) computes the planar arrangement specified +* by the given contours, and further subdivides this arrangement +* into regions. Each region is marked "inside" if it belongs +* to the polygon, according to the rule given by tess->windingRule. +* Each interior region is guaranteed be monotone. +*/ +{ + TESSvertex *v, *vNext; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges( tess ); + if ( !InitPriorityQ( tess ) ) return 0; /* if error */ + InitEdgeDict( tess ); + + while( (v = (TESSvertex *)pqExtractMin( tess->pq )) != NULL ) { + for( ;; ) { + vNext = (TESSvertex *)pqMinimum( tess->pq ); + if( vNext == NULL || ! VertEq( vNext, v )) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (TESS_BOUNDARY_ONLY). + */ + vNext = (TESSvertex *)pqExtractMin( tess->pq ); + SpliceMergeVertices( tess, v->anEdge, vNext->anEdge ); + } + SweepEvent( tess, v ); + } + + /* Set tess->event for debugging purposes */ + tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org; + DebugEvent( tess ); + DoneEdgeDict( tess ); + DonePriorityQ( tess ); + + if ( !RemoveDegenerateFaces( tess, tess->mesh ) ) return 0; + tessMeshCheckMesh( tess->mesh ); + + return 1; +} diff --git a/src/libtess2/Source/sweep.h b/src/libtess2/Source/sweep.h new file mode 100755 index 00000000..32f0f86d --- /dev/null +++ b/src/libtess2/Source/sweep.h @@ -0,0 +1,74 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef SWEEP_H +#define SWEEP_H + +#include "mesh.h" + +/* tessComputeInterior( tess ) computes the planar arrangement specified +* by the given contours, and further subdivides this arrangement +* into regions. Each region is marked "inside" if it belongs +* to the polygon, according to the rule given by tess->windingRule. +* Each interior region is guaranteed be monotone. +*/ +int tessComputeInterior( TESStesselator *tess ); + + +/* The following is here *only* for access by debugging routines */ + +#include "dict.h" + +/* For each pair of adjacent edges crossing the sweep line, there is +* an ActiveRegion to represent the region between them. The active +* regions are kept in sorted order in a dynamic dictionary. As the +* sweep line crosses each vertex, we update the affected regions. +*/ + +struct ActiveRegion { + TESShalfEdge *eUp; /* upper edge, directed right to left */ + DictNode *nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + int inside; /* is this region inside the polygon? */ + int sentinel; /* marks fake edges at t = +/-infinity */ + int dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + int fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +}; + +#define RegionBelow(r) ((ActiveRegion *) dictKey(dictPred((r)->nodeUp))) +#define RegionAbove(r) ((ActiveRegion *) dictKey(dictSucc((r)->nodeUp))) + +#endif diff --git a/src/libtess2/Source/tess.c b/src/libtess2/Source/tess.c new file mode 100755 index 00000000..fa1639c3 --- /dev/null +++ b/src/libtess2/Source/tess.c @@ -0,0 +1,1085 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#include +#include +#include +#include "bucketalloc.h" +#include "tess.h" +#include "mesh.h" +#include "sweep.h" +#include "geom.h" +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 + +#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2]) + +#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) +static void Normalize( TESSreal v[3] ) +{ + TESSreal len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + + assert( len > 0 ); + len = sqrtf( len ); + v[0] /= len; + v[1] /= len; + v[2] /= len; +} +#endif + +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +static int LongAxis( TESSreal v[3] ) +{ + int i = 0; + + if( ABS(v[1]) > ABS(v[0]) ) { i = 1; } + if( ABS(v[2]) > ABS(v[i]) ) { i = 2; } + return i; +} + +static void ComputeNormal( TESStesselator *tess, TESSreal norm[3] ) +{ + TESSvertex *v, *v1, *v2; + TESSreal c, tLen2, maxLen2; + TESSreal maxVal[3], minVal[3], d1[3], d2[3], tNorm[3]; + TESSvertex *maxVert[3], *minVert[3]; + TESSvertex *vHead = &tess->mesh->vHead; + int i; + + v = vHead->next; + for( i = 0; i < 3; ++i ) { + c = v->coords[i]; + minVal[i] = c; + minVert[i] = v; + maxVal[i] = c; + maxVert[i] = v; + } + + for( v = vHead->next; v != vHead; v = v->next ) { + for( i = 0; i < 3; ++i ) { + c = v->coords[i]; + if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; } + if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; } + } + } + + /* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; } + if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; } + if( minVal[i] >= maxVal[i] ) { + /* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; norm[1] = 0; norm[2] = 1; + return; + } + + /* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1->coords[0] - v2->coords[0]; + d1[1] = v1->coords[1] - v2->coords[1]; + d1[2] = v1->coords[2] - v2->coords[2]; + for( v = vHead->next; v != vHead; v = v->next ) { + d2[0] = v->coords[0] - v2->coords[0]; + d2[1] = v->coords[1] - v2->coords[1]; + d2[2] = v->coords[2] - v2->coords[2]; + tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1]; + tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2]; + tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0]; + tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2]; + if( tLen2 > maxLen2 ) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if( maxLen2 <= 0 ) { + /* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[LongAxis(d1)] = 1; + } +} + + +static void CheckOrientation( TESStesselator *tess ) +{ + TESSreal area; + TESSface *f, *fHead = &tess->mesh->fHead; + TESSvertex *v, *vHead = &tess->mesh->vHead; + TESShalfEdge *e; + + /* When we compute the normal automatically, we choose the orientation + * so that the the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for( f = fHead->next; f != fHead; f = f->next ) { + e = f->anEdge; + if( e->winding <= 0 ) continue; + do { + area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t); + e = e->Lnext; + } while( e != f->anEdge ); + } + if( area < 0 ) { + /* Reverse the orientation by flipping all the t-coordinates */ + for( v = vHead->next; v != vHead; v = v->next ) { + v->t = - v->t; + } + tess->tUnit[0] = - tess->tUnit[0]; + tess->tUnit[1] = - tess->tUnit[1]; + tess->tUnit[2] = - tess->tUnit[2]; + } +} + +#ifdef FOR_TRITE_TEST_PROGRAM +#include +extern int RandomSweep; +#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0) +#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0) +#else +#if defined(SLANTED_SWEEP) +/* The "feature merging" is not intended to be complete. There are +* special cases where edges are nearly parallel to the sweep line +* which are not implemented. The algorithm should still behave +* robustly (ie. produce a reasonable tesselation) in the presence +* of such edges, however it may miss features which could have been +* merged. We could minimize this effect by choosing the sweep line +* direction to be something unusual (ie. not parallel to one of the +* coordinate axes). +*/ +#define S_UNIT_X (TESSreal)0.50941539564955385 /* Pre-normalized */ +#define S_UNIT_Y (TESSreal)0.86052074622010633 +#else +#define S_UNIT_X (TESSreal)1.0 +#define S_UNIT_Y (TESSreal)0.0 +#endif +#endif + +/* Determine the polygon normal and project vertices onto the plane +* of the polygon. +*/ +void tessProjectPolygon( TESStesselator *tess ) +{ + TESSvertex *v, *vHead = &tess->mesh->vHead; + TESSreal norm[3]; + TESSreal *sUnit, *tUnit; + int i, first, computedNormal = FALSE; + + norm[0] = tess->normal[0]; + norm[1] = tess->normal[1]; + norm[2] = tess->normal[2]; + if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) { + ComputeNormal( tess, norm ); + computedNormal = TRUE; + } + sUnit = tess->sUnit; + tUnit = tess->tUnit; + i = LongAxis( norm ); + +#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT) + /* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize( norm ); + + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + /* Now make it exactly perpendicular */ + w = Dot( sUnit, norm ); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize( sUnit ); + + /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1]; + tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2]; + tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0]; + Normalize( tUnit ); +#else + /* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i+1)%3] = S_UNIT_X; + sUnit[(i+2)%3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; +#endif + + /* Project the vertices onto the sweep plane */ + for( v = vHead->next; v != vHead; v = v->next ) + { + v->s = Dot( v->coords, sUnit ); + v->t = Dot( v->coords, tUnit ); + } + if( computedNormal ) { + CheckOrientation( tess ); + } + + /* Compute ST bounds. */ + first = 1; + for( v = vHead->next; v != vHead; v = v->next ) + { + if (first) + { + tess->bmin[0] = tess->bmax[0] = v->s; + tess->bmin[1] = tess->bmax[1] = v->t; + first = 0; + } + else + { + if (v->s < tess->bmin[0]) tess->bmin[0] = v->s; + if (v->s > tess->bmax[0]) tess->bmax[0] = v->s; + if (v->t < tess->bmin[1]) tess->bmin[1] = v->t; + if (v->t > tess->bmax[1]) tess->bmax[1] = v->t; + } + } +} + +#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \ + eDst->Sym->winding += eSrc->Sym->winding) + +/* tessMeshTessellateMonoRegion( face ) tessellates a monotone region +* (what else would it do??) The region must consist of a single +* loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this +* case means that any vertical line intersects the interior of the +* region in a single interval. +* +* Tessellation consists of adding interior edges (actually pairs of +* half-edges), to split the region into non-overlapping triangles. +* +* The basic idea is explained in Preparata and Shamos (which I don''t +* have handy right now), although their implementation is more +* complicated than this one. The are two edge chains, an upper chain +* and a lower chain. We process all vertices from both chains in order, +* from right to left. +* +* The algorithm ensures that the following invariant holds after each +* vertex is processed: the untessellated region consists of two +* chains, where one chain (say the upper) is a single edge, and +* the other chain is concave. The left vertex of the single edge +* is always to the left of all vertices in the concave chain. +* +* Each step consists of adding the rightmost unprocessed vertex to one +* of the two chains, and forming a fan of triangles from the rightmost +* of two chain endpoints. Determining whether we can add each triangle +* to the fan is a simple orientation test. By making the fan as large +* as possible, we restore the invariant (check it yourself). +*/ +int tessMeshTessellateMonoRegion( TESSmesh *mesh, TESSface *face ) +{ + TESShalfEdge *up, *lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face->anEdge; + assert( up->Lnext != up && up->Lnext->Lnext != up ); + + for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev ) + ; + for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext ) + ; + lo = up->Lprev; + + while( up->Lnext != lo ) { + if( VertLeq( up->Dst, lo->Org )) { + /* up->Dst is on the left. It is safe to form triangles from lo->Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext ) + || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + lo = lo->Lprev; + } else { + /* lo->Org is on the left. We can make CCW triangles from up->Dst. */ + while( lo->Lnext != up && (EdgeGoesRight( up->Lprev ) + || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, up, up->Lprev ); + if (tempHalfEdge == NULL) return 0; + up = tempHalfEdge->Sym; + } + up = up->Lnext; + } + } + + /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert( lo->Lnext != up ); + while( lo->Lnext->Lnext != up ) { + TESShalfEdge *tempHalfEdge= tessMeshConnect( mesh, lo->Lnext, lo ); + if (tempHalfEdge == NULL) return 0; + lo = tempHalfEdge->Sym; + } + + return 1; +} + +/* tessMeshTessellateInterior( mesh ) tessellates each region of +* the mesh which is marked "inside" the polygon. Each such region +* must be monotone. +*/ +int tessMeshTessellateInterior( TESSmesh *mesh ) +{ + TESSface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f->next; + if( f->inside ) { + if ( !tessMeshTessellateMonoRegion( mesh, f ) ) return 0; + } + } + return 1; +} + + +typedef struct EdgeStackNode EdgeStackNode; +typedef struct EdgeStack EdgeStack; + +struct EdgeStackNode { + TESShalfEdge *edge; + EdgeStackNode *next; +}; + +struct EdgeStack { + EdgeStackNode *top; + struct BucketAlloc *nodeBucket; +}; + +int stackInit( EdgeStack *stack, TESSalloc *alloc ) +{ + stack->top = NULL; + stack->nodeBucket = createBucketAlloc( alloc, "CDT nodes", sizeof(EdgeStackNode), 512 ); + return stack->nodeBucket != NULL; +} + +void stackDelete( EdgeStack *stack ) +{ + deleteBucketAlloc( stack->nodeBucket ); +} + +int stackEmpty( EdgeStack *stack ) +{ + return stack->top == NULL; +} + +void stackPush( EdgeStack *stack, TESShalfEdge *e ) +{ + EdgeStackNode *node = (EdgeStackNode *)bucketAlloc( stack->nodeBucket ); + if ( ! node ) return; + node->edge = e; + node->next = stack->top; + stack->top = node; +} + +TESShalfEdge *stackPop( EdgeStack *stack ) +{ + TESShalfEdge *e = NULL; + EdgeStackNode *node = stack->top; + if (node) { + stack->top = node->next; + e = node->edge; + bucketFree( stack->nodeBucket, node ); + } + return e; +} + +/* + Starting with a valid triangulation, uses the Edge Flip algorithm to + refine the triangulation into a Constrained Delaunay Triangulation. +*/ +int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) +{ + /* At this point, we have a valid, but not optimal, triangulation. + We refine the triangulation using the Edge Flip algorithm */ + +/* + 1) Find all internal edges + 2) Mark all dual edges + 3) insert all dual edges into a queue +*/ + TESSface *f; + EdgeStack stack; + stackInit(&stack, alloc); + TESShalfEdge *e; + TESShalfEdge *edges[4]; + for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { + if ( f->inside) { + e = f->anEdge; + do { + e->mark = EdgeIsInternal(e); /* Mark internal edges */ + if (e->mark && !e->Sym->mark) stackPush(&stack, e); /* Insert into queue */ + e = e->Lnext; + } while (e != f->anEdge); + } + } + + // Pop stack until we find a reversed edge + // Flip the reversed edge, and insert any of the four opposite edges + // which are internal and not already in the stack (!marked) + while (!stackEmpty(&stack)) { + e = stackPop(&stack); + e->mark = e->Sym->mark = 0; + if (!tesedgeIsLocallyDelaunay(e)) { + tessMeshFlipEdge(mesh, e); + // for each opposite edge + edges[0] = e->Lnext; + edges[1] = e->Lprev; + edges[2] = e->Sym->Lnext; + edges[3] = e->Sym->Lprev; + for (int i=0;i<3;i++) { + if (!edges[i]->mark && EdgeIsInternal(edges[i])) { + edges[i]->mark = edges[i]->Sym->mark = 1; + stackPush(&stack, edges[i]); + } + } + } + } + + stackDelete(&stack); + + return 1; +} + + +/* tessMeshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces +* which are not marked "inside" the polygon. Since further mesh operations +* on NULL faces are not allowed, the main purpose is to clean up the +* mesh so that exterior loops are not represented in the data structure. +*/ +void tessMeshDiscardExterior( TESSmesh *mesh ) +{ + TESSface *f, *next; + + /*LINTED*/ + for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) { + /* Since f will be destroyed, save its next pointer. */ + next = f->next; + if( ! f->inside ) { + tessMeshZapFace( mesh, f ); + } + } +} + +/* tessMeshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the +* winding numbers on all edges so that regions marked "inside" the +* polygon have a winding number of "value", and regions outside +* have a winding number of 0. +* +* If keepOnlyBoundary is TRUE, it also deletes all edges which do not +* separate an interior region from an exterior one. +*/ +int tessMeshSetWindingNumber( TESSmesh *mesh, int value, + int keepOnlyBoundary ) +{ + TESShalfEdge *e, *eNext; + + for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) { + eNext = e->next; + if( e->Rface->inside != e->Lface->inside ) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e->winding = (e->Lface->inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if( ! keepOnlyBoundary ) { + e->winding = 0; + } else { + if ( !tessMeshDelete( mesh, e ) ) return 0; + } + } + } + return 1; +} + +void* heapAlloc( void* userData, unsigned int size ) +{ + TESS_NOTUSED( userData ); + return malloc( size ); +} + +void* heapRealloc( void *userData, void* ptr, unsigned int size ) +{ + TESS_NOTUSED( userData ); + return realloc( ptr, size ); +} + +void heapFree( void* userData, void* ptr ) +{ + TESS_NOTUSED( userData ); + free( ptr ); +} + +static TESSalloc defaulAlloc = +{ + heapAlloc, + heapRealloc, + heapFree, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +}; + +TESStesselator* tessNewTess( TESSalloc* alloc ) +{ + TESStesselator* tess; + + if (alloc == NULL) + alloc = &defaulAlloc; + + /* Only initialize fields which can be changed by the api. Other fields + * are initialized where they are used. + */ + + tess = (TESStesselator *)alloc->memalloc( alloc->userData, sizeof( TESStesselator )); + if ( tess == NULL ) { + return 0; /* out of memory */ + } + tess->alloc = *alloc; + /* Check and set defaults. */ + if (tess->alloc.meshEdgeBucketSize == 0) + tess->alloc.meshEdgeBucketSize = 512; + if (tess->alloc.meshVertexBucketSize == 0) + tess->alloc.meshVertexBucketSize = 512; + if (tess->alloc.meshFaceBucketSize == 0) + tess->alloc.meshFaceBucketSize = 256; + if (tess->alloc.dictNodeBucketSize == 0) + tess->alloc.dictNodeBucketSize = 512; + if (tess->alloc.regionBucketSize == 0) + tess->alloc.regionBucketSize = 256; + + tess->normal[0] = 0; + tess->normal[1] = 0; + tess->normal[2] = 0; + + tess->bmin[0] = 0; + tess->bmin[1] = 0; + tess->bmax[0] = 0; + tess->bmax[1] = 0; + + tess->windingRule = TESS_WINDING_ODD; + + if (tess->alloc.regionBucketSize < 16) + tess->alloc.regionBucketSize = 16; + if (tess->alloc.regionBucketSize > 4096) + tess->alloc.regionBucketSize = 4096; + tess->regionPool = createBucketAlloc( &tess->alloc, "Regions", + sizeof(ActiveRegion), tess->alloc.regionBucketSize ); + + // Initialize to begin polygon. + tess->mesh = NULL; + + tess->outOfMemory = 0; + tess->vertexIndexCounter = 0; + + tess->vertices = 0; + tess->vertexIndices = 0; + tess->vertexCount = 0; + tess->elements = 0; + tess->elementCount = 0; + + return tess; +} + +void tessDeleteTess( TESStesselator *tess ) +{ + + struct TESSalloc alloc = tess->alloc; + + deleteBucketAlloc( tess->regionPool ); + + if( tess->mesh != NULL ) { + tessMeshDeleteMesh( &alloc, tess->mesh ); + tess->mesh = NULL; + } + if (tess->vertices != NULL) { + alloc.memfree( alloc.userData, tess->vertices ); + tess->vertices = 0; + } + if (tess->vertexIndices != NULL) { + alloc.memfree( alloc.userData, tess->vertexIndices ); + tess->vertexIndices = 0; + } + if (tess->elements != NULL) { + alloc.memfree( alloc.userData, tess->elements ); + tess->elements = 0; + } + + alloc.memfree( alloc.userData, tess ); +} + + +static TESSindex GetNeighbourFace(TESShalfEdge* edge) +{ + if (!edge->Rface) + return TESS_UNDEF; + if (!edge->Rface->inside) + return TESS_UNDEF; + return edge->Rface->n; +} + +void OutputPolymesh( TESStesselator *tess, TESSmesh *mesh, int elementType, int polySize, int vertexSize ) +{ + TESSvertex* v = 0; + TESSface* f = 0; + TESShalfEdge* edge = 0; + int maxFaceCount = 0; + int maxVertexCount = 0; + int faceVerts, i; + TESSindex *elements = 0; + TESSreal *vert; + + // Assume that the input data is triangles now. + // Try to merge as many polygons as possible + if (polySize > 3) + { + if (!tessMeshMergeConvexFaces( mesh, polySize )) + { + tess->outOfMemory = 1; + return; + } + } + + // Mark unused + for ( v = mesh->vHead.next; v != &mesh->vHead; v = v->next ) + v->n = TESS_UNDEF; + + // Create unique IDs for all vertices and faces. + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + f->n = TESS_UNDEF; + if( !f->inside ) continue; + + edge = f->anEdge; + faceVerts = 0; + do + { + v = edge->Org; + if ( v->n == TESS_UNDEF ) + { + v->n = maxVertexCount; + maxVertexCount++; + } + faceVerts++; + edge = edge->Lnext; + } + while (edge != f->anEdge); + + assert( faceVerts <= polySize ); + + f->n = maxFaceCount; + ++maxFaceCount; + } + + tess->elementCount = maxFaceCount; + if (elementType == TESS_CONNECTED_POLYGONS) + maxFaceCount *= 2; + tess->elements = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * maxFaceCount * polySize ); + if (!tess->elements) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexCount = maxVertexCount; + tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSreal) * tess->vertexCount * vertexSize ); + if (!tess->vertices) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->vertexCount ); + if (!tess->vertexIndices) + { + tess->outOfMemory = 1; + return; + } + + // Output vertices. + for ( v = mesh->vHead.next; v != &mesh->vHead; v = v->next ) + { + if ( v->n != TESS_UNDEF ) + { + // Store coordinate + vert = &tess->vertices[v->n*vertexSize]; + vert[0] = v->coords[0]; + vert[1] = v->coords[1]; + if ( vertexSize > 2 ) + vert[2] = v->coords[2]; + // Store vertex index. + tess->vertexIndices[v->n] = v->idx; + } + } + + // Output indices. + elements = tess->elements; + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + // Store polygon + edge = f->anEdge; + faceVerts = 0; + do + { + v = edge->Org; + *elements++ = v->n; + faceVerts++; + edge = edge->Lnext; + } + while (edge != f->anEdge); + // Fill unused. + for (i = faceVerts; i < polySize; ++i) + *elements++ = TESS_UNDEF; + + // Store polygon connectivity + if ( elementType == TESS_CONNECTED_POLYGONS ) + { + edge = f->anEdge; + do + { + *elements++ = GetNeighbourFace( edge ); + edge = edge->Lnext; + } + while (edge != f->anEdge); + // Fill unused. + for (i = faceVerts; i < polySize; ++i) + *elements++ = TESS_UNDEF; + } + } +} + +void OutputContours( TESStesselator *tess, TESSmesh *mesh, int vertexSize ) +{ + TESSface *f = 0; + TESShalfEdge *edge = 0; + TESShalfEdge *start = 0; + TESSreal *verts = 0; + TESSindex *elements = 0; + TESSindex *vertInds = 0; + int startVert = 0; + int vertCount = 0; + + tess->vertexCount = 0; + tess->elementCount = 0; + + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + start = edge = f->anEdge; + do + { + ++tess->vertexCount; + edge = edge->Lnext; + } + while ( edge != start ); + + ++tess->elementCount; + } + + tess->elements = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->elementCount * 2 ); + if (!tess->elements) + { + tess->outOfMemory = 1; + return; + } + + tess->vertices = (TESSreal*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSreal) * tess->vertexCount * vertexSize ); + if (!tess->vertices) + { + tess->outOfMemory = 1; + return; + } + + tess->vertexIndices = (TESSindex*)tess->alloc.memalloc( tess->alloc.userData, + sizeof(TESSindex) * tess->vertexCount ); + if (!tess->vertexIndices) + { + tess->outOfMemory = 1; + return; + } + + verts = tess->vertices; + elements = tess->elements; + vertInds = tess->vertexIndices; + + startVert = 0; + + for ( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) + { + if ( !f->inside ) continue; + + vertCount = 0; + start = edge = f->anEdge; + do + { + *verts++ = edge->Org->coords[0]; + *verts++ = edge->Org->coords[1]; + if ( vertexSize > 2 ) + *verts++ = edge->Org->coords[2]; + *vertInds++ = edge->Org->idx; + ++vertCount; + edge = edge->Lnext; + } + while ( edge != start ); + + elements[0] = startVert; + elements[1] = vertCount; + elements += 2; + + startVert += vertCount; + } +} + +void tessAddContour( TESStesselator *tess, int size, const void* vertices, + int stride, int numVertices ) +{ + const unsigned char *src = (const unsigned char*)vertices; + TESShalfEdge *e; + int i; + + if ( tess->mesh == NULL ) + tess->mesh = tessMeshNewMesh( &tess->alloc ); + if ( tess->mesh == NULL ) { + tess->outOfMemory = 1; + return; + } + + if ( size < 2 ) + size = 2; + if ( size > 3 ) + size = 3; + + e = NULL; + + for( i = 0; i < numVertices; ++i ) + { + const TESSreal* coords = (const TESSreal*)src; + src += stride; + + if( e == NULL ) { + /* Make a self-loop (one vertex, one edge). */ + e = tessMeshMakeEdge( tess->mesh ); + if ( e == NULL ) { + tess->outOfMemory = 1; + return; + } + if ( !tessMeshSplice( tess->mesh, e, e->Sym ) ) { + tess->outOfMemory = 1; + return; + } + } else { + /* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if ( tessMeshSplitEdge( tess->mesh, e ) == NULL ) { + tess->outOfMemory = 1; + return; + } + e = e->Lnext; + } + + /* The new vertex is now e->Org. */ + e->Org->coords[0] = coords[0]; + e->Org->coords[1] = coords[1]; + if ( size > 2 ) + e->Org->coords[2] = coords[2]; + else + e->Org->coords[2] = 0; + /* Store the insertion number so that the vertex can be later recognized. */ + e->Org->idx = tess->vertexIndexCounter++; + + /* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e->winding = 1; + e->Sym->winding = -1; + } +} + +int tessTesselate( TESStesselator *tess, int windingRule, int elementType, + int polySize, int vertexSize, const TESSreal* normal ) +{ + TESSmesh *mesh; + int rc = 1; + + if (tess->vertices != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->vertices ); + tess->vertices = 0; + } + if (tess->elements != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->elements ); + tess->elements = 0; + } + if (tess->vertexIndices != NULL) { + tess->alloc.memfree( tess->alloc.userData, tess->vertexIndices ); + tess->vertexIndices = 0; + } + + tess->vertexIndexCounter = 0; + + if (normal) + { + tess->normal[0] = normal[0]; + tess->normal[1] = normal[1]; + tess->normal[2] = normal[2]; + } + + tess->windingRule = windingRule; + + if (vertexSize < 2) + vertexSize = 2; + if (vertexSize > 3) + vertexSize = 3; + + if (setjmp(tess->env) != 0) { + /* come back here if out of memory */ + return 0; + } + + if (!tess->mesh) + { + return 0; + } + + /* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + tessProjectPolygon( tess ); + + /* tessComputeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess->windingRule. + * Each interior region is guaranteed be monotone. + */ + if ( !tessComputeInterior( tess ) ) { + longjmp(tess->env,1); /* could've used a label */ + } + + mesh = tess->mesh; + + /* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if (elementType == TESS_BOUNDARY_CONTOURS) { + rc = tessMeshSetWindingNumber( mesh, 1, TRUE ); + } else { + rc = tessMeshTessellateInterior( mesh ); + if (elementType == TESS_CONSTRAINED_DELAUNAY_TRIANGLES) { + rc = tessMeshRefineDelaunay( mesh, &tess->alloc ); + elementType = TESS_POLYGONS; + polySize = 3; + } + } + if (rc == 0) longjmp(tess->env,1); /* could've used a label */ + + tessMeshCheckMesh( mesh ); + + if (elementType == TESS_BOUNDARY_CONTOURS) { + OutputContours( tess, mesh, vertexSize ); /* output contours */ + } + else + { + OutputPolymesh( tess, mesh, elementType, polySize, vertexSize ); /* output polygons */ + } + + tessMeshDeleteMesh( &tess->alloc, mesh ); + tess->mesh = NULL; + + if (tess->outOfMemory) + return 0; + return 1; +} + +int tessGetVertexCount( TESStesselator *tess ) +{ + return tess->vertexCount; +} + +const TESSreal* tessGetVertices( TESStesselator *tess ) +{ + return tess->vertices; +} + +const TESSindex* tessGetVertexIndices( TESStesselator *tess ) +{ + return tess->vertexIndices; +} + +int tessGetElementCount( TESStesselator *tess ) +{ + return tess->elementCount; +} + +const int* tessGetElements( TESStesselator *tess ) +{ + return tess->elements; +} diff --git a/src/libtess2/Source/tess.h b/src/libtess2/Source/tess.h new file mode 100755 index 00000000..c8c747bf --- /dev/null +++ b/src/libtess2/Source/tess.h @@ -0,0 +1,90 @@ +/* +** SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) +** Copyright (C) [dates of first publication] Silicon Graphics, Inc. +** All Rights Reserved. +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +** of the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice including the dates of first publication and either this +** permission notice or a reference to http://oss.sgi.com/projects/FreeB/ shall be +** included in all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +** INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +** PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. +** BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +** OR OTHER DEALINGS IN THE SOFTWARE. +** +** Except as contained in this notice, the name of Silicon Graphics, Inc. shall not +** be used in advertising or otherwise to promote the sale, use or other dealings in +** this Software without prior written authorization from Silicon Graphics, Inc. +*/ +/* +** Author: Eric Veach, July 1994. +*/ + +#ifndef TESS_H +#define TESS_H + +#include +#include "bucketalloc.h" +#include "mesh.h" +#include "dict.h" +#include "priorityq.h" +#include "../Include/tesselator.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//typedef struct TESStesselator TESStesselator; + +struct TESStesselator { + + /*** state needed for collecting the input data ***/ + TESSmesh *mesh; /* stores the input contours, and eventually + the tessellation itself */ + int outOfMemory; + + /*** state needed for projecting onto the sweep plane ***/ + + TESSreal normal[3]; /* user-specified normal (if provided) */ + TESSreal sUnit[3]; /* unit vector in s-direction (debugging) */ + TESSreal tUnit[3]; /* unit vector in t-direction (debugging) */ + + TESSreal bmin[2]; + TESSreal bmax[2]; + + /*** state needed for the line sweep ***/ + int windingRule; /* rule for determining polygon interior */ + + Dict *dict; /* edge dictionary for sweep line */ + PriorityQ *pq; /* priority queue of vertex events */ + TESSvertex *event; /* current sweep event being processed */ + + struct BucketAlloc* regionPool; + + TESSindex vertexIndexCounter; + + TESSreal *vertices; + TESSindex *vertexIndices; + int vertexCount; + TESSindex *elements; + int elementCount; + + TESSalloc alloc; + + jmp_buf env; /* place to jump to when memAllocs fail */ +}; + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 19bdaaff..837df5c0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -555,7 +555,7 @@ else() endif() # Internal includes -include_directories(../src) +include_directories(../src ../src/libtess2/Include) # Handle OpenSCAD version based on VERSION env. variable. # Use current timestamp if not specified (development builds) @@ -679,8 +679,8 @@ set(CGAL_SOURCES ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc ../src/cgalutils-tess.cc + ../src/cgalutils-tess2.cc ../src/cgalutils-polyhedron.cc - ../src/cgalutils-tess-old.cc ../src/CGALCache.cc ../src/CGAL_Nef_polyhedron_DxfData.cc ../src/Polygon2d-CGAL.cc @@ -692,8 +692,15 @@ set(COMMON_SOURCES ../src/traverser.cc ../src/GeometryCache.cc ../src/clipper-utils.cc + ../src/Tree.cc ../src/polyclipping/clipper.cpp - ../src/Tree.cc) + ../src/libtess2/Source/bucketalloc.c + ../src/libtess2/Source/dict.c + ../src/libtess2/Source/geom.c + ../src/libtess2/Source/mesh.c + ../src/libtess2/Source/priorityq.c + ../src/libtess2/Source/sweep.c + ../src/libtess2/Source/tess.c) # # Offscreen OpenGL context source code From e1c62ea152dce1239a2a30a8984cbc564b7eccf1 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 13:30:50 -0500 Subject: [PATCH 061/174] Added some forgotten libraries --- src/AboutDialog.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 22ca9272..b2c2cc44 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -47,12 +47,18 @@ Please visit this link for a copy of the license: GNU GMP
  • GNU MPFR
  • CGAL +
  • Clipper
  • Eigen
  • OpenCSG
  • OpenGL
  • GLEW -
  • Qt Toolkit +
  • Qt Toolkit +
  • QScintilla
  • Boost +
  • GLib +
  • Fontconfig +
  • Freetype +
  • Harfbuzz
  • Bison
  • Flex
  • CMake From 0b1925a417a05e74f99f7e3079c82d15d16db64b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 16:51:02 -0500 Subject: [PATCH 062/174] Less intense debug output --- src/cache.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cache.h b/src/cache.h index e0e3104a..20921eb7 100644 --- a/src/cache.h +++ b/src/cache.h @@ -177,7 +177,7 @@ void Cache::trim(int m) Node *u = n; n = n->p; #ifdef DEBUG - PRINTB("Trimming cache: %1% (%2% bytes)", *u->keyPtr % u->c); + PRINTB("Trimming cache: %1% (%2% bytes)", u->keyPtr->substr(0, 40) % u->c); #endif unlink(*u); } From b0c822988b5ef2626b685628a8ea1c4a82d4819a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 16:52:23 -0500 Subject: [PATCH 063/174] sync with upstream --- src/libtess2/Source/sweep.c | 8 ++++---- src/libtess2/Source/tess.c | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/libtess2/Source/sweep.c b/src/libtess2/Source/sweep.c index 73da9353..a8d8971a 100755 --- a/src/libtess2/Source/sweep.c +++ b/src/libtess2/Source/sweep.c @@ -1121,10 +1121,10 @@ static void InitEdgeDict( TESStesselator *tess ) w = (tess->bmax[0] - tess->bmin[0]); h = (tess->bmax[1] - tess->bmin[1]); - smin = tess->bmin[0] - w; - smax = tess->bmax[0] + w; - tmin = tess->bmin[1] - h; - tmax = tess->bmax[1] + h; + smin = tess->bmin[0] - w - 0.01; + smax = tess->bmax[0] + w + 0.01; + tmin = tess->bmin[1] - h - 0.01; + tmax = tess->bmax[1] + h + 0.01; AddSentinel( tess, smin, smax, tmin ); AddSentinel( tess, smin, smax, tmax ); diff --git a/src/libtess2/Source/tess.c b/src/libtess2/Source/tess.c index fa1639c3..ff8039ed 100755 --- a/src/libtess2/Source/tess.c +++ b/src/libtess2/Source/tess.c @@ -70,6 +70,15 @@ static int LongAxis( TESSreal v[3] ) return i; } +static int ShortAxis( TESSreal v[3] ) +{ + int i = 0; + + if( ABS(v[1]) < ABS(v[0]) ) { i = 1; } + if( ABS(v[2]) < ABS(v[i]) ) { i = 2; } + return i; +} + static void ComputeNormal( TESStesselator *tess, TESSreal norm[3] ) { TESSvertex *v, *v1, *v2; @@ -136,7 +145,7 @@ static void ComputeNormal( TESStesselator *tess, TESSreal norm[3] ) if( maxLen2 <= 0 ) { /* All points lie on a single line -- any decent normal will do */ norm[0] = norm[1] = norm[2] = 0; - norm[LongAxis(d1)] = 1; + norm[ShortAxis(d1)] = 1; } } From da8f4d9933d852807aa63e10733a10686fe64839 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 18:35:20 -0500 Subject: [PATCH 064/174] Upstream sync --- src/libtess2/Source/sweep.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libtess2/Source/sweep.c b/src/libtess2/Source/sweep.c index a8d8971a..112f1ef5 100755 --- a/src/libtess2/Source/sweep.c +++ b/src/libtess2/Source/sweep.c @@ -1121,10 +1121,12 @@ static void InitEdgeDict( TESStesselator *tess ) w = (tess->bmax[0] - tess->bmin[0]); h = (tess->bmax[1] - tess->bmin[1]); - smin = tess->bmin[0] - w - 0.01; - smax = tess->bmax[0] + w + 0.01; - tmin = tess->bmin[1] - h - 0.01; - tmax = tess->bmax[1] + h + 0.01; + /* If the bbox is empty, ensure that sentinels are not coincident by + slightly enlarging it. */ + smin = tess->bmin[0] - (w > 0 ? w : 0.01); + smax = tess->bmax[0] + (w > 0 ? w : 0.01); + tmin = tess->bmin[1] - (h > 0 ? h : 0.01); + tmax = tess->bmax[1] + (h > 0 ? h : 0.01); AddSentinel( tess, smin, smax, tmin ); AddSentinel( tess, smin, smax, tmax ); From e3103c69c2bb6d0fa924caf118f16de3c9160038 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 18:46:09 -0500 Subject: [PATCH 065/174] Don't tessellate triangles, ignore self-intersections, convert all coordinates to TESSfloat --- src/cgalutils-tess2.cc | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/cgalutils-tess2.cc b/src/cgalutils-tess2.cc index aee7f111..f810dc88 100644 --- a/src/cgalutils-tess2.cc +++ b/src/cgalutils-tess2.cc @@ -19,12 +19,22 @@ static void stdFree(void* userData, void* ptr) { namespace CGALUtils { bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, - Polygons &triangles, - const K::Vector_3 *normal) + Polygons &triangles, + const K::Vector_3 *normal) { // No polygon. FIXME: Will this ever happen or can we assert here? if (polygons.empty()) return false; + if (polygons.size() == 1 && polygons[0].size() == 3) { + // Input polygon has 3 points. shortcut tessellation. + Polygon t; + t.push_back(Vector3d(polygons[0][0].x(), polygons[0][0].y(), polygons[0][0].z())); + t.push_back(Vector3d(polygons[0][1].x(), polygons[0][1].y(), polygons[0][1].z())); + t.push_back(Vector3d(polygons[0][2].x(), polygons[0][2].y(), polygons[0][2].z())); + triangles.push_back(t); + return false; + } + TESSreal *normalvec = NULL; TESSreal passednormal[3]; if (normal) { @@ -52,16 +62,16 @@ bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, BOOST_FOREACH(const PolygonK &poly, polygons) { contour.clear(); BOOST_FOREACH(const Vertex3K &v, poly) { - outputvertices.push_back(Vector3d(v.x(), v.y(), v.z())); - contour.push_back(v.x()); - contour.push_back(v.y()); - contour.push_back(v.z()); + TESSreal tessv[3] = {v.x(), v.y(), v.z()}; + outputvertices.push_back(Vector3d(tessv[0], tessv[1], tessv[2])); + contour.push_back(tessv[0]); + contour.push_back(tessv[1]); + contour.push_back(tessv[2]); } tessAddContour(tess, 3, &contour.front(), sizeof(TESSreal) * 3, poly.size()); } if (!tessTesselate(tess, TESS_WINDING_ODD, TESS_CONSTRAINED_DELAUNAY_TRIANGLES, 3, 3, normalvec)) return -1; - // printf("Memory used: %.1f kB\n", allocated/1024.0f); const TESSindex *vindices = tessGetVertexIndices(tess); const TESSindex *elements = tessGetElements(tess); @@ -70,12 +80,15 @@ bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, Polygon tri; for (int t=0;t Date: Tue, 13 Jan 2015 18:51:00 -0500 Subject: [PATCH 066/174] Always normalize normal vector, for safety --- src/cgalutils-tess.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cgalutils-tess.cc b/src/cgalutils-tess.cc index e0ed641b..f602d7b1 100644 --- a/src/cgalutils-tess.cc +++ b/src/cgalutils-tess.cc @@ -107,9 +107,9 @@ namespace CGALUtils { else { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygons.front().begin(), polygons.front().end(), normalvec); - double sqrl = normalvec.squared_length(); - if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); } + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); // Pass the normal vector to the (undocumented) // CGAL::Triangulation_2_filtered_projection_traits_3. This @@ -164,9 +164,9 @@ namespace CGALUtils { else { // Calculate best guess at face normal using Newell's method CGAL::normal_vector_newell_3(polygon.begin(), polygon.end(), normalvec); - double sqrl = normalvec.squared_length(); - if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); } + double sqrl = normalvec.squared_length(); + if (sqrl > 0.0) normalvec = normalvec / sqrt(sqrl); // Pass the normal vector to the (undocumented) // CGAL::Triangulation_2_filtered_projection_traits_3. This From f32eb7e84d645c20b9e2ddcaa63735cf8868b481 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 18:54:35 -0500 Subject: [PATCH 067/174] Grid Nef3 vertices when converting to PolySet --- src/cgalutils.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 97aecb4d..ab3e37d7 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -892,6 +892,8 @@ namespace CGALUtils { bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) { bool err = false; + // Grid all vertices in a Nef polyhedron to merge close vertices. + Grid3d grid(GRID_FINE); CGAL_Nef_polyhedron3::Halffacet_const_iterator hfaceti; CGAL_forall_halffacets(hfaceti, N) { CGAL::Plane_3 plane(hfaceti->plane()); @@ -903,11 +905,22 @@ namespace CGALUtils { CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(cyclei); CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c2(c1); PolygonK polygon; + std::vector indices; // Vertex indices in one polygon CGAL_For_all(c1, c2) { CGAL_Point_3 p = c1->source()->center_vertex()->point(); - polygon.push_back(Vertex3K(CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()))); + Vector3d v = vector_convert(p); + indices.push_back(grid.align(v)); + polygon.push_back(Vertex3K(v[0], v[1], v[2])); } - polyholes.push_back(polygon); + // Remove consecutive duplicate vertices + PolygonK::iterator currp = polygon.begin(); + for (int i=0;i= 3) polyholes.push_back(polygon); } /* at this stage, we have a sequence of polygons. the first From e03c0cebdac15605a104c6d91bb1036fa21ed885 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 19:17:33 -0500 Subject: [PATCH 068/174] Polygon tests --- cgal/data/collinear-axis-aligned.polygon | 4 ++++ cgal/data/duplicate-vertex.polygon | 4 ++++ cgal/data/hourglass.polygon | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 cgal/data/collinear-axis-aligned.polygon create mode 100644 cgal/data/duplicate-vertex.polygon create mode 100644 cgal/data/hourglass.polygon diff --git a/cgal/data/collinear-axis-aligned.polygon b/cgal/data/collinear-axis-aligned.polygon new file mode 100644 index 00000000..623008b9 --- /dev/null +++ b/cgal/data/collinear-axis-aligned.polygon @@ -0,0 +1,4 @@ +-76.547562539078825239,38.705110299157155396,5.353092412611622386 +-76.547562541749158527,38.705110304107662955,5.3530924135499766692 +-76.5475616455078125,38.705108642578125,0 +-76.5475616455078125,38.705108642578125,0.020000000000000000416 diff --git a/cgal/data/duplicate-vertex.polygon b/cgal/data/duplicate-vertex.polygon new file mode 100644 index 00000000..58f1414b --- /dev/null +++ b/cgal/data/duplicate-vertex.polygon @@ -0,0 +1,4 @@ +0 0 0 +1 0 0 +1 1 0 +1 1 0 diff --git a/cgal/data/hourglass.polygon b/cgal/data/hourglass.polygon new file mode 100644 index 00000000..073e80b8 --- /dev/null +++ b/cgal/data/hourglass.polygon @@ -0,0 +1,4 @@ +0 0 0 +1 0 0 +0 1 0 +1 1 0 From 39d68238725749b79842d1da3c997913986b4992 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 19:21:46 -0500 Subject: [PATCH 069/174] Turn off gridding again --- src/cgalutils.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 26e74522..c5e9b012 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -888,7 +888,7 @@ namespace CGALUtils { return err; } #endif -#if 1 +#if 0 bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) { bool err = false; @@ -952,6 +952,58 @@ namespace CGALUtils { } return err; } +#endif +#if 1 + bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) + { + bool err = false; + CGAL_Nef_polyhedron3::Halffacet_const_iterator hfaceti; + CGAL_forall_halffacets(hfaceti, N) { + CGAL::Plane_3 plane(hfaceti->plane()); + PolyholeK polyholes; + // the 0-mark-volume is the 'empty' volume of space. skip it. + if (hfaceti->incident_volume()->mark()) continue; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator cyclei; + CGAL_forall_facet_cycles_of(cyclei, hfaceti) { + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(cyclei); + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c2(c1); + PolygonK polygon; + CGAL_For_all(c1, c2) { + CGAL_Point_3 p = c1->source()->center_vertex()->point(); + polygon.push_back(Vertex3K(CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()))); + } + polyholes.push_back(polygon); + } + + /* at this stage, we have a sequence of polygons. the first + is the "outside edge' or 'body' or 'border', and the rest of the + polygons are 'holes' within the first. there are several + options here to get rid of the holes. we choose to go ahead + and let the tessellater deal with the holes, and then + just output the resulting 3d triangles*/ + + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + std::vector triangles; + bool err = CGALUtils::tessellatePolygonWithHolesNew(polyholes, triangles, NULL); + if (!err) { + BOOST_FOREACH(const Polygon &p, triangles) { + if (p.size() != 3) { + PRINT("WARNING: triangle doesn't have 3 points. skipping"); + continue; + } + ps.append_poly(); + ps.append_vertex(p[0].x(), p[0].y(), p[0].z()); + ps.append_vertex(p[1].x(), p[1].y(), p[1].z()); + ps.append_vertex(p[2].x(), p[2].y(), p[2].z()); + } + } + } + return err; + } #endif CGAL_Nef_polyhedron *createNefPolyhedronFromGeometry(const Geometry &geom) { From fc68e3571e4f5d35ea24778e07f46ff48b4d5f24 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 19:56:18 -0500 Subject: [PATCH 070/174] Convert all coordinates to float; the tessellator works in floats --- src/cgalutils.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index c5e9b012..c3a01cbe 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -970,7 +970,8 @@ namespace CGALUtils { PolygonK polygon; CGAL_For_all(c1, c2) { CGAL_Point_3 p = c1->source()->center_vertex()->point(); - polygon.push_back(Vertex3K(CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()))); + float v[3] = { CGAL::to_double(p.x()), CGAL::to_double(p.y()), CGAL::to_double(p.z()) }; + polygon.push_back(Vertex3K(v[0], v[1], v[2])); } polyholes.push_back(polygon); } From 2e79055edca244d20b352ec476971451c1658662 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 21:39:00 -0500 Subject: [PATCH 071/174] sync with upstream --- src/libtess2/Include/tesselator.h | 2 +- src/libtess2/Source/geom.c | 14 ++++++++++---- src/libtess2/Source/mesh.c | 8 ++++---- src/libtess2/Source/tess.c | 5 +++-- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/libtess2/Include/tesselator.h b/src/libtess2/Include/tesselator.h index 1cc41665..6e51e321 100755 --- a/src/libtess2/Include/tesselator.h +++ b/src/libtess2/Include/tesselator.h @@ -116,7 +116,7 @@ enum TessElementType TESS_POLYGONS, TESS_CONNECTED_POLYGONS, TESS_BOUNDARY_CONTOURS, - TESS_CONSTRAINED_DELAUNAY_TRIANGLES, + TESS_CONSTRAINED_DELAUNAY_TRIANGLES }; typedef float TESSreal; diff --git a/src/libtess2/Source/geom.c b/src/libtess2/Source/geom.c index 21da0c2d..21156f3f 100755 --- a/src/libtess2/Source/geom.c +++ b/src/libtess2/Source/geom.c @@ -266,10 +266,16 @@ void tesedgeIntersect( TESSvertex *o1, TESSvertex *d1, */ TESSreal calcAngle( TESSvertex *v0, TESSvertex *v1, TESSvertex *v2 ) { - TESSreal a[2] = { v2->s - v1->s, v2->t - v1->t }; - TESSreal b[2] = { v0->s - v1->s, v0->t - v1->t }; - TESSreal num = a[0] * b[0] + a[1] * b[1]; - TESSreal den = sqrt( a[0] * a[0] + a[1] * a[1] ) * sqrt( b[0] * b[0] + b[1] * b[1] ); + TESSreal num; + TESSreal den; + TESSreal a[2]; + TESSreal b[2]; + a[0] = v2->s - v1->s; + a[1] = v2->t - v1->t; + b[0] = v0->s - v1->s; + b[1] = v0->t - v1->t; + num = a[0] * b[0] + a[1] * b[1]; + den = sqrt( a[0] * a[0] + a[1] * a[1] ) * sqrt( b[0] * b[0] + b[1] * b[1] ); if ( den > 0.0 ) num /= den; if ( num < -1.0 ) num = -1.0; if ( num > 1.0 ) num = 1.0; diff --git a/src/libtess2/Source/mesh.c b/src/libtess2/Source/mesh.c index 20c52ff6..15ce620d 100755 --- a/src/libtess2/Source/mesh.c +++ b/src/libtess2/Source/mesh.c @@ -752,16 +752,12 @@ int tessMeshMergeConvexFaces( TESSmesh *mesh, int maxVertsPerFace ) void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ) { - assert(EdgeIsInternal(edge)); - TESShalfEdge *a0 = edge; TESShalfEdge *a1 = a0->Lnext; TESShalfEdge *a2 = a1->Lnext; - assert(a2->Lnext == a0); TESShalfEdge *b0 = edge->Sym; TESShalfEdge *b1 = b0->Lnext; TESShalfEdge *b2 = b1->Lnext; - assert(b2->Lnext == b0); TESSvertex *aOrg = a0->Org; TESSvertex *aOpp = a2->Org; @@ -771,6 +767,10 @@ void tessMeshFlipEdge( TESSmesh *mesh, TESShalfEdge *edge ) TESSface *fa = a0->Lface; TESSface *fb = b0->Lface; + assert(EdgeIsInternal(edge)); + assert(a2->Lnext == a0); + assert(b2->Lnext == b0); + a0->Org = bOpp; a0->Onext = b1->Sym; b0->Org = aOpp; diff --git a/src/libtess2/Source/tess.c b/src/libtess2/Source/tess.c index ff8039ed..49e2c495 100755 --- a/src/libtess2/Source/tess.c +++ b/src/libtess2/Source/tess.c @@ -461,9 +461,9 @@ int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) */ TESSface *f; EdgeStack stack; - stackInit(&stack, alloc); TESShalfEdge *e; TESShalfEdge *edges[4]; + stackInit(&stack, alloc); for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) { if ( f->inside) { e = f->anEdge; @@ -482,13 +482,14 @@ int tessMeshRefineDelaunay( TESSmesh *mesh, TESSalloc *alloc ) e = stackPop(&stack); e->mark = e->Sym->mark = 0; if (!tesedgeIsLocallyDelaunay(e)) { + int i; tessMeshFlipEdge(mesh, e); // for each opposite edge edges[0] = e->Lnext; edges[1] = e->Lprev; edges[2] = e->Sym->Lnext; edges[3] = e->Sym->Lprev; - for (int i=0;i<3;i++) { + for (i=0;i<3;i++) { if (!edges[i]->mark && EdgeIsInternal(edges[i])) { edges[i]->mark = edges[i]->Sym->mark = 1; stackPush(&stack, edges[i]); From c30eeecfa2ce1672b8858e8e4c66df4ed2eeacfd Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 22:29:33 -0500 Subject: [PATCH 072/174] Make sure we export the on-screen image. Fixes #1154 --- src/QGLView.cc | 2 ++ src/mainwin.cc | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/QGLView.cc b/src/QGLView.cc index 25ca07a2..372e0e16 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -299,6 +299,8 @@ void QGLView::mouseReleaseEvent(QMouseEvent*) bool QGLView::save(const char *filename) { + // Force reading from front buffer. Some configurations will read from the back buffer here. + glReadBuffer(GL_FRONT); QImage img = grabFrameBuffer(); return img.save(filename, "PNG"); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 123bfd4d..7e91f4cf 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1753,6 +1753,8 @@ void MainWindow::csgRender() } if (viewActionAnimate->isChecked() && e_dump->isChecked()) { + // Force reading from front buffer. Some configurations will read from the back buffer here. + glReadBuffer(GL_FRONT); QImage img = this->qglview->grabFrameBuffer(); QString filename; double s = this->e_fsteps->text().toDouble(); From b2692d9a98d13a8a9dfc1ea48ad920df2ec169ff Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 13 Jan 2015 23:51:56 -0500 Subject: [PATCH 073/174] Changed license of most remaining examples to CC0 --- examples/Advanced/advance_intersection.scad | 12 + examples/Advanced/demo_cut.scad | 12 + examples/Advanced/difference.scad | 12 + examples/Advanced/intersecting.scad | 11 + examples/Advanced/iteration.scad | 11 + examples/Advanced/search.scad | 12 + examples/Advanced/translation.scad | 12 + examples/Basics/LetterBlock.scad | 28 ++ examples/Extrusion/cut_view.scad | 11 + examples/Extrusion/fan_view.scad | 11 + examples/Extrusion/text.scad | 12 + examples/Shapes/M.stl | 450 ++++++++++++++++++++ examples/Shapes/chopped_blocks.scad | 22 +- examples/Shapes/chopped_blocks.stl | Bin 6484 -> 6484 bytes examples/Shapes/fence.scad | 11 + examples/Shapes/flat_body.scad | 11 + examples/Shapes/polyhedron.scad | 12 + examples/Shapes/rounded_box.scad | 11 + examples/Shapes/sphere.scad | 20 +- examples/Shapes/tripod.scad | 11 + 20 files changed, 679 insertions(+), 13 deletions(-) create mode 100644 examples/Basics/LetterBlock.scad create mode 100644 examples/Shapes/M.stl diff --git a/examples/Advanced/advance_intersection.scad b/examples/Advanced/advance_intersection.scad index 5b415211..11ea6337 100644 --- a/examples/Advanced/advance_intersection.scad +++ b/examples/Advanced/advance_intersection.scad @@ -11,3 +11,15 @@ intersection() linear_extrude(height = 100, center = true, convexity= 3) import(file = "advance_intersection.dxf"); } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/demo_cut.scad b/examples/Advanced/demo_cut.scad index 0b42c612..a63a76ed 100644 --- a/examples/Advanced/demo_cut.scad +++ b/examples/Advanced/demo_cut.scad @@ -31,3 +31,15 @@ module demo_cut() translate([ -30, 0, 0 ]) demo_proj(); translate([ +30, 0, 0 ]) demo_cut(); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/difference.scad b/examples/Advanced/difference.scad index 790f25db..5cf6da7f 100644 --- a/examples/Advanced/difference.scad +++ b/examples/Advanced/difference.scad @@ -75,3 +75,15 @@ translate([ 30, 0, 0 ]) nut(); spring(); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/intersecting.scad b/examples/Advanced/intersecting.scad index 9cf62689..36537723 100644 --- a/examples/Advanced/intersecting.scad +++ b/examples/Advanced/intersecting.scad @@ -8,3 +8,14 @@ intersection_for(i = [ ]) rotate(i) cube([100, 20, 20], center = true); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/iteration.scad b/examples/Advanced/iteration.scad index 25c51735..3895ffe7 100644 --- a/examples/Advanced/iteration.scad +++ b/examples/Advanced/iteration.scad @@ -43,3 +43,14 @@ module example006() example006(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/search.scad b/examples/Advanced/search.scad index b4f44f03..dff02254 100644 --- a/examples/Advanced/search.scad +++ b/examples/Advanced/search.scad @@ -20,3 +20,15 @@ module clock_hour_words(word_offset=20.0,word_height=2.0) { } clock_hour_words(word_offset=16.0,word_height=5.0); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Advanced/translation.scad b/examples/Advanced/translation.scad index 417557a1..aaecd2ff 100644 --- a/examples/Advanced/translation.scad +++ b/examples/Advanced/translation.scad @@ -22,3 +22,15 @@ for (i = [1:4]) } } } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Basics/LetterBlock.scad b/examples/Basics/LetterBlock.scad new file mode 100644 index 00000000..7eee768d --- /dev/null +++ b/examples/Basics/LetterBlock.scad @@ -0,0 +1,28 @@ +echo(version=version()); + +module LetterBlock(letter, size=30) { + difference() { + translate([0,0,size/4]) + cube([size,size,size/2], center=true); + translate([0,0,size/6]) + linear_extrude(height=size, convexity=3) + text(letter, + size=size*22/30, + font="Tahoma", + halign="center", + valign="center"); + } +} + +LetterBlock("M"); + +// Written by Marius Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Extrusion/cut_view.scad b/examples/Extrusion/cut_view.scad index 7d11b917..07a558b0 100644 --- a/examples/Extrusion/cut_view.scad +++ b/examples/Extrusion/cut_view.scad @@ -64,3 +64,14 @@ translate([0, 0, -10]) // cutview(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Extrusion/fan_view.scad b/examples/Extrusion/fan_view.scad index 5ea81811..37bcb1d5 100644 --- a/examples/Extrusion/fan_view.scad +++ b/examples/Extrusion/fan_view.scad @@ -29,3 +29,14 @@ intersection() import(file = "fan_view.dxf", layer = "fan_side", origin = fan_side_center); } +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Extrusion/text.scad b/examples/Extrusion/text.scad index 891cc0f0..838f70d7 100644 --- a/examples/Extrusion/text.scad +++ b/examples/Extrusion/text.scad @@ -31,3 +31,15 @@ difference() import(file = "text.dxf", layer = "X"); } } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/M.stl b/examples/Shapes/M.stl new file mode 100644 index 00000000..699a7e0c --- /dev/null +++ b/examples/Shapes/M.stl @@ -0,0 +1,450 @@ +solid OpenSCAD_Model + facet normal -1 0 0 + outer loop + vertex -15 15 0 + vertex -15 -15 0 + vertex -15 -15 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex -15 15 15 + vertex -15 15 0 + vertex -15 -15 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex -6.49335 -10.8438 15 + vertex 15 -15 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -9.24535 11.3642 15 + vertex -15 15 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5.72964 11.3642 15 + vertex -5.22034 11.3642 15 + vertex 0.351639 -0.977737 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 15 15 + vertex -15 -15 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -5.22034 11.3642 15 + vertex -15 15 15 + vertex -9.24535 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 15 15 + vertex -15 15 15 + vertex -5.22034 11.3642 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 9.82664 11.3642 15 + vertex 15 15 15 + vertex 5.72964 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 15 15 + vertex -5.22034 11.3642 15 + vertex 5.72964 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 -10.8438 15 + vertex 15 15 15 + vertex 9.82664 11.3642 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 15 -15 15 + vertex 9.82664 -10.8438 15 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 15 -15 15 + vertex 15 15 15 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 -15 15 + vertex 15 -15 15 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 -10.8438 15 + vertex 1.07065 -4.69974 15 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 0 -0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex 6.88264 8.29724 15 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -15 -15 15 + vertex -6.49335 -10.8438 15 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 -10.8438 15 + vertex 1.07065 -4.69974 15 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 15 + vertex -6.49335 -10.8438 15 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 -15 15 + vertex 15 -15 0 + vertex 15 15 0 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 15 15 15 + vertex 15 -15 15 + vertex 15 15 0 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 15 15 0 + vertex -15 15 0 + vertex -15 15 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 15 15 15 + vertex 15 15 0 + vertex -15 15 15 + endloop + endfacet + facet normal 0 0 -1 + outer loop + vertex 15 -15 0 + vertex -15 -15 0 + vertex -15 15 0 + endloop + endfacet + facet normal -0 -0 -1 + outer loop + vertex 15 15 0 + vertex 15 -15 0 + vertex -15 15 0 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -15 -15 15 + vertex -15 -15 0 + vertex 15 -15 0 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex 15 -15 15 + vertex -15 -15 15 + vertex 15 -15 0 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 5 + vertex -9.24535 -10.8438 5 + vertex -6.49335 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -6.49335 8.29724 5 + vertex -9.24535 11.3642 5 + vertex -9.24535 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 1.07065 -4.69974 5 + vertex 0.351639 -0.977737 5 + vertex -0.726349 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 0.351639 -0.977737 5 + vertex -6.49335 8.29724 5 + vertex -0.726349 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex -5.22034 11.3642 5 + vertex -9.24535 11.3642 5 + vertex -6.49335 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 -10.8438 5 + vertex 6.88264 8.29724 5 + vertex 6.88264 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 11.3642 5 + vertex 6.88264 8.29724 5 + vertex 9.82664 -10.8438 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 9.82664 11.3642 5 + vertex 5.72964 11.3642 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 6.88264 8.29724 5 + vertex 0.351639 -0.977737 5 + vertex 1.07065 -4.69974 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 5.72964 11.3642 5 + vertex 0.351639 -0.977737 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 0 1 + outer loop + vertex 0.351639 -0.977737 5 + vertex -5.22034 11.3642 5 + vertex -6.49335 8.29724 5 + endloop + endfacet + facet normal 0.914058 0.405584 0 + outer loop + vertex -0.726349 -4.69974 5 + vertex -6.49335 8.29724 5 + vertex -6.49335 8.29724 15 + endloop + endfacet + facet normal 0.914058 0.405584 0 + outer loop + vertex -0.726349 -4.69974 15 + vertex -0.726349 -4.69974 5 + vertex -6.49335 8.29724 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 1.07065 -4.69974 5 + vertex -0.726349 -4.69974 5 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 1.07065 -4.69974 15 + vertex 1.07065 -4.69974 5 + vertex -0.726349 -4.69974 15 + endloop + endfacet + facet normal -0.912882 0.408223 0 + outer loop + vertex 6.88264 8.29724 5 + vertex 1.07065 -4.69974 5 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal -0.912882 0.408223 0 + outer loop + vertex 6.88264 8.29724 15 + vertex 6.88264 8.29724 5 + vertex 1.07065 -4.69974 15 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 6.88264 -10.8438 15 + vertex 6.88264 -10.8438 5 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex 6.88264 8.29724 15 + vertex 6.88264 -10.8438 15 + vertex 6.88264 8.29724 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 9.82664 -10.8438 5 + vertex 6.88264 -10.8438 5 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex 9.82664 -10.8438 15 + vertex 9.82664 -10.8438 5 + vertex 6.88264 -10.8438 15 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex 9.82664 11.3642 5 + vertex 9.82664 -10.8438 5 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex 9.82664 11.3642 15 + vertex 9.82664 11.3642 5 + vertex 9.82664 -10.8438 15 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex 5.72964 11.3642 15 + vertex 5.72964 11.3642 5 + vertex 9.82664 11.3642 5 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex 9.82664 11.3642 15 + vertex 5.72964 11.3642 15 + vertex 9.82664 11.3642 5 + endloop + endfacet + facet normal 0.916746 -0.399471 0 + outer loop + vertex 0.351639 -0.977737 15 + vertex 0.351639 -0.977737 5 + vertex 5.72964 11.3642 5 + endloop + endfacet + facet normal 0.916746 -0.399471 0 + outer loop + vertex 5.72964 11.3642 15 + vertex 0.351639 -0.977737 15 + vertex 5.72964 11.3642 5 + endloop + endfacet + facet normal -0.911421 -0.411475 -0 + outer loop + vertex -5.22034 11.3642 15 + vertex -5.22034 11.3642 5 + vertex 0.351639 -0.977737 5 + endloop + endfacet + facet normal -0.911421 -0.411475 -0 + outer loop + vertex 0.351639 -0.977737 15 + vertex -5.22034 11.3642 15 + vertex 0.351639 -0.977737 5 + endloop + endfacet + facet normal 0 -1 0 + outer loop + vertex -9.24535 11.3642 15 + vertex -9.24535 11.3642 5 + vertex -5.22034 11.3642 5 + endloop + endfacet + facet normal -0 -1 -0 + outer loop + vertex -5.22034 11.3642 15 + vertex -9.24535 11.3642 15 + vertex -5.22034 11.3642 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -9.24535 -10.8438 15 + vertex -9.24535 -10.8438 5 + vertex -9.24535 11.3642 5 + endloop + endfacet + facet normal 1 0 0 + outer loop + vertex -9.24535 11.3642 15 + vertex -9.24535 -10.8438 15 + vertex -9.24535 11.3642 5 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -6.49335 -10.8438 5 + vertex -9.24535 -10.8438 5 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal 0 1 0 + outer loop + vertex -6.49335 -10.8438 15 + vertex -6.49335 -10.8438 5 + vertex -9.24535 -10.8438 15 + endloop + endfacet + facet normal -1 0 0 + outer loop + vertex -6.49335 8.29724 5 + vertex -6.49335 -10.8438 5 + vertex -6.49335 -10.8438 15 + endloop + endfacet + facet normal -1 -0 -0 + outer loop + vertex -6.49335 8.29724 15 + vertex -6.49335 8.29724 5 + vertex -6.49335 -10.8438 15 + endloop + endfacet +endsolid OpenSCAD_Model diff --git a/examples/Shapes/chopped_blocks.scad b/examples/Shapes/chopped_blocks.scad index ea5e27ac..30e24bc4 100644 --- a/examples/Shapes/chopped_blocks.scad +++ b/examples/Shapes/chopped_blocks.scad @@ -1,10 +1,5 @@ -// chopped_blocks.stl is derived from Mblock.stl -// (c) 2009 Will Langford licensed under -// the Creative Commons - GNU GPL license. -// http://www.thingiverse.com/thing:753 -// -// Jonas Pfeil converted the file to binary -// STL and duplicated its content. +// chopped_blocks.stl is derived from Basics/LetterBlock.scad +// The exported STL was converted to binary using MeshLab echo(version=version()); @@ -21,7 +16,7 @@ module blk2() { } module chop() { - translate([ -14, 0, 0 ]) + translate([ -18, 0, 0 ]) import(file = "chopped_blocks.stl", convexity = 12); } @@ -36,3 +31,14 @@ difference() { } } +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/chopped_blocks.stl b/examples/Shapes/chopped_blocks.stl index c24cdf7768a13e36b53b58e7e23148d7e8b9b39a..0291b9fe848c3b5fafc747a9140f7af638d152a3 100644 GIT binary patch literal 6484 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 PGZ+c`{(uJeD`1 and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/flat_body.scad b/examples/Shapes/flat_body.scad index a18a94a7..135d8fbc 100644 --- a/examples/Shapes/flat_body.scad +++ b/examples/Shapes/flat_body.scad @@ -27,3 +27,14 @@ module shape() // linear_extrude(convexity = 10, center = true) shape(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/polyhedron.scad b/examples/Shapes/polyhedron.scad index 6aa44357..c0947f98 100644 --- a/examples/Shapes/polyhedron.scad +++ b/examples/Shapes/polyhedron.scad @@ -16,3 +16,15 @@ polyhedron( [4, 0, 3] ] ); + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/rounded_box.scad b/examples/Shapes/rounded_box.scad index aac5fd2f..48b1e5f6 100644 --- a/examples/Shapes/rounded_box.scad +++ b/examples/Shapes/rounded_box.scad @@ -36,3 +36,14 @@ module roundedBox(size, radius, sidesonly) translate([-15,0,0])roundedBox([20,30,40], 5, true); translate([15,0,0]) roundedBox([20,30,40], 5, false); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/sphere.scad b/examples/Shapes/sphere.scad index 6e808acd..37cf3d4a 100644 --- a/examples/Shapes/sphere.scad +++ b/examples/Shapes/sphere.scad @@ -1,6 +1,4 @@ -// example012.stl is Mblock.stl, (c) 2009 Will Langford -// licensed under the Creative Commons - GNU GPL license. -// http://www.thingiverse.com/thing:753 +// M.stl is generated from Basics/LetterBlock.scad echo(version=version()); @@ -8,6 +6,18 @@ difference() { sphere(20); - translate([ -2.92, 0.5, +20 ]) rotate([180, 0, 180]) - import("sphere.stl", convexity = 5); + translate([ 0, 0.5, +20 ]) rotate([180, 0, 180]) + import("M.stl", convexity = 5); } + +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . diff --git a/examples/Shapes/tripod.scad b/examples/Shapes/tripod.scad index c46d2cc4..bedc0f57 100644 --- a/examples/Shapes/tripod.scad +++ b/examples/Shapes/tripod.scad @@ -156,3 +156,14 @@ if (mode == "exploded") if (mode == "assembled") assembled(); +// Written by Clifford Wolf and Marius +// Kintel +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . From 4af38828d227a6a7f63a30f3a0969e010aa52ba5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 14 Jan 2015 11:47:56 -0500 Subject: [PATCH 074/174] Remaining example -> CC0 --- examples/Advanced/fractal.scad | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/Advanced/fractal.scad b/examples/Advanced/fractal.scad index 871222a4..bab5eb15 100644 --- a/examples/Advanced/fractal.scad +++ b/examples/Advanced/fractal.scad @@ -1,6 +1,4 @@ // Menger Sponge -// By Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013 -// CC-BY-SA license // Size of edge of sponge D=100; @@ -32,3 +30,14 @@ difference() { rotate([45, atan(1/sqrt(2)), 0]) menger(); translate([0,0,-D]) cube(2*D, center=true); } + +// Written by Nathan Hellweg, Emmett Lalish and Marius Kintel May 13, 2013 +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to the +// public domain worldwide. This software is distributed without any +// warranty. +// +// You should have received a copy of the CC0 Public Domain +// Dedication along with this software. +// If not, see . From 1e14e63947a56c836dcf918a3ba6a417528d7de8 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 14 Jan 2015 20:01:53 +0100 Subject: [PATCH 075/174] Add cheat-sheet link to help menu --- src/MainWindow.h | 1 + src/MainWindow.ui | 9 ++++++--- src/UIUtils.cc | 13 ++++++++++++- src/UIUtils.h | 2 ++ src/mainwin.cc | 6 ++++++ src/openscad.cc | 2 ++ src/openscad.h | 1 + 7 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/MainWindow.h b/src/MainWindow.h index dc5c8140..48e22a28 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -240,6 +240,7 @@ public slots: void helpAbout(); void helpHomepage(); void helpManual(); + void helpCheatSheet(); void helpLibrary(); void helpFontInfo(); void quit(); diff --git a/src/MainWindow.ui b/src/MainWindow.ui index e316e56b..01300dd5 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -360,6 +360,7 @@ + @@ -874,9 +875,6 @@ Show Scale Markers - @@ -1189,6 +1187,11 @@ Hide toolbars + + + Cheat Sheet + + diff --git a/src/UIUtils.cc b/src/UIUtils.cc index 3e8c8c01..8b701c45 100644 --- a/src/UIUtils.cc +++ b/src/UIUtils.cc @@ -34,6 +34,7 @@ #include "qtgettext.h" #include "UIUtils.h" #include "PlatformUtils.h" +#include "openscad.h" QFileInfo UIUtils::openFile(QWidget *parent) { @@ -103,7 +104,17 @@ void UIUtils::openHomepageURL() QDesktopServices::openUrl(QUrl("http://openscad.org/")); } +static void openVersionedURL(QString url) +{ + QDesktopServices::openUrl(QUrl(url.arg(versionnumber.c_str()))); +} + void UIUtils::openUserManualURL() { - QDesktopServices::openUrl(QUrl("http://www.openscad.org/documentation.html")); + openVersionedURL("http://www.openscad.org/documentation.html?version=%1"); +} + +void UIUtils::openCheatSheetURL() +{ + openVersionedURL("http://www.openscad.org/cheatsheet/index.html?version=%1"); } diff --git a/src/UIUtils.h b/src/UIUtils.h index 4e26e35b..5ce87b28 100644 --- a/src/UIUtils.h +++ b/src/UIUtils.h @@ -42,4 +42,6 @@ namespace UIUtils { void openHomepageURL(); void openUserManualURL(); + + void openCheatSheetURL(); } diff --git a/src/mainwin.cc b/src/mainwin.cc index 7e91f4cf..a11dd96e 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -407,6 +407,7 @@ MainWindow::MainWindow(const QString &filename) connect(this->helpActionAbout, SIGNAL(triggered()), this, SLOT(helpAbout())); connect(this->helpActionHomepage, SIGNAL(triggered()), this, SLOT(helpHomepage())); connect(this->helpActionManual, SIGNAL(triggered()), this, SLOT(helpManual())); + connect(this->helpActionCheatSheet, SIGNAL(triggered()), this, SLOT(helpCheatSheet())); connect(this->helpActionLibraryInfo, SIGNAL(triggered()), this, SLOT(helpLibrary())); connect(this->helpActionFontInfo, SIGNAL(triggered()), this, SLOT(helpFontInfo())); @@ -2518,6 +2519,11 @@ void MainWindow::helpManual() UIUtils::openUserManualURL(); } +void MainWindow::helpCheatSheet() +{ + UIUtils::openCheatSheetURL(); +} + void MainWindow::helpLibrary() { if (!this->library_info_dialog) { diff --git a/src/openscad.cc b/src/openscad.cc index 0b0de394..ae9a872a 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -93,6 +93,8 @@ static std::string arg_colorscheme; #define QUOTE(x__) # x__ #define QUOTED(x__) QUOTE(x__) +std::string versionnumber = QUOTED(OPENSCAD_VERSION); + std::string openscad_versionnumber = QUOTED(OPENSCAD_VERSION) #ifdef OPENSCAD_COMMIT " (git " QUOTED(OPENSCAD_COMMIT) ")" diff --git a/src/openscad.h b/src/openscad.h index f37f0253..04f530ed 100644 --- a/src/openscad.h +++ b/src/openscad.h @@ -35,6 +35,7 @@ extern std::string commandline_commands; // doing this, use currentdir to get the original CWD. extern std::string currentdir; +// Version number without the git suffix. extern std::string versionnumber; // Just the number (might have the git commit as suffix), e.g. 2014.12.23. From b6d76e370cb68c5640ca9f8cb9faba107c9aa7d0 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 10:04:18 -0500 Subject: [PATCH 076/174] update: no SVG/AMF import in this release --- releases/2014.QX.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2014.QX.md b/releases/2014.QX.md index 15500944..c8e9a87f 100644 --- a/releases/2014.QX.md +++ b/releases/2014.QX.md @@ -13,8 +13,8 @@ * MDI * FIXME: Windows cmd-line fixes * Qt5, retina -* SVG import/export -* AMF import/export +* SVG export +* AMF export * Color schemes for viewer and editor can be user-edited * Improved editor * Splash screen From dcda8faa3d7e7f8c719941470e21051bd3c46760 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 15 Jan 2015 16:59:46 +0100 Subject: [PATCH 077/174] Remove setting WhitespaceBackgroundColor from noColor() too. --- src/scintillaeditor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/scintillaeditor.cpp b/src/scintillaeditor.cpp index 43f36f01..fdebead8 100644 --- a/src/scintillaeditor.cpp +++ b/src/scintillaeditor.cpp @@ -331,7 +331,6 @@ void ScintillaEditor::noColor() qsci->setIndicatorForegroundColor(QColor(255, 0, 0, 128), indicatorNumber); qsci->setIndicatorOutlineColor(QColor(0, 0, 0, 255), indicatorNumber); // only alpha part is used qsci->setCaretLineBackgroundColor(Qt::white); - qsci->setWhitespaceBackgroundColor(Qt::white); qsci->setWhitespaceForegroundColor(Qt::black); qsci->setMarginsBackgroundColor(Qt::white); qsci->setMarginsForegroundColor(Qt::black); From 33425115c578338646e6348bdd47a4b6a2bfe7e8 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Thu, 15 Jan 2015 17:29:11 +0100 Subject: [PATCH 078/174] Update dumptest reference files. --- .../dumptest-examples/LetterBlock-expected.csg | 15 +++++++++++++++ .../dumptest-examples/chopped_blocks-expected.csg | 8 ++++---- .../dumptest-examples/sphere-expected.csg | 4 ++-- 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 tests/regression/dumptest-examples/LetterBlock-expected.csg diff --git a/tests/regression/dumptest-examples/LetterBlock-expected.csg b/tests/regression/dumptest-examples/LetterBlock-expected.csg new file mode 100644 index 00000000..3fbaf903 --- /dev/null +++ b/tests/regression/dumptest-examples/LetterBlock-expected.csg @@ -0,0 +1,15 @@ +group() { + group(); + group() { + difference() { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 7.5], [0, 0, 0, 1]]) { + cube(size = [30, 30, 15], center = true); + } + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 5], [0, 0, 0, 1]]) { + linear_extrude(height = 30, center = false, convexity = 3, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { + text(text = "M", size = 22, spacing = 1, font = "Tahoma", direction = "ltr", language = "en", script = "latin", halign = "center", valign = "center", $fn = 0, $fa = 12, $fs = 2); + } + } + } + } +} diff --git a/tests/regression/dumptest-examples/chopped_blocks-expected.csg b/tests/regression/dumptest-examples/chopped_blocks-expected.csg index 816d33ef..93410a7b 100644 --- a/tests/regression/dumptest-examples/chopped_blocks-expected.csg +++ b/tests/regression/dumptest-examples/chopped_blocks-expected.csg @@ -17,7 +17,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -36,7 +36,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -55,7 +55,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } @@ -74,7 +74,7 @@ group() { } } group() { - multmatrix([[1, 0, 0, -14], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, -18], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { import(file = "chopped_blocks.stl", layer = "", origin = [0, 0], scale = 1, convexity = 12, $fn = 0, $fa = 12, $fs = 2); } } diff --git a/tests/regression/dumptest-examples/sphere-expected.csg b/tests/regression/dumptest-examples/sphere-expected.csg index e6f46184..688301ea 100644 --- a/tests/regression/dumptest-examples/sphere-expected.csg +++ b/tests/regression/dumptest-examples/sphere-expected.csg @@ -2,9 +2,9 @@ group() { group(); difference() { sphere($fn = 0, $fa = 12, $fs = 2, r = 20); - multmatrix([[1, 0, 0, -2.92], [0, 1, 0, 0.5], [0, 0, 1, 20], [0, 0, 0, 1]]) { + multmatrix([[1, 0, 0, 0], [0, 1, 0, 0.5], [0, 0, 1, 20], [0, 0, 0, 1]]) { multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) { - import(file = "sphere.stl", layer = "", origin = [0, 0], scale = 1, convexity = 5, $fn = 0, $fa = 12, $fs = 2); + import(file = "M.stl", layer = "", origin = [0, 0], scale = 1, convexity = 5, $fn = 0, $fa = 12, $fs = 2); } } } From c0760e990454b4b00602321d30412011749fe5b9 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Thu, 15 Jan 2015 11:14:01 -0600 Subject: [PATCH 079/174] Removal of openscad.cc cmdline section for registry change Removal of the code block in the cmdline() section of openscad.cc that sets the Document Icon. This was necessary due to the follow: "This is also used from the test framework which does not link with Qt. See Travis log: /home/travis/build/openscad/openscad/src/openscad.cc:46:16: fatal error: QDir: No such file or directory" modified: src/openscad.cc --- src/openscad.cc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/openscad.cc b/src/openscad.cc index 7be03d27..9e83b415 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -320,12 +320,6 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c parser_init(); localization_init(); -#ifdef Q_OS_WIN - QSettings reg_setting(QLatin1String("HKEY_CURRENT_USER"), QSettings::NativeFormat); - QString appPath = QDir::toNativeSeparators(app.applicationFilePath() + QLatin1String(",1")); - reg_setting.setValue(QLatin1String("Software/Classes/OpenSCAD_File/DefaultIcon/Default"),QVariant(appPath)); -#endif - Tree tree; #ifdef ENABLE_CGAL GeometryEvaluator geomevaluator(tree); From d7175c7d012dfee347c1ab5137103e6f0990663a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 14:38:04 -0500 Subject: [PATCH 080/174] Added hash_value() for Vector3f --- src/grid.cc | 5 +++++ src/grid.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/grid.cc b/src/grid.cc index 79d72900..44a882aa 100644 --- a/src/grid.cc +++ b/src/grid.cc @@ -1,6 +1,11 @@ #include "grid.h" namespace Eigen { + size_t hash_value(Vector3f const &v) { + size_t seed = 0; + for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); + return seed; + } size_t hash_value(Vector3d const &v) { size_t seed = 0; for (int i=0;i<3;i++) boost::hash_combine(seed, v[i]); diff --git a/src/grid.h b/src/grid.h index e3db9a43..f467ba3c 100644 --- a/src/grid.h +++ b/src/grid.h @@ -90,6 +90,7 @@ public: typedef Eigen::Matrix Vector3l; namespace Eigen { + size_t hash_value(Vector3f const &v); size_t hash_value(Vector3d const &v); size_t hash_value(Vector3l const &v); } From 90b647ec4851ed4d89300a355c4cf1eaad696c0a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 14:38:34 -0500 Subject: [PATCH 081/174] Use iterator as dest instead of a vector, for flexibility --- src/Reindexer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Reindexer.h b/src/Reindexer.h index 0dbfecaf..f7601e0d 100644 --- a/src/Reindexer.h +++ b/src/Reindexer.h @@ -51,10 +51,9 @@ public: /*! Copies the internal vector to the given destination */ - void copy(std::vector &dest) { + template void copy(OutputIterator dest) { this->getArray(); - dest.resize(this->vec.size()); - std::copy(this->vec.begin(), this->vec.end(), dest.begin()); + std::copy(this->vec.begin(), this->vec.end(), dest); } private: From 1c52fad1d38145ebc32f30cf44f7104d6d269b44 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 14:47:05 -0500 Subject: [PATCH 082/174] Moved libtess2-based tessellation to GeometryUtils, related refactoring --- cgal/polyhole-tessellator-libtess2.cpp | 87 ++++++++------- cgal/polyhole-tessellator-libtess2.pro | 7 +- openscad.pro | 3 +- src/GeometryUtils.cc | 141 +++++++++++++++++++++++++ src/GeometryUtils.h | 25 +++++ src/cgalutils-tess2.cc | 100 ------------------ src/cgalutils.cc | 84 ++++++++++++++- src/cgalutils.h | 3 - src/linalg.h | 7 +- src/polyset.cc | 14 ++- src/polyset.h | 7 +- tests/CMakeLists.txt | 4 +- 12 files changed, 324 insertions(+), 158 deletions(-) create mode 100644 src/GeometryUtils.cc create mode 100644 src/GeometryUtils.h delete mode 100644 src/cgalutils-tess2.cc diff --git a/cgal/polyhole-tessellator-libtess2.cpp b/cgal/polyhole-tessellator-libtess2.cpp index f157f586..4ff654df 100644 --- a/cgal/polyhole-tessellator-libtess2.cpp +++ b/cgal/polyhole-tessellator-libtess2.cpp @@ -3,27 +3,24 @@ #include #include #include +#include #include -#include "cgalutils.h" +#include "GeometryUtils.h" +#include "Reindexer.h" #include "linalg.h" +#include "grid.h" -#include -typedef CGAL::Epick K; -typedef CGAL::Point_3 Vertex3K; -typedef std::vector PolygonK; -typedef std::vector PolyholeK; - - -// Nef polyhedron are using CGAL_Kernel3 (Cartesian) -// Triangulation will use Epick - -static void export_stl(const Polygons &triangles, std::ostream &output) +static void export_stl(const IndexedTriangleMesh &trimesh, std::ostream &output) { setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output output << "solid OpenSCAD_Model\n"; - BOOST_FOREACH(const Polygon &p, triangles) { - assert(p.size() == 3); // STL only allows triangles + const Vector3f *verts = &trimesh.vertices.front(); + BOOST_FOREACH(const IndexedTriangle &t, trimesh.triangles) { + Vector3f p[3]; + p[0] = verts[t[0]]; + p[1] = verts[t[1]]; + p[2] = verts[t[2]]; std::stringstream stream; stream << p[0][0] << " " << p[0][1] << " " << p[0][2]; std::string vs1 = stream.str(); @@ -39,13 +36,13 @@ static void export_stl(const Polygons &triangles, std::ostream &output) // so the default value of "1 0 0" can be used. If the vertices are not // collinear then the unit normal must be calculated from the // components. - Vector3d normal = (p[1] - p[0]).cross(p[2] - p[0]); + Vector3f normal = (p[1] - p[0]).cross(p[2] - p[0]); normal.normalize(); output << " facet normal " << normal[0] << " " << normal[1] << " " << normal[2] << "\n"; output << " outer loop\n"; - BOOST_FOREACH(const Vector3d &v, p) { - output << " vertex " << v[0] << " " << v[1] << " " << v[2] << "\n"; + for (int i=0;i<3;i++) { + output << " vertex " << p[i][0] << " " << p[i][1] << " " << p[i][2] << "\n"; } output << " endloop\n"; output << " endfacet\n"; @@ -62,19 +59,20 @@ static void export_stl(const Polygons &triangles, std::ostream &output) each coordinate is on a separate line 2. each polygon is separated by one or more blank lines */ -bool import_polygon(PolyholeK &polyhole, const std::string &filename) +bool import_polygon(IndexedPolygons &polyhole, const std::string &filename) { + Reindexer uniqueVertices; std::ifstream ifs(filename.c_str()); if (!ifs) return false; std::string line; - PolygonK polygon; + IndexedFace polygon; while (std::getline(ifs, line)) { std::stringstream ss(line); double X = 0.0, Y = 0.0, Z = 0.0; if (!(ss >> X)) { //ie blank lines => flag start of next polygon - if (polygon.size() > 0) polyhole.push_back(polygon); + if (polygon.size() > 0) polyhole.faces.push_back(polygon); polygon.clear(); continue; } @@ -94,23 +92,24 @@ bool import_polygon(PolyholeK &polyhole, const std::string &filename) std::cerr << "Z error\n"; return false; } - polygon.push_back(Vertex3K(X, Y, Z)); + polygon.push_back(uniqueVertices.lookup(Vector3f(X, Y, Z))); } - if (polygon.size() > 0) polyhole.push_back(polygon); + if (polygon.size() > 0) polyhole.faces.push_back(polygon); ifs.close(); + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); return true; } int main(int argc, char *argv[]) { - PolyholeK polyhole; - K::Vector_3 *normal = NULL; + IndexedPolygons polyhole; + Vector3f *normal = NULL; if (argc >= 2) { if (!import_polygon(polyhole, argv[1])) { std::cerr << "Error importing polygon" << std::endl; exit(1); } - std::cerr << "Imported " << polyhole.size() << " polygons" << std::endl; + std::cerr << "Imported " << polyhole.faces.size() << " polygons" << std::endl; if (argc == 3) { std::vector strs; @@ -119,29 +118,35 @@ int main(int argc, char *argv[]) boost::split(strs, arg, boost::is_any_of(",")); assert(strs.size() == 3); BOOST_FOREACH(const std::string &s, strs) normalvec.push_back(boost::lexical_cast(s)); - normal = new K::Vector_3(normalvec[0], normalvec[1], normalvec[2]); + normal = new Vector3f(normalvec[0], normalvec[1], normalvec[2]); } } else { //construct two non-intersecting nested polygons - PolygonK polygon1; - polygon1.push_back(Vertex3K(0,0,0)); - polygon1.push_back(Vertex3K(2,0,0)); - polygon1.push_back(Vertex3K(2,2,0)); - polygon1.push_back(Vertex3K(0,2,0)); - PolygonK polygon2; - polygon2.push_back(Vertex3K(0.5,0.5,0)); - polygon2.push_back(Vertex3K(1.5,0.5,0)); - polygon2.push_back(Vertex3K(1.5,1.5,0)); - polygon2.push_back(Vertex3K(0.5,1.5,0)); - polyhole.push_back(polygon1); - polyhole.push_back(polygon2); + Reindexer uniqueVertices; + IndexedFace polygon1; + polygon1.push_back(uniqueVertices.lookup(Vector3f(0,0,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(2,0,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(2,2,0))); + polygon1.push_back(uniqueVertices.lookup(Vector3f(0,2,0))); + IndexedFace polygon2; + polygon2.push_back(uniqueVertices.lookup(Vector3f(0.5,0.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(1.5,0.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(1.5,1.5,0))); + polygon2.push_back(uniqueVertices.lookup(Vector3f(0.5,1.5,0))); + polyhole.faces.push_back(polygon1); + polyhole.faces.push_back(polygon2); + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); } - Polygons triangles; - bool ok = CGALUtils::tessellatePolygonWithHolesNew(polyhole, triangles, normal); + std::vector triangles; + bool ok = GeometryUtils::tessellatePolygonWithHoles(polyhole, triangles, normal); std::cerr << "Tessellated into " << triangles.size() << " triangles" << std::endl; - export_stl(triangles, std::cout); + IndexedTriangleMesh trimesh; + trimesh.vertices = polyhole.vertices; + trimesh.triangles = triangles; + + export_stl(trimesh, std::cout); } diff --git a/cgal/polyhole-tessellator-libtess2.pro b/cgal/polyhole-tessellator-libtess2.pro index d8697f8d..98c9964f 100644 --- a/cgal/polyhole-tessellator-libtess2.pro +++ b/cgal/polyhole-tessellator-libtess2.pro @@ -80,10 +80,10 @@ CONFIG += gettext include(../common.pri) -HEADERS += ../src/cgal.h \ - ../src/cgalutils.h \ +HEADERS += ../src/GeometryUtils.cc \ ../src/linalg.h \ ../src/printutils.h \ + ../src/grid.h \ ../src/libtess2/Include/tesselator.h \ ../src/libtess2/Source/bucketalloc.h \ ../src/libtess2/Source/dict.h \ @@ -94,8 +94,9 @@ HEADERS += ../src/cgal.h \ ../src/libtess2/Source/tess.h SOURCES += polyhole-tessellator-libtess2.cpp \ - ../src/cgalutils-tess2.cc \ + ../src/GeometryUtils.cc \ ../src/printutils.cc \ + ../src/grid.cc \ ../src/libtess2/Source/bucketalloc.c \ ../src/libtess2/Source/dict.c \ ../src/libtess2/Source/geom.c \ diff --git a/openscad.pro b/openscad.pro index fef027b0..a2eefe65 100644 --- a/openscad.pro +++ b/openscad.pro @@ -297,6 +297,7 @@ HEADERS += src/typedefs.h \ src/Geometry.h \ src/Polygon2d.h \ src/clipper-utils.h \ + src/GeometryUtils.h \ src/polyset-utils.h \ src/polyset.h \ src/printutils.h \ @@ -365,6 +366,7 @@ SOURCES += src/version_check.cc \ src/Polygon2d.cc \ src/clipper-utils.cc \ src/polyset-utils.cc \ + src/GeometryUtils.cc \ src/polyset.cc \ src/csgops.cc \ src/transform.cc \ @@ -492,7 +494,6 @@ HEADERS += src/cgal.h \ SOURCES += src/cgalutils.cc \ src/cgalutils-tess.cc \ - src/cgalutils-tess2.cc \ src/cgalutils-polyhedron.cc \ src/CGALCache.cc \ src/CGALRenderer.cc \ diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc new file mode 100644 index 00000000..4482704c --- /dev/null +++ b/src/GeometryUtils.cc @@ -0,0 +1,141 @@ +#include "GeometryUtils.h" +#include "tesselator.h" +#include "printutils.h" +#include + +static void *stdAlloc(void* userData, unsigned int size) { + int* allocated = ( int*)userData; + TESS_NOTUSED(userData); + *allocated += (int)size; + return malloc(size); +} + +static void stdFree(void* userData, void* ptr) { + TESS_NOTUSED(userData); + free(ptr); +} + +bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, + std::vector &triangles, + const Vector3f *normal) +{ + // No polygon. FIXME: Will this ever happen or can we assert here? + if (polygons.faces.empty()) return false; + + if (polygons.faces.size() == 1 && polygons.faces[0].size() == 3) { + // Input polygon has 3 points. shortcut tessellation. + triangles.push_back(IndexedTriangle(polygons.faces[0][0], polygons.faces[0][1], polygons.faces[0][2])); + return false; + } + + TESSreal *normalvec = NULL; + TESSreal passednormal[3]; + if (normal) { + passednormal[0] = normal->x(); + passednormal[1] = normal->y(); + passednormal[2] = normal->z(); + normalvec = passednormal; + } + + int allocated = 0; + TESSalloc ma; + TESStesselator* tess = 0; + + memset(&ma, 0, sizeof(ma)); + ma.memalloc = stdAlloc; + ma.memfree = stdFree; + ma.userData = (void*)&allocated; + ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices. + + tess = tessNewTess(&ma); + if (!tess) return -1; + + int numContours = 0; + std::vector contour; + BOOST_FOREACH(const IndexedFace &face, polygons.faces) { + const Vector3f *verts = &polygons.vertices.front(); + contour.clear(); + BOOST_FOREACH(int idx, face) { + const Vector3f &v = verts[idx]; + contour.push_back(v[0]); + contour.push_back(v[1]); + contour.push_back(v[2]); + } + assert(face.size() >= 3); + PRINTDB("Contour: %d\n", face.size()); + tessAddContour(tess, 3, &contour.front(), sizeof(TESSreal) * 3, face.size()); + numContours++; + } + + if (!tessTesselate(tess, TESS_WINDING_ODD, TESS_CONSTRAINED_DELAUNAY_TRIANGLES, 3, 3, normalvec)) return -1; + + const TESSindex *vindices = tessGetVertexIndices(tess); + const TESSindex *elements = tessGetElements(tess); + int numelems = tessGetElementCount(tess); + + if (polygons.faces.size() == 1) { // Only works for polygons without holes + int numInputVerts = polygons.faces[0].size(); + std::vector vflags(numInputVerts); // Init 0 + + IndexedTriangle tri; + for (int t=0;t + +typedef std::vector Polygon; +typedef std::vector Polygons; + +typedef std::vector IndexedFace; +typedef Vector3i IndexedTriangle; + +struct IndexedPolygons { + std::vector vertices; + std::vector faces; +}; + +struct IndexedTriangleMesh { + std::vector vertices; + std::vector triangles; +}; + +namespace GeometryUtils { + bool tessellatePolygonWithHoles(const IndexedPolygons &polygons, std::vector &triangles, + const Vector3f *normal = NULL); +} diff --git a/src/cgalutils-tess2.cc b/src/cgalutils-tess2.cc deleted file mode 100644 index f810dc88..00000000 --- a/src/cgalutils-tess2.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include "cgalutils.h" -#include "linalg.h" -#include "tesselator.h" - -#include - -static void *stdAlloc(void* userData, unsigned int size) { - int* allocated = ( int*)userData; - TESS_NOTUSED(userData); - *allocated += (int)size; - return malloc(size); -} - -static void stdFree(void* userData, void* ptr) { - TESS_NOTUSED(userData); - free(ptr); -} - -namespace CGALUtils { - -bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, - Polygons &triangles, - const K::Vector_3 *normal) -{ - // No polygon. FIXME: Will this ever happen or can we assert here? - if (polygons.empty()) return false; - - if (polygons.size() == 1 && polygons[0].size() == 3) { - // Input polygon has 3 points. shortcut tessellation. - Polygon t; - t.push_back(Vector3d(polygons[0][0].x(), polygons[0][0].y(), polygons[0][0].z())); - t.push_back(Vector3d(polygons[0][1].x(), polygons[0][1].y(), polygons[0][1].z())); - t.push_back(Vector3d(polygons[0][2].x(), polygons[0][2].y(), polygons[0][2].z())); - triangles.push_back(t); - return false; - } - - TESSreal *normalvec = NULL; - TESSreal passednormal[3]; - if (normal) { - passednormal[0] = normal->x(); - passednormal[1] = normal->y(); - passednormal[2] = normal->z(); - normalvec = passednormal; - } - - int allocated = 0; - TESSalloc ma; - TESStesselator* tess = 0; - - memset(&ma, 0, sizeof(ma)); - ma.memalloc = stdAlloc; - ma.memfree = stdFree; - ma.userData = (void*)&allocated; - ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices. - - tess = tessNewTess(&ma); - if (!tess) return -1; - - std::vector contour; - std::vector outputvertices; - BOOST_FOREACH(const PolygonK &poly, polygons) { - contour.clear(); - BOOST_FOREACH(const Vertex3K &v, poly) { - TESSreal tessv[3] = {v.x(), v.y(), v.z()}; - outputvertices.push_back(Vector3d(tessv[0], tessv[1], tessv[2])); - contour.push_back(tessv[0]); - contour.push_back(tessv[1]); - contour.push_back(tessv[2]); - } - tessAddContour(tess, 3, &contour.front(), sizeof(TESSreal) * 3, poly.size()); - } - - if (!tessTesselate(tess, TESS_WINDING_ODD, TESS_CONSTRAINED_DELAUNAY_TRIANGLES, 3, 3, normalvec)) return -1; - - const TESSindex *vindices = tessGetVertexIndices(tess); - const TESSindex *elements = tessGetElements(tess); - int numelems = tessGetElementCount(tess); - - Polygon tri; - for (int t=0;t #include @@ -953,7 +954,7 @@ namespace CGALUtils { return err; } #endif -#if 1 +#if 0 bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) { bool err = false; @@ -976,6 +977,15 @@ namespace CGALUtils { polyholes.push_back(polygon); } + std::cout << "---\n"; + BOOST_FOREACH(const PolygonK &poly, polyholes) { + BOOST_FOREACH(const Vertex3K &v, poly) { + std::cout << v.x() << "," << v.y() << "," << v.z() << "\n"; + } + std::cout << "\n"; + } + std::cout << "-\n"; + /* at this stage, we have a sequence of polygons. the first is the "outside edge' or 'body' or 'border', and the rest of the polygons are 'holes' within the first. there are several @@ -1000,6 +1010,78 @@ namespace CGALUtils { ps.append_vertex(p[0].x(), p[0].y(), p[0].z()); ps.append_vertex(p[1].x(), p[1].y(), p[1].z()); ps.append_vertex(p[2].x(), p[2].y(), p[2].z()); + // std::cout << p[0].x() << "," << p[0].y() << "," << p[0].z() << "\n"; + // std::cout << p[1].x() << "," << p[1].y() << "," << p[1].z() << "\n"; + // std::cout << p[2].x() << "," << p[2].y() << "," << p[2].z() << "\n\n"; + } + } + } + return err; + } +#endif +#if 1 + bool createPolySetFromNefPolyhedron3(const CGAL_Nef_polyhedron3 &N, PolySet &ps) + { + bool err = false; + CGAL_Nef_polyhedron3::Halffacet_const_iterator hfaceti; + CGAL_forall_halffacets(hfaceti, N) { + CGAL::Plane_3 plane(hfaceti->plane()); + // Since we're downscaling to float, vertices might merge during this conversion. + // To avoid passing equal vertices to the tessellator, we remove consecutively identical + // vertices. + Reindexer uniqueVertices; + IndexedPolygons polyhole; + // the 0-mark-volume is the 'empty' volume of space. skip it. + if (hfaceti->incident_volume()->mark()) continue; + CGAL_Nef_polyhedron3::Halffacet_cycle_const_iterator cyclei; + CGAL_forall_facet_cycles_of(cyclei, hfaceti) { + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c1(cyclei); + CGAL_Nef_polyhedron3::SHalfedge_around_facet_const_circulator c2(c1); + polyhole.faces.push_back(IndexedFace()); + IndexedFace &currface = polyhole.faces.back(); + CGAL_For_all(c1, c2) { + CGAL_Point_3 p = c1->source()->center_vertex()->point(); + // Create vertex indices and remove consecutive duplicate vertices + int idx = uniqueVertices.lookup(vector_convert(p)); + if (currface.empty() || idx != currface.back()) currface.push_back(idx); + } + if (currface.front() == currface.back()) currface.pop_back(); + if (currface.size() < 3) polyhole.faces.pop_back(); // Cull empty triangles + } + uniqueVertices.copy(std::back_inserter(polyhole.vertices)); + +#if 0 // For debugging + std::cout << "---\n"; + BOOST_FOREACH(const IndexedFace &poly, polyhole.faces) { + BOOST_FOREACH(int i, poly) { + std::cout << polyhole.vertices[i][0] << "," << polyhole.vertices[i][1] << "," << polyhole.vertices[i][2] << "\n"; + } + std::cout << "\n"; + } + std::cout << "-\n"; +#endif + + /* at this stage, we have a sequence of polygons. the first + is the "outside edge' or 'body' or 'border', and the rest of the + polygons are 'holes' within the first. there are several + options here to get rid of the holes. we choose to go ahead + and let the tessellater deal with the holes, and then + just output the resulting 3d triangles*/ + + // We cannot trust the plane from Nef polyhedron to be correct. + // Passing an incorrect normal vector can cause a crash in the constrained delaunay triangulator + // See http://cgal-discuss.949826.n4.nabble.com/Nef3-Wrong-normal-vector-reported-causes-triangulator-crash-tt4660282.html + // CGAL::Vector_3 nvec = plane.orthogonal_vector(); + // K::Vector_3 normal(CGAL::to_double(nvec.x()), CGAL::to_double(nvec.y()), CGAL::to_double(nvec.z())); + std::vector triangles; + bool err = GeometryUtils::tessellatePolygonWithHoles(polyhole, triangles, NULL); + const Vector3f *verts = &polyhole.vertices.front(); + if (!err) { + BOOST_FOREACH(const Vector3i &t, triangles) { + ps.append_poly(); + ps.append_vertex(verts[t[0]]); + ps.append_vertex(verts[t[1]]); + ps.append_vertex(verts[t[2]]); } } } diff --git a/src/cgalutils.h b/src/cgalutils.h index fa4917f5..4939c9fb 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -36,9 +36,6 @@ namespace CGALUtils { bool tessellatePolygonWithHoles(const PolyholeK &polygons, Polygons &triangles, const K::Vector_3 *normal = NULL); - bool tessellatePolygonWithHolesNew(const PolyholeK &polygons, - Polygons &triangles, - const K::Vector_3 *normal = NULL); bool tessellate3DFaceWithHoles(std::vector &polygons, std::vector &triangles, CGAL::Plane_3 &plane); diff --git a/src/linalg.h b/src/linalg.h index 9e7d9f94..54fd1235 100644 --- a/src/linalg.h +++ b/src/linalg.h @@ -9,6 +9,10 @@ EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d) using Eigen::Vector2d; EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3d) using Eigen::Vector3d; +EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3f) +using Eigen::Vector3f; +EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3i) +using Eigen::Vector3i; typedef Eigen::AlignedBox BoundingBox; using Eigen::Matrix3f; @@ -17,9 +21,6 @@ using Eigen::Matrix4d; #define Transform3d Eigen::Affine3d #define Transform2d Eigen::Affine2d -typedef std::vector Polygon; -typedef std::vector Polygons; - bool matrix_contains_infinity( const Transform3d &m ); bool matrix_contains_nan( const Transform3d &m ); diff --git a/src/polyset.cc b/src/polyset.cc index 85328727..a8a08a2b 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -92,21 +92,31 @@ void PolySet::append_vertex(double x, double y, double z) append_vertex(Vector3d(x, y, z)); } -void PolySet::append_vertex(Vector3d v) +void PolySet::append_vertex(const Vector3d &v) { polygons.back().push_back(v); } +void PolySet::append_vertex(const Vector3f &v) +{ + polygons.back().push_back(v.cast()); +} + void PolySet::insert_vertex(double x, double y, double z) { insert_vertex(Vector3d(x, y, z)); } -void PolySet::insert_vertex(Vector3d v) +void PolySet::insert_vertex(const Vector3d &v) { polygons.back().insert(polygons.back().begin(), v); } +void PolySet::insert_vertex(const Vector3f &v) +{ + polygons.back().insert(polygons.back().begin(), v.cast()); +} + BoundingBox PolySet::getBoundingBox() const { BoundingBox bbox; diff --git a/src/polyset.h b/src/polyset.h index cf151dbe..ed865e85 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -3,6 +3,7 @@ #include "Geometry.h" #include "system-gl.h" #include "linalg.h" +#include "GeometryUtils.h" #include "renderer.h" #include "Polygon2d.h" #include @@ -31,9 +32,11 @@ public: size_t numPolygons() const { return polygons.size(); } void append_poly(); void append_vertex(double x, double y, double z = 0.0); - void append_vertex(Vector3d v); + void append_vertex(const Vector3d &v); + void append_vertex(const Vector3f &v); void insert_vertex(double x, double y, double z = 0.0); - void insert_vertex(Vector3d v); + void insert_vertex(const Vector3d &v); + void insert_vertex(const Vector3f &v); void append(const PolySet &ps); void render_surface(Renderer::csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo = NULL) const; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 3589757e..2124dcd7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -670,7 +670,8 @@ set(NOCGAL_SOURCES ../src/export.cc ../src/LibraryInfo.cc ../src/polyset.cc - ../src/polyset-utils.cc) + ../src/polyset-utils.cc + ../src/GeometryUtils.cc) set(CGAL_SOURCES @@ -679,7 +680,6 @@ set(CGAL_SOURCES ../src/CGAL_Nef_polyhedron.cc ../src/cgalutils.cc ../src/cgalutils-tess.cc - ../src/cgalutils-tess2.cc ../src/cgalutils-polyhedron.cc ../src/CGALCache.cc ../src/CGAL_Nef_polyhedron_DxfData.cc From 0e23303cbc2c6960f7cbb7d5829bc47e0a812c77 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 15:05:04 -0500 Subject: [PATCH 083/174] doc --- src/GeometryUtils.cc | 49 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index 4482704c..2d3ee265 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -15,6 +15,22 @@ static void stdFree(void* userData, void* ptr) { free(ptr); } +/*! + Tessellates input contours into a triangle mesh. + + The input contours may consist of positive (CCW) and negative (CW) + contours. These define holes, and possibly islands. + + The output will be written as indices into the input vertex vector. + + This function should be robust wrt. malformed input. + + It will only use existing vertices and is guaranteed use all + existing vertices, i.e. it will maintain connectivity if the input + polygon is part of a polygon mesh. + + Returns true on error, false on success. +*/ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, std::vector &triangles, const Vector3f *normal) @@ -31,24 +47,21 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, TESSreal *normalvec = NULL; TESSreal passednormal[3]; if (normal) { - passednormal[0] = normal->x(); - passednormal[1] = normal->y(); - passednormal[2] = normal->z(); + passednormal[0] = (*normal)[0]; + passednormal[1] = (*normal)[1]; + passednormal[2] = (*normal)[2]; normalvec = passednormal; } - int allocated = 0; TESSalloc ma; TESStesselator* tess = 0; memset(&ma, 0, sizeof(ma)); ma.memalloc = stdAlloc; ma.memfree = stdFree; - ma.userData = (void*)&allocated; ma.extraVertices = 256; // realloc not provided, allow 256 extra vertices. - tess = tessNewTess(&ma); - if (!tess) return -1; + if (!(tess = tessNewTess(&ma))) return true; int numContours = 0; std::vector contour; @@ -73,7 +86,23 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, const TESSindex *elements = tessGetElements(tess); int numelems = tessGetElementCount(tess); + /* + At this point, we have a delaunay triangle mesh. + + However, as libtess2 might merge vertices, as well as insert new + vertices for intersecting edges, we need to detect these and + insert dummy triangles to maintain external connectivity. + + FIXME: This currently only works for polygons without holes. + */ if (polygons.faces.size() == 1) { // Only works for polygons without holes + + /* + Algorithm: + A) Collect all triangles using _only_ existing vertices -> triangles + B) Locate all unused vertices + C) For each unused vertex, create a triangle connecting it to the existing mesh + */ int numInputVerts = polygons.faces[0].size(); std::vector vflags(numInputVerts); // Init 0 @@ -83,7 +112,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, for (int i=0;i<3;i++) { int vidx = vindices[elements[t*3 + i]]; if (vidx == TESS_UNDEF) err = true; - else tri[i] = vidx; + else tri[i] = vidx; // A) } PRINTDB("%d (%d) %d (%d) %d (%d)", elements[t*3 + 0] % vindices[elements[t*3 + 0]] % @@ -92,14 +121,14 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, // FIXME: We ignore self-intersecting triangles rather than detecting and handling this if (!err) { triangles.push_back(tri); - vflags[tri[0]] = 1; + vflags[tri[0]] = 1; // B) vflags[tri[1]] = 1; vflags[tri[2]] = 1; } } for (int i=0;i Date: Thu, 15 Jan 2015 15:11:47 -0500 Subject: [PATCH 084/174] Updated expected results --- .../monotonepngtest/issue591-expected.png | Bin 0 -> 8778 bytes .../monotonepngtest/issue666-expected.png | Bin 0 -> 4408 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression/monotonepngtest/issue591-expected.png create mode 100644 tests/regression/monotonepngtest/issue666-expected.png diff --git a/tests/regression/monotonepngtest/issue591-expected.png b/tests/regression/monotonepngtest/issue591-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..07e1559f478d446b72d144453abc299f9fac3fbe GIT binary patch literal 8778 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 S6Z}R5vfgjMulO%=(*FWta#8dE literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue666-expected.png b/tests/regression/monotonepngtest/issue666-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..08ee92b2216f45ca6b83efbc3b78c9fdabf45a71 GIT binary patch literal 4408 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_puuo-U3d6^w7MGV(Gg@Gv_b z*za4?v*2+)UsdcS+v4fU4h;;A^A5apoi>Akk%?tr1LFsF77l?9E{TSWk4eG`4hI;1 z0L3|6Sa}?_RBYrFP)K0-15&w&iA^DD&kdkj1BSW=phzGivw&_~4p6NGgFVR96%C9X zV)|x4wLA^-3JwhpAqN;-y2WP$)v_Jn7f^6e&`MxfbhO(SsGIo#JBNURfT#h(#Yacg z92$VmU> Date: Thu, 15 Jan 2015 16:07:06 -0500 Subject: [PATCH 085/174] #1156 Bugfix: We don't have userdata any longer --- src/GeometryUtils.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index 2d3ee265..edb1b315 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -4,9 +4,7 @@ #include static void *stdAlloc(void* userData, unsigned int size) { - int* allocated = ( int*)userData; TESS_NOTUSED(userData); - *allocated += (int)size; return malloc(size); } From d8d8ee3ab57b1f7c616834dc4c9d5363a9cfb3f2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 16:17:31 -0500 Subject: [PATCH 086/174] debug output --- cgal/export_nef.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cgal/export_nef.cpp b/cgal/export_nef.cpp index 2048a3f4..f54e8109 100644 --- a/cgal/export_nef.cpp +++ b/cgal/export_nef.cpp @@ -165,6 +165,7 @@ int main(int argc, char *argv[]) N = new CGAL_Nef_polyhedron(new CGAL_Nef_polyhedron3); std::ifstream stream(filename.c_str()); stream >> *N->p3; + std::cerr << "Imported Nef polyhedron" << std::endl; } } else { From c54a2e8f0c38cade64d8ebbddcbf9fdf5ae9271b Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Thu, 15 Jan 2015 15:48:23 -0600 Subject: [PATCH 087/174] Removed redundant #include statement QDir was already being conditionally included prior to the gui function, including it at the top of the file was redundant. modified: src/openscad.cc --- src/openscad.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/openscad.cc b/src/openscad.cc index 9e83b415..c47af0e9 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -43,8 +43,6 @@ #include "CocoaUtils.h" #include "FontCache.h" -#include - #include #include #include From fb55e1485b917223b1c9180b69c327029c6a670f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 17:25:57 -0500 Subject: [PATCH 088/174] #1156 PRINTDB bugfix --- src/GeometryUtils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index edb1b315..b9c452fa 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -131,7 +131,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, int j; for (j = i; j < numInputVerts && vflags[j] == 0; j++) { // Create triangle fan from vertex i-1 to the first existing vertex - PRINTDB("(%d) (%d) (%d)\n", startv % j % (j+1)%numInputVerts); + PRINTDB("(%d) (%d) (%d)\n", startv % j % ((j+1)%numInputVerts)); tri[0] = startv; tri[1] = j; tri[2] = (j+1)%numInputVerts; From ebc1404e05ded234aa88e99f7378b49c7bcee2dd Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 17:54:13 -0500 Subject: [PATCH 089/174] #1156 Added failing polygon test --- cgal/data/out-of-range.polygon | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cgal/data/out-of-range.polygon diff --git a/cgal/data/out-of-range.polygon b/cgal/data/out-of-range.polygon new file mode 100644 index 00000000..de105279 --- /dev/null +++ b/cgal/data/out-of-range.polygon @@ -0,0 +1,5 @@ +50.9504,53.0377,9.35305 +50.2251,53.0492,9.4122 +50.9537,53.0376,9.35278 +55.2851,53.5142,9.35278 +50.9537,53.0376,9.35278 From 1822865b587b6330381853515ef0b9abf22221dc Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 17:54:29 -0500 Subject: [PATCH 090/174] Assert on invalid result --- cgal/polyhole-tessellator-libtess2.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cgal/polyhole-tessellator-libtess2.cpp b/cgal/polyhole-tessellator-libtess2.cpp index 4ff654df..885b114b 100644 --- a/cgal/polyhole-tessellator-libtess2.cpp +++ b/cgal/polyhole-tessellator-libtess2.cpp @@ -17,6 +17,10 @@ static void export_stl(const IndexedTriangleMesh &trimesh, std::ostream &output) output << "solid OpenSCAD_Model\n"; const Vector3f *verts = &trimesh.vertices.front(); BOOST_FOREACH(const IndexedTriangle &t, trimesh.triangles) { + assert(t[0] < trimesh.vertices.size()); + assert(t[1] < trimesh.vertices.size()); + assert(t[2] < trimesh.vertices.size()); + Vector3f p[3]; p[0] = verts[t[0]]; p[1] = verts[t[1]]; From 3f4e6705e86440b83df7f87d6f8be213e63c45c0 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 17:55:58 -0500 Subject: [PATCH 091/174] #1156 bugfix: We were assuming monotone polygon indices with no duplicates. Caused a out of bounds write --- src/GeometryUtils.cc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index b9c452fa..babb5968 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -63,6 +63,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, int numContours = 0; std::vector contour; + std::vector vflags(polygons.vertices.size()); // Inits with 0's BOOST_FOREACH(const IndexedFace &face, polygons.faces) { const Vector3f *verts = &polygons.vertices.front(); contour.clear(); @@ -71,6 +72,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, contour.push_back(v[0]); contour.push_back(v[1]); contour.push_back(v[2]); + vflags[idx]++; } assert(face.size() >= 3); PRINTDB("Contour: %d\n", face.size()); @@ -101,8 +103,8 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, B) Locate all unused vertices C) For each unused vertex, create a triangle connecting it to the existing mesh */ - int numInputVerts = polygons.faces[0].size(); - std::vector vflags(numInputVerts); // Init 0 + const IndexedFace &face = polygons.faces.front(); + int inputSize = face.size(); IndexedTriangle tri; for (int t=0;t Date: Thu, 15 Jan 2015 22:01:30 -0500 Subject: [PATCH 092/174] #1156 bugfix: Fix for polygons using the same vertex multiple times, but not consecutively --- cgal/data/out-of-range2.polygon | 5 +++ cgal/polyhole-tessellator-libtess2.cpp | 3 ++ src/GeometryUtils.cc | 45 ++++++++++++++------------ 3 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 cgal/data/out-of-range2.polygon diff --git a/cgal/data/out-of-range2.polygon b/cgal/data/out-of-range2.polygon new file mode 100644 index 00000000..7221d0ec --- /dev/null +++ b/cgal/data/out-of-range2.polygon @@ -0,0 +1,5 @@ +50.95040130615234375,53.037654876708984375,9.35305023193359375 +50.225086212158203125,53.049152374267578125,9.4121952056884765625 +50.953746795654296875,53.037601470947265625,9.3527774810791015625 +55.285125732421875,53.514209747314453125,9.3527774810791015625 +50.953746795654296875,53.037601470947265625,9.3527774810791015625 diff --git a/cgal/polyhole-tessellator-libtess2.cpp b/cgal/polyhole-tessellator-libtess2.cpp index 885b114b..f0ef286b 100644 --- a/cgal/polyhole-tessellator-libtess2.cpp +++ b/cgal/polyhole-tessellator-libtess2.cpp @@ -10,6 +10,7 @@ #include "Reindexer.h" #include "linalg.h" #include "grid.h" +#include "printutils.h" static void export_stl(const IndexedTriangleMesh &trimesh, std::ostream &output) { @@ -106,6 +107,8 @@ bool import_polygon(IndexedPolygons &polyhole, const std::string &filename) int main(int argc, char *argv[]) { + OpenSCAD::debug = "GeometryUtils"; + IndexedPolygons polyhole; Vector3f *normal = NULL; if (argc >= 2) { diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index babb5968..4bcdedd7 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -63,7 +63,9 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, int numContours = 0; std::vector contour; - std::vector vflags(polygons.vertices.size()); // Inits with 0's + // Since libtess2's indices is based on the running number of points added, we need to map back + // to our indices. allindices does the mapping. + std::vector allindices; BOOST_FOREACH(const IndexedFace &face, polygons.faces) { const Vector3f *verts = &polygons.vertices.front(); contour.clear(); @@ -72,7 +74,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, contour.push_back(v[0]); contour.push_back(v[1]); contour.push_back(v[2]); - vflags[idx]++; + allindices.push_back(idx); } assert(face.size() >= 3); PRINTDB("Contour: %d\n", face.size()); @@ -104,7 +106,8 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, C) For each unused vertex, create a triangle connecting it to the existing mesh */ const IndexedFace &face = polygons.faces.front(); - int inputSize = face.size(); + int inputSize = allindices.size(); // inputSize is number of points added to libtess2 + std::vector vflags(inputSize); // Inits with 0's IndexedTriangle tri; for (int t=0;t Date: Thu, 15 Jan 2015 22:48:40 -0500 Subject: [PATCH 093/174] Updated expected results after modifying examples to CC0 --- .../cgalpngtest/LetterBlock-expected.png | Bin 0 -> 8339 bytes .../cgalpngtest/chopped_blocks-expected.png | Bin 10299 -> 10308 bytes .../cgalpngtest/sphere-expected.png | Bin 12621 -> 12637 bytes .../monotonepngtest/LetterBlock-expected.png | Bin 0 -> 8376 bytes .../chopped_blocks-expected.png | Bin 6782 -> 10322 bytes .../monotonepngtest/sphere-expected.png | Bin 9068 -> 12595 bytes .../opencsgtest/LetterBlock-expected.png | Bin 0 -> 8733 bytes .../opencsgtest/chopped_blocks-expected.png | Bin 10775 -> 10852 bytes .../opencsgtest/sphere-expected.png | Bin 12906 -> 12806 bytes .../LetterBlock-expected.png | Bin 0 -> 8524 bytes .../chopped_blocks-expected.png | Bin 10904 -> 11022 bytes .../throwntogethertest/sphere-expected.png | Bin 12503 -> 12356 bytes 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression/cgalpngtest/LetterBlock-expected.png create mode 100644 tests/regression/monotonepngtest/LetterBlock-expected.png create mode 100644 tests/regression/opencsgtest/LetterBlock-expected.png create mode 100644 tests/regression/throwntogethertest/LetterBlock-expected.png diff --git a/tests/regression/cgalpngtest/LetterBlock-expected.png b/tests/regression/cgalpngtest/LetterBlock-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b976cc7827702a4d1f8d2f0a3dba7d31dd9c499b GIT binary patch literal 8339 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 literal 10299 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 NFw!&Et<=Uu{~tOJCIJ8d diff --git a/tests/regression/cgalpngtest/sphere-expected.png b/tests/regression/cgalpngtest/sphere-expected.png index 8065e9c4e4e1f6ba444ee3a4d74c8bf8a74157d2..8acb26c300440f735be3dbfb28906b860d8b1b8d 100644 GIT binary patch literal 12637 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 literal 12621 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 IW*(9M15Z$nvH$=8 literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/chopped_blocks-expected.png b/tests/regression/monotonepngtest/chopped_blocks-expected.png index 5ef9324be480b70ec53bda6d1a148b2c790e3b8b..50abe82f2cb75082cc8af54e7c21bbffbe65b6a9 100644 GIT binary patch literal 10322 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 literal 6782 zcmds6`9GB3+ducrGzOy?D%odJqR93k5@u{6k}b3`ilha7YDzNPC`*cDZM8*|vb3m( z2}NZ$ie%R(OV*5K*5~%=`+EL>=lSV*e!9-|30xnJj;JI>L;T0%@t3;-Zu zYh&pQ019cM0B+@RNzUR40CHBgmS(QO(63G%h)E_gsRxAH+n_aaVGZ{pPc1ihi^KQB zjQ}i*1w>x}oc{kk0zvv)BN;>w8hIq}t#IwrO(^m%geeNdN&#vL067>yQ~|IW1S~}X zdH4TW69XJA7SJCX)@WbbTeP+ch^0g-&nX6N__!@d)F#O)N!MzvRnG1`c1bl4_f90R z{M)6RGSX1i%BlxW@+KRne*J2k;&o3iuZxXp+VNL3g9KnH3;-$00A#I&0La4upk@UC zbqi8lyCnf|yb1v9{6BRmEIvsB%pxyOlT2O`W3>;hcw`tZX8& z7+{mGz4+l^Xv`Woj_@P}W3g^^3;^m6wpFe53|}J&$GIe7Hf;b@8^O?CF&`R^$>+8d z_kTYuT-q~KYKu}Pf`K-Nv!sD^CYBa_u^Hx_NVL^<&EAIrk5avOwz_Bspz#nRZA;Zf zfx~k9c{_eeHLjv*r$g$mMWQ#2T7aOS>so>bzhhfgF%M`&gqDvav-U)0i|yP93{#YT znhyMkR~-zDZGlsgF)kHio4hSBfMMskLM6KYZeQ3=esgtL0pqnuysUPiN{LOR0|wl) zJs7%kvFbIbyZ_KtRm_JvZX_DLwQd7Ae&E~pI|D;IbOTgoY-Au5emZae(|e>7OtsFB8L(7r9z19W=##@uXdZ-JfI`ali%x z#65U6^R%-EuUA=uO(1KqQg+4|+;!9POu3k0IT&wW!$bkXf zp8{U&{eY(lItJT5|B4t>72UTBNm~jsyv=)mK`^2Kw{b7%>K)$cL3ot-FMR9UruF@U z7}|W>wkM4d^lwr5=lfR%jN1S6{SG_Pmke^FB%_=UOqt!u4J;L`Mzy}-y-%0A-_iiC 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 literal 9068 zcmdsd=U-FL*X<+$LMI4{fIyV5f(X(@LrEyolwMU36qPCbm=t>K8+W#@agnNfY0US3S zKs*G%;D6u61tc}0PE+GyjhuC9I_50<2Z~gudI|-hCjce^fGiq-I1g~b5TM2YklO#> zPWc0ya%Ytp;hC#Zy^lQOhb^I1mXE_P{&cR^QO?{6F;}@9@=hi2uC~NzL^XXNEd#%g zzC&(sc%15DPp-TnoMZo6+qZhr0 zq6f;5x*K?hh$>rv%%H_!1(C2*1yD6+C^&0FgV9KN{yY9o4Vg${-&haBuE$frvd4aulN9hr6mpO&85{4MnzHsP=Z0gx067 zkpo_(+)W>VxJ!?5+895I64jdOhtX;QdH@N9{~jYmX|QqLInf6L#|RLkdXtUwA4n@7 z6ank;uM#SVHu}#b42tl$H+?2qEhCxbqApJ{iMtIDSm< zS%9GZL5Bys(2r2yU(U4vHRhk}h9NW-7f(PDSs_dDSSOIB;~iV*s^1VsQg zJZ8H}_RGuHoj#;)EPt=s=4pZ?uRrW%^*itI;rfU)uq9(36)g1ht|@s}qmIW!CgwP1 zo{i{L{HWR#L)F&eo7xMd#Y+M0!-s2 zHjYx)dN<4TPJ$xL^~u_n|4tA$Va)2;DG*_2n}N+x^IxS(WH>dd*y_%Zn%v^}da2QgtXP>2xy;+g)vGY&W7E7Y_P-Jsy^{E zT}y7iF>!3CHo}~N4A;j0(tWk?EZWR#dwqE5=2O*lh-;&m6au0{Wq;+gGxl7_jT@sk zb_O-lYskya*zYT!82caF&R+`9b#Gkl7(950y@cR|B53ncefQ0u>jh>Vv6C9r-P>D!4&49TMhbP!iCSH?K@MLdhWU2%PI+ zP0QwFDI{5@&E;C*1>r9RWt3xn7HgF|6wa~qAK&~sdhLB~e;c!syG3L_m;loBn9#*B zbdpJ=;BA;Fch?5t$kPskacMDHvePrLDsyo-7r?Wzi*{@o7aoh&>oxftpxDX`MVOLz zydL!8yl=x|AgIxuB*nnQ8uEvvP6jT$^&~~XJ`DIImSi#!kRxk-%=`9`AX0dN_^9Bc z3!My(vv?KVP@&?}O(hf1*G!Jc4WF5d58-FGLP&&w;DKQ~uL<|j0lm?_M3E_uDAtBLeJn=XP3K-j z&8hjTlKz{c!txI#0qtqN#mfA)oi&dJZq&^BndDz0+(++?_J}nF88HTH#IHbbuPP~p z9&>lLlb!_o9B|aT-P3B#4~`w%`Sr9qpN4s()5>JVL^QE*U0TtMT|!JE7zCSKF7`RB z7AqZU3TmRsDRO+UkPY$VA4Ats6&JXnay7DQ!h7`%wz8{gx_-h?b zqe&IHpQH;mR+ObKp!nO;kJ~V6cybhs1vly`T8{%Je`B9|lwSDLpZ8z1*_Tj08l<1w zt)DabkL`aRml_t*^lR`c7MT9>`nsLWxE+*wOm5rc5O*WL=HV`0U9VeP#plu3!@_gj z%$iLOBWQ*N%CvPN{HMXO1i}m4# z#6`Z;I7KAB-}N}B^-~qaoeDf#Q@wQjqtG~zFnrXGD5mpv!9MP9pb!aeIvWKYhV_>S zJhQCvc9?c|rdI6APd&XcJASz9%B;KXslk!-!v6&9rb+T{>%+d-7$hdSO@Gc}sjLD))8`2M>m|tviJ$IflkY zz6RSn%&O(qU0^xLqrV?^oERc)8qEZ_HPz${A8D zj8Q2>p$9WpA{u_yFA8@*YC|QXz_7#>9;y9heT7*)W)lx=f*s$Kp0~&-X?=cYWHIzO zndy9PkI?MVPU3N88;TRO93B0t_F}WWnKfy}w&+H7FVipbY`i?z_a z=khAX%L8d)Ao(it<23?zyj`u)wW2{fME}auU{s(guVVzBJwuukgJABMD1qOucS=SD zI=)kSrpNa?E@mZXkLi5JXq7|fa>sA+zJ5(TnG1uXsBYTEC6s5w)f>MQSI6GByE%;u(lNZ&O zIKPPXIyXIJW1HXLZ>;(H%(#j0wbZFm(l5O$L#HOlh}P@Epp1$)&-7w?XX&|Qn2(-+ zV)nGmEb}cruh5z`5A@etCw)UT3LSz_&~*}Ps9RrE z*`dm zMgETmv5p!e=67-?QPnDtP~~M@u>*3LW(ip0XI`hJMd?2-)i)F^b4osH730Kd(#vB^ zc<~Kz$Qfhf)eK#TX(rgKqJ|_@h@-^+c|YVYn2_`Z1DCa%a|O=3uPthBri~T}3kdxA zpi*^k?X3p3xj^5AT~rwos<8~R>3o6_eAZHwbzQZB!TN0dC5e%@8ZBX^d=G6N$NIos z85l8|?LmLOJy4TBd?s)5SbzQW*JVCZE7% zYIJdLU$F`|U6Z^lb-`c(Wp=H|NMqx(8%me2Ei6W~aQnsf_VEG5k4R|lNNt)Kiu%)O z{K|*ms+`9PYFOCr9+%qdSSKha8Glf2nqm4&LFH21B3gd+N0P7DVPih)B?7lc=T3N|7&FL#4ttCT#Nsk4HWB5+}4R4mYe$p8RA9 z#5e)hm0wA(wjKn=KG=BA47I+-mmg)Vy7k%Xdcd7$u4wfpG2-i+e84*=@ww;CiF>;j z1b0)ypI`dxHMFHVjNtdC#Ny4CYt%x7_CZG}UkG{Tx%<5(FqKIkZ}CjGlhvCtAMAtm z?@eDVSJ2%%ZthvUx;=C!S?}4TQ;Ar>dvY9#HUqR?biQ+T!hA^qq`@b)a+7JHhXyYNV`Es3*ouDH_&qpN#Y`G^S6EPJ8JB|K%FLK0^E3$xS;9l zWYXs?+k;Ed97j2px}Bw>2X2j9c|}4jSU0Hob0~cYeSCpnU7?L0GpQ%wk-25PGDXt+ z{=LgPMFsl#0NQ*MFeNf0m%Nj5QzBlrJ*YY0mh1;*a_sO{PlO(x9efU={=I+sXDmGT zVaL!z_)8HF&#TlS1OH+4_SUMYnX~?SUC@5Aum{bU1ZDp@bgE-dN1YD>e3%$oT7G}@96o7Q$AsMhzSb-q@ z#d!Wcz3K}RtV{YyIeA%l_O3H$ioPEo_UvNwbZPug%cKsVrY0r}1C$g(-+BHZ;sgTD zcMevU(G)ZVD2rD;saLDJ`KvqB6%94v@_>$rRJ z9vg5uOrwqd-%(gZ!-pp__9rq*vKA#+VU9*7$vFFls%r|J)Dq$Gb77~vjM z*Sc!{T?@vmB)H!D_7F8S(FN~=ID|oECLQW)4*Vll(?LqRiLGoT?V#nzC^L$=R39kg zc!*E7q>nrjm3ALT227d0L4msYM%bIDjb`qLF)5=Nlkg3C4s^_eCEyylk&!0AA77nx z^v@vM(n^BV;&W$bJsovL#@8u-mb&@-)zNua{Sa!udYK|W-5eL3bJSpv4o-v zOcJC_K1PsIz_R*qSU9LRcrECr4-N%A&+ISp5}L8wp-Hs4m8<(C_q7s{qwz!_3x|M{ zGNdo!*nVcFhuMRXSDzuZF0qbuKw0lJT2e!v<^**axhMMIYYyC`wvEaXLk&PJ*j8dt zrgqbu-nvo-?>8E^q1txR!e@`;v7_F*loc805BESVA4eA57xuwLyM*g_olF1ZxCvah zT91^sPV`?r8F9<=7DEJccf}j+^l*^@<>#$aF~e)!Z@R5IDb4_Pjpnsz2hN5il z+evkTk{Pvg_p$gtmCt&o0+dw~wD))BT!}^mVa%G$62!X1$F<0B6)Y)(KOTebg&Mev zoWQCNf|SfbyXb>)WjHP&=ID$HWMev0KD8tphLK`g#QNPg(xb5v2D+Ir3=h*H+aU(B zk>%t1v4WNlWZCpblNPucagIcQ=tvTu{Pa46h#oK3@1>8R8Z1uy!i3X5HSo8R5Ht>$ zbLitb9YvKWbCO2>@n)EgqM(8*#C0}P-r_yn0qmXPqqOpJ0*xYge&voT93;gYeNu+F zuK!>f=|TZn;5S^HI6SSe&wg-b&8(m^7=hXb8&G99$zti6wdyLZ3zD9R7O8{>oR>XF z0_nr}_wAgFIB~X#d)wblQv`zqW`i{R;mG&+dN#j-0yys4&!9mrzTSZJHfYSnQxr|? zeg;r;T{y2qqXXO@TzJm z0)6*xwKQ%X&ft8?T&ehq&|vCz@@oa>T<9+A8{X6YF-d)Oz1<@nHZ?*klXW31Y+BTo zYHGmY)!JuPgHK4ZDOWYEe@t|+-%MKHjiGhqOx_06oe%eGH(!}m++RNodJ{hDYSpLT z@ROCAxKhf0js23lmG7F<&&#V0g=WgzF68uF(HcK;mnUV?DqkXN!{ z=S1=C%c6hg++P{SUMP&<%)w^gbxsjmx`kw9#JRl49p_gpf6t1$*>sn0jp92Spq(xH zkvlxofDM2@Z~lAp6KfVuu*>ZD@o4tam}GNRrkV3a zPu*C)^1$fI0z|JHIS7Lg2$U#E6v(8*sjQk@l%eo$yA3)S=)o(Aco@db-)uxo%=rPI z#72QoP-JUXx(`hk9V6yk3G6f;%s#q8UafiGsQPaoCC^@t^Z}vYEAp28z2=-t=!T_8 zg`E_Kd^JVLXAjTK)0-C~jz&oEYkw^(nZxahr2Z5vP@jIzH&1w~c>N92v$GJY3C&Oc zGC?`|c;zmLv#A#l-DI=J_u!3GrKqJ9!`o{nPV~#_SlrDtHM;g{fdoskD1p zyX~mPRbC_>nGeylLEWw$U+tPz5GBv#v`l!umbpi*At!h9CDp>X7r{_oBwG1i#bZ0lY_r%33l~bdVBu;vQan=V_5~3Xkkv^d( zYd$0juqZ73CZ0UCn@m4I@FV2$(@5c|FR)Adm(aJbo17%{dd-_mAYCLM z@a_s+PJ=$G8S6DuCf}f=MaHJ&lA^Lu7-Vs{^6yICB7!|$Fz23ETq1nHN=X>hSFoO@ z=xrWuqR_Ifs70j){Lv80oc7(ygIVvuM?U;3H5_W_F1SnmQxYNF%$$WrN1}4W<&21& zm|@0Y(RH==i!RMBM$xcapCT@2`?`F5caC&cE(xpn(7T2$Nq5O+^#|D|a$R3i+ zS#=Buh<)j;`dRknVub1~=9_w^FAtg*8EzKIWt=C!AHW`LuICX>>STi3tCPCwaGF6@ zyX!0&DQYC4n4?v7NVTOYe7w&Q+9^rlVe;^tbeXP!3q_9C6bR`x{MIrht@DpNAt`sF zp%u8NttI!)kz^e*vRJWBAHt+Qrj`)P18hr91;l%92;_>g+H#=H)i_#XKI~4|E(Dbj z&1wh#1;228#%~a2ZBX{5D4Vc*4}Nw1)ENz0&UWp%ad97pMHhx&Bw(K4D<99Qd3xT~ zXJe-|Jhm@7%I?W}MUs2>zhkhf3>j8KSr6$85%Ogvt|+4OvU1+Z@{-vH1l|jSp1tU= zR?CH2a5W7EzN1N=*!Y8xn4_BCaQpNT*3)zk*NiHeMcrKo$|>*2^(|h*J^P-!8O55| zOZ$0n9K!&l9bRji1M{;z3VCOkUA^rMugfEptv)@0c6KInP==;E9WE{6mc5UYPQmMz~G?`3#|nJp>LELP4JA?vP5=p63FwmdtoGb7ILFCMS%wj>Am zo>qro3M11#@##ktFr3ivJwF}bJT3RY|ND7LrZ5<%mq!*ouWw}Ry`Ap08O{~7fC`%# z8OiV&Ul-VATqVfg91-sq@024@9LQ*f8*Orm;Ps2AxVmw}<+4ArS=#sgs)rdOJ#n*j zZTY_fi5h{9K0uVa@cDA(M+?_#ajtIiNc)QBL1&Z7!7i)IY7$Y1A{hZ~WnKhl`CMh+ zy&t@E5bDuOx^ekOzdg21?^QnbG{sGYZ1dWMYUlhSu18Fk(HWI7lfo}NmY07w`X*a{ z31#MPSn;QEGc|OT0q8>VA#>;y7V_wfZ*zESCq@uF^ek%?>KqMZD7&n_2Bb>^0`(SD z-PCKbybA1QkGl~16*-;E?-s_Fw!^hww}55U#1gZCMD$Z!C<^ls4|poDvUid3Q zK0{bG@}Xr4QUoS=MKNB_<=fE{aSuy3v_jU&0fD)_Jb0^iEGr`E&R6$1D~g=yOzn0> zSz1@smd^unsdIhZX}m{q_FzC{PzMM4M0CJ)ayF6?bZD{Uc;e(OV|hYtKL&6kA05|m zy~~*o5Po;0hStsi`r*{Hkfr7>6+#wqUE@+Q9eeyY=Vk*!Ng5uUK!oVz=z)3Q%w65p zZ{I@tAS6C-!JCWjj}{RI#)5pvM~=v1*tt!q0_Q=aa>u63YblF*q-+!;@QC3N?uR^a z`O=*z`-^mkJ0_h9w=_r7mb}Q_cRB1r!2qPND*X3$!Rt-&%XBB#B~H`kFFbUXlB0wL z;CrZYxt;%BasQP=tH)D$Oq^vt%y9R?2bI!)M&33&3m~Hp$qTfNNT->9+jF?b@#;gi zQ9f*d`Lf1`Z@!xj=9{ef3qe^)vpH0*^VG;;#yo0-(hXr`KK-w0Eahda<`sC7&~7Er zMWiObgADC?-EbUx`=oyCmm%OPe_?VNtth}bntl_jp?DZh>@59Hvs0)do01z5A_>i%%^aV$h+{i z{hn^!EP*f7sSBGI5RT4azQ&8V0os_vqZ7NESZz}LfjK`_GPpO<0d?0H-cEftSNb^N z#Z8{fv-SCW?L?Tsx!uatROD4@MOciOQ(&Pt$LH@gpQhZ5*X*f`$#2WcI)8Utaht^+ zn7eTT)6QzVO@b5s2;nNz#+``oc6d(;Fb8c(v~;_0WXqTnaz+ zTmT&{0I#zEXf@;nz&xD#aOH*pb@<}nJFY_jE>{?U3eNxcO@&#s8)#pTo7A`8?Gjxr z%Ra;PI0oQNeH;G2?|^|N%-q)lNqxKDis>TwoM{jb16PIq7aW}UzfOJ7v5$(s6*!Nc Qre+mrUDs7BQ?U;GA3e7Yk^lez diff --git a/tests/regression/opencsgtest/LetterBlock-expected.png b/tests/regression/opencsgtest/LetterBlock-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..bc54e6702931aee7cbb2b29c1ddf4f5b7d03cbc3 GIT binary patch literal 8733 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 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/chopped_blocks-expected.png b/tests/regression/opencsgtest/chopped_blocks-expected.png index 1288ff6865a4ab13c8dea36a935e319c1d91ed51..f20736adb0b7b9336736875fc0bf42eb227e033f 100644 GIT binary patch literal 10852 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 Wx-y++SK#SU;5gp)*i#el#Qy_!y(0hs literal 10775 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 literal 12906 zcmeHuS3px;5avw?5D+9Z=@2@i(gg&8&;+E4B1#t&klqxj3DOY-X@ax>(wp>7P^zF1 zr1zpgKq*QOB-yy-VIOy&|EDD9o}A3NXJ)={zB`FEG18%@<)j4wfL>2m%M<{>j;XlCS;pla`Pj&2(HG_n}J(1VR1!pTmU^80t1p!VC-rKwv->2#Nr}sZ0n!{Mk*%e{&H)GZh>FLGRrL zKqcdU(&_)r04;Npr^8JygCJJd z`Q0LEax?0DEE*%#!Q_HMNI)7ZDphjyZ8t?B#GUfpwo|^{*e@Wx7`@C!0cHdsKvCSH z2Z;a%_WK9BhzwS~WAshNE@uZ{bU#03I#&wpq4^WsxM-f8Ku0beeXHWMe}#6q5&)7?mEj@HG1uAs^w%7|VM`_#*d zojfcReaT}O1?Ub@d_lco{WqL-9Rz{99-B=C6acyc7iHi^zb)BhOpnB9@~<^A$9G*` zeg%M+UkM%d!0j#rWmhiVUcO3EcE=kfgp*S=N&~=&6|VOF6$H51OU=<5Fr0r_n43jnp{G=r#N*gxaA-;)99y;t1f2rEIS2A2}I35K5~Hq+tIiT{2elm-rj1{B%M z^{n-52U!vVu~QMc##-XvQ$X2sVv?BSXF8!r zQ=JvL!`^SnTNPMneLU`UU@N|LMkCVkS1}OXG_CkXkahD)*yrzw5p5V^#9$J&ZCmfi zg?g@uzt?%lC#}>8{hoYh6tfV1E8dyS%P7N|fhth-wm7HvK0fp2xzr3|N#n6K26OC> z#iC$cW2MX>-F`M=kc>3GN%>weZ~cv6oJvzY^OM_;!0>nt3Vg6NLJ31-g<}4Zfqk&F zS3><--G6XD{6+Iq8gLkm6a|#-Mdwxr11Z|@j~LZYV zWgScJE1-iMb!q+*R+4q9p7HMT{cnZF<2VU98;Yrk%irON za^y=-kK?!JC9O`_ZY)COCJi$Gw(>?ixGI33dl4oROO9D4f7rr40>MUcCp(k(9@ih= zU`%QBtD-mJFqG1Hd@3i%nnCqXX6~fVBtvd6KH_%3;~IUQsbF|fs=d!c*)UW0C5y60 z)07}C@a{QIxu>{JXwr0 zh=%D$Z^}ntB*FpDm0PkI)a;B;%mL8A@DsmjwXkyJvD41U{z!S?g*QYQ+!g(aPs&w` zRwt&ht7v{YAKosX#5ZEU9R3CRXn-e#lXJOp5hA{I0blD%&HG~I@4ISauo5XkDtOIU zRkTi`<8glr2ERURFXVU|WeXV^_g+{CU3fMnw=;9HxOCoMRhRZW@aXr(l9z(YTk&-e z>3rf^$IK-Tdg3J~$YmMsgE_;C&M2D)&Zrad$0$A28{sAL?oRPlGro)jv!s}_zs-yU z?bR`bg|fH?hQ>;_nZqiDhOsMp8SI3+=z~v9A*NBAuyS>afBSHEDZ2nuRw>Uha1S`ZRtK{gQfR#zKz+`c0_h_HPF+iz zLcDD+ak3KLZB2A?pPnE+#_#`WP3#lw?Hw2#CskPk?)~50kdB`nGG4R>& zo6*JS(1(F30PdCAx4!z_USsIr_aJsnWV0TsSqv|(LsgHIF6EP<&|T1cO$^y1nCCY2 zpMM=L!7Vx4FPCS*SR^SZAWUCmqCz)9FD|jVR2)rj&DtVy4ZCOIp6vRja7wVg0<;Lr zkC#F$|KK~VxneUKG}Nf%?RL<_O)SSp(hVfsUV)2%&Tx{GE}x%OShvIwYj5O%R%Qzw z6Uenef|SF(!`1!!HqT}fsUqGGTi-^jHr8mOMSZy6prC}K(WMqHdnUVpsw$8;-ZDqO zhJ_q@mtTA;W3WG|9;BgXPXn3B9Dq1s?>|;7-8lFqJ=I3J!#2?zulNDk&wNvU4ky({ z&uuPpwjGySuu!|4REy?=l;|b}$PJGGMdWOzN`ZuNp4nNe->=tl(Km(>HHSk`;0@-~fKZdbt zA*=%dOkQ&expfb>Inp6$P=N$0Ju-kvQN+E!@oF?FyJ6^Ap7QRE*^FO_&g3&!Dx~^N zTnn_7s5F`8^SgyS8&gRO-ZDA%j0kXhS>`C(MQ8V%&ClO%a1Uc$pvoU3bv~usbq`T2 z9ek6UAZP&A!kXuZjV5zawDC-5$iAp;3e!ON z3bW{XKByb`p@r;V5a0O~JC=|EF>qq9qk_Oi+6 zG^26V+{)7PBg!-giWEL4H3Z=3ukKGBUrt(?M7AnFe(O>|JEGe32b?i@y-NgtTzR5~ z^z#*WT)7m7K)(aP*jFNsw^qAJm&G{CJ{}lsR@y2ZtScCm-W>Bi#4WL{jmdorWp#cb ziqb;}5VimDE>nee2GTnhK2l)~QMMC2JT0_$x!7WFDy2ii zyeyAB&1QadQoTe}!+f$}c)o-e-nKlA7Qk|0e6eAEQRAK1^KYxb>i-f>$h!)A8 zGtigt(u=|I(VgriYBFT>l-YCiZ3_7-`d+USQ!IOKI}7Z&JFXrIvlDv76S?Hh^bod$ z)eMyEbH&C*bJ5L<h`=4R@@HZ3V>XT?(I z$jJNq;T;)xSnc&?BIaBJ@jT%EH4%^-#n&Ar2-(Bkp2K_g)UpqA4VBAp;@`fy%U!4Q zfO0DnQX;BR*3NAz%?U~$V|JlH*iyc))2wV1tRR)hUr2|{`*m-x7Fg%`JSy$qGpUVtzQ~F1^rtjxsneMyk-F)-LX~Cq!9ekl!u7u}KBW;Z-dLB~Zzfa}5Qk+eO70lDk_Ayucpg-Nd6a@bSB4JLlEouv+*FxQ1F_)UB~EN2NJZiEpQ~Izt96Sj%0vHK zzrX=AA-My9p#rQ5JOR1`gfpsp4~f>O6@cNmi8{{yx0&zW55tRqwz0@FYaTU;Yxl#7 z4zhfU$yGuT_LcX}6UjM#)dGt_|Ffn?BFQMK#3OUtIbi#}Xi+@pVI95H+s6G(C`z`q zL{w>@D~0&2lUSgXn@#mo@!Y(=gS(!ZXj4|01S69`*gg7ZTffw@xqy%jowTq{k9b4A zHj0~#p@TvEQX#A{*xg=6=_~4h{deAl$(=f7Zn>)zy%i*}2ONgrG9IGZDaBm&Vy8QB zKWvSnn?&AYsKcUcNlz!17QenY@QdoI60OEU?zPt_%bxWRg| z^J!wm{&YP~ud7{>c3V?)39$IGn!x+#43(I}2yz5AmCAi7?3&x&VceqebnoKRetA5d zgbrSI0qhP;&n?Se`&g}}@#V1sg}^j#N$mcyL~mGs&Q0DD{xZYYfGleKX6-0nG(D;& zt>kH#Ddi-xPsWd(7~Rb5=hmbhz<4lG?2S+8^l=jGJ)0um;a&PWD^g*?YkU&7Jw8D` zP*vnSV3uEW?RaDdS@ouV;Q2}qWu(c=)db?~K7UUC;hrv8!NhJ-B}+~`Pk3@CA<52p zPATZnwzHYQb}gs9whEhv{+4WeaRRR-+#e&EL%puB8e$E|AHo6ol=F8ShqUm_b?WCR zcOyQDE_ z#{9YP{q-0FPiWrTq`&4h^j?Opb?WExU7ab))>ca})T-5%OX57>r4sb^rI4b3=rfWb`r_Ch!A2PdVsXXEKY1vGVPPGwr77qlhjc2bTfnko0dU1)me-mq^W`4lg%CRJj1D$c=(q>GLb?0vi@6;@*51=Y>`Z z?vjzCiRW=WRkFrvpZ})L@e=#i_l*1M zHG~6jA{jJl?y+zC^zgb-0DnZcTPPvR+|H&yoiodT}uoETs_m0RUgMRHKE*%u_w7whP8GyoEa;eb!O7*k&)(_vh zQ|b{p&vOj1se15RO#Impot@)GsuIJ;0NSf^fejKY&PK3SQr(o=T7X?<|EJkeL8&*vjmA?sxQFo-V(1& zz~vVGU_{9gYCpaO@q+Zn11O)l4qo6FqGH6y62I6mLJ_r94|mgF(+RmF4u)gR;28Jy z2I7yYqs<0Je6cK@1w{~`{s&)bRRyJ-kAJVhhyXO+9@==C zaO};^vE+dF?HRjCHSDox4zb@XbA-_WrwJa}+WdktyXAk-gebcSMRypgiutLo1WbZz6X6FO<2zvP+X)S3W#vvYG0R?oR(1gWLZ`l7CePq zZD*Mc7_eQNNGTbGBJ$sGOk7JrhrKdGQ^68!IsOJk+z2vr1CQ*0b9rF5;pIWYJE=_b z;GfB%o6l;7@8(1^qW%WAdW=307EAsNDgSFt%CPf0E|pZB^7e0PQ!>3P(8XkOdl8C# z=VBiH-IkJRH~hk~mzr4|x>_~V91s7Wci?cCefGbjuSjZ{8 zz{^lP_>Xaj_xIBrqx-&KVVWHA#gZaaao6`;l@p%~&UNZI;)sg>cXRVnQ3&}9{3VWe zH+IG{`)d26e>c9VldfKUbFrO8$)w_#@~pHt6T|eo+;QtEnJUd1Y#ClQU?`&dDcRz6 z7EV2M>YdXQ9@;_rx!%bAPokk|vQ6g|GEmZ;@}a}ik;1KL38?}A!ENB72#WXWzAkR= zG)S4quSQHclN23sp3@-`m1P@kEXR1J4BesjvsaG75|#*Q>DQuM%k!x7^As(icS9Lf zxnDb9_wU0yS5mvjtRPL=vr`3u><3^GkGYQRlf0|Zj<>{2nTBt)`~B$ePDrau@(@~X zLVT)OloWIEB`a@=1-@!EcJ$7gEx7Z%C52nOLelms-J~N-HuN$S0U3}R)wg@V+w=6{ zl^%Utx0B<;uWxU91O$IeRmOa=JPWE`jhCfkbM8wkTsSNf0o}D4y&sdBdhH@BZ&o|g zllb+E9jh#Q2zt^C=uNO59C#Zhd1(Xb@dq~&dw&#_j+5lJirxDCWoygANhua476nwl zOdm_tpjdY!LO>oy=k?d1F*O)YB88ADndz$T7hZCjL=|@KQG)N#!0-jDJ1%q}Tt1Tm zJ$=kj=428aolkPDp3l&VF8d7uCq~STqJ-uVqV|j?qqd%jJa*Z)vdD7G#f`Q5J*r-3 zo(!H2o|^oH2ypf&2BGXL^>os3fE&=>F2DkdkzA>YueF5{xP-X5d}&AEQlkAOM$WE# za1pQBIBgV;@6|!fa~O*8_(!i~;oVvz#S=5x6d|_z?qSc%e=PMo^JMu#S<__t?pe+=T!^6I=HI z1RuxuyTbqY&4*cKe1kfw4fVH$rAJM4hjFmqdg3UhIrr@^MpR0c@KM+ZM^^F|epZ>p zq%qtpAuPu+gX;ZtPd?Tkeq`Cr{5Hpn`)#gbnu0hVX^4_0=Jm7Rz?=!K1r?cEDm-5M zN~Q6=(1Qy+oVQfuGpGfZYF>ur5#DFAH!#do-yT4nAF#qz9)YWadpT&1JxW~vG0te< zNm4%@oLPsX?XoB&pIsSp>pn|50@bVrvhgVv0KT+5c8NB5Sqiy<$wZ*BBZ77d%>^F> zfICui3ij=c1D)cf5CiD%*gLh_%kwH+{Ga*p3`^h-&rz1{Nw5U6`kc_Pk=7$Q>Cto& z;3opfX)(W(9e0*j`Q(J}{hk*A+9j3S)l!Uvt9r>6m+8>hn+!LEygg@!ETLJg-|i6@z$&!-ON#Anj5v^?s`9eQ)@ z%0+@#c1^{pL#~qD!z6okvW%nt$HH7f1QdOAZPgX^jJoYYKJ|i?M&Ua9ueqxdO2{DP zwnW#9k2Rd>a38wu>w@Vk7*NWW?vITK!W^S`)jIq3kYCMUjaR|2wB4B5 zH6cWf)X-~$Ab!@?Z)$LLAc@NDP6AK8kp`Ea5cxYD`k@JAt;LeR!B7+h7&zhDqAEl| z4tC>3^x6EKvfgyPEJKZ+Ak$G2vh!$xCCJJ(7lsm2k(5L4U{u|8-M^bWJ~;~AEXD11 zIErVHiDfzz`)d;~j^(gqlYG#ApMN+TZBvnzwcbGD|jvB!(KL6$D02l&^mf z0sVC=0voa1xXc-*vQa?>dFSjEq#Rqk3lzj2dFB2}ryj};Bh3m^0RN#5YoUq3N~&ge z*qtoJ3P)<~fb~9I2oHfJqv|Y4RUfFP=S7tsC}hCWjSvZEO~?)BHjOBfyGZN@GQjmP zR(jAGgCGCtyN5RGze%&|4m+Pvx3e3!rAGa(d`y+ta-onaE9)bzkVIIGWaMxb$3m_V zg72_=RwUY?20>RO^T%T2zL)J%Ar*Jii&PVG z4X%k0#I`IKtof#2A!F#%AdlZdh^8o-Fr#n>QE+zwaYg(gfp0xoL*k!2M|Fml>uP4k zn!mpHveW82KUUlBxT^Aqf;4=XTVX=<%O1#)QRIf+!7Fdor|TVcCATzA{E zY6W(NMz;N*&5wF|iZUQ)>fYA~1(CJNUD2R9z_5w5J84u${}6+48i#4yEb`-Zylb0orGs8* za+C`E5bAows_Pdr}1T{teS=6zyWtbNB%wm3Lw!)brrb* zKF~my-nvBKIFL||SPv~W&94*-TMZSbQa;qwLKg2UUbY73=$LMDS_F?oP?e}jGbCQo z_=^$Grhp#6*m;Ssu#yF8-6Y=777;<9C9tYssg)|`_e=pP!u+fMgJRL_{;y{JHK7$6 zzOoLp{;c>zkq74)RM+$BPNP#2WzYS!jVOOgc1=&&tcfS8A<01?eC%6cmB8Ju>?w;x$9OZXsF>&gnbr zn-oiA3X`?1S0(BEMZp>JOg}CAT3@Z)Lt5o%uQ$mu{5d8>h`qc$mVP)ToSgjrIE z8kzMdexewGn;le=Vw%>`$l+%P=XpPqxU{+%auDqSv;@73R$8<5*mV1@>&y3wM zg&X6&OePm?{!aHVC{&vlNm2)tT1^2|tTu_y&1xOazJFd=IA&PrnKAo>U1b=>BtMvm zg(7B%+cic8lpm-bcu>Ve!dtlJ?=G3j*nf<0*c_U+L~$}AOC_ppi3im?2Nry(YwD;` z3*OMbOZpAma^C#T%}y>E&W5T!H?7{!N5-7solr6TD{7-il<&;LufX8ZF8WzmTDa2O zP1h%X+@^%`@f)uf`c69YF(+$7YWO{#Y+k_{a+d~z-iEjSjs*40Jgbrmzw^g$-@bNc zsJDDxzVt^S_6ARbLMRQv2(GV80}}gIAaMkxe?SUq8)`Y)AU^|Aa>cPkMTy5mhvnW} z3^=liy<+)J{^{Jp9ut8liWF%4b9X^@Zz|(n&{tkWLzO2NF{76;grdpXuEzQ1C9Ii{ z-FuVBK2bY|Z)MtE3Zd^et|BqJc@9G~Z#y@;k@-j=T!vitKO)<^xn6~|<(_SNFjLFk z?28=Kz?SGCxRcu~0)D83CMM&x<^k81byM7v0EolH9IQ_dqT!oF!?)Si&eLaAc&!TSXZ}i|$ny#5euutO&<> zeo7M1C(E(I+`-Z?*j-RSbcv18O`^CQ0y!}vCXFo@|1&*>H@2N;`wArp+bBxAX#n;n z5@oNCd=jOMT~M`Sx9EZm!MB&FFLjf`u#$;GxRFZLt*swjIRMyhBrd6##!rI!y4=^U|2@iISJLr96HvIeYmc7|TYWA-K1HF!-OuTbDi@^7~0wC@oBoN0j%;j zBG;BP-G$>WY^HBEcv!#D8E#|>Aay4fM=pdPdV*8)VTn9|o6Tr>jo(RLYk?jzey6KTV` z$cNj7DqW01I9M!~foz_GMQBk^4%8Z3pDz&S+@?*a{!jDB{tK`M4cYkxeZHe+DD4#S zuh5e5f;$PAtBQgw=drL6 z0MeaT_w(ciS+n*Hl6QphSwbfKVlL!Q6en9@HiE5Agz%pI&77Uk2f;g=z9gEG$IAsIbyA6|X_uY*{M{G^2rH4yc$@Av_SlO29}+-M+eoWQ!|vt(0K~R(2><{9 diff --git a/tests/regression/throwntogethertest/LetterBlock-expected.png b/tests/regression/throwntogethertest/LetterBlock-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..d75b31356b773dfb9a553a4839f43991e9382e44 GIT binary patch literal 8524 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 SwI4v>&vK`&d5I}4?mqw;tCvXt literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/chopped_blocks-expected.png b/tests/regression/throwntogethertest/chopped_blocks-expected.png index 9bc4306698f94437a78224f1e4059572984e369e..11e0cbdb5c9685c85f13a19e80dbe187cff9029d 100644 GIT binary patch literal 11022 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 literal 10904 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

    This list shows the fonts currently registered with " +"OpenSCAD.

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " +msgstr "" +"

    Cette liste affiche les polices présentement chargées " +"avec OpenSCAD

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " + +#: objects/ui_launchingscreen.h:276 +msgid "Welcome to OpenSCAD" +msgstr "Bienvenido a OpenSCAD" + +#: objects/ui_launchingscreen.h:277 +msgid "New" +msgstr "Nuevo" + +#: objects/ui_launchingscreen.h:278 +msgid "Open" +msgstr "Abrir" + +#: objects/ui_launchingscreen.h:279 +msgid "Help" +msgstr "Ayuda" + +#: objects/ui_launchingscreen.h:280 +msgid "Recents" +msgstr "Recientes" + +#: objects/ui_launchingscreen.h:281 +msgid "Open Recent" +msgstr "Abrir recientes" + +#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 +#: objects/ui_MainWindow.h:855 +msgid "Examples" +msgstr "Ejemplos" + +#: objects/ui_launchingscreen.h:285 +msgid "Open Example" +msgstr "Abrir ejemplos" + +#: objects/ui_launchingscreen.h:287 +msgid "" +"\n" +"

    OpenSCAD

    \n" +"

    The Programmers Solid 3D CAD Modeller

    \n" +"\n" +"\n" +"\n" +msgstr "" +"\n" +"

    OpenSCAD

    \n" +"

    Le modeleur CAD 3D des programmeurs

    \n" +"\n" +"\n" +"\n" + +#: objects/ui_launchingscreen.h:294 +msgid "Don't show again" +msgstr "No mostrar de nuevo" + +#: objects/ui_LibraryInfoDialog.h:75 +msgid "Lib & Build Info" +msgstr "Informacion de las librerias y compilación" + +#: objects/ui_LibraryInfoDialog.h:76 +msgid "OpenSCAD Detailed Library and Build Information" +msgstr "Informations detalles de las librerias y compilación" + +#: objects/ui_MainWindow.h:731 +msgid "&New" +msgstr "&Nuevos" + +#: objects/ui_MainWindow.h:732 +msgid "Ctrl+N" +msgstr "Ctrl+N" + +#: objects/ui_MainWindow.h:733 +msgid "&Open..." +msgstr "&Abrir..." + +#: objects/ui_MainWindow.h:734 +msgid "Ctrl+O" +msgstr "Ctrl+O" + +#: objects/ui_MainWindow.h:735 +msgid "&Save" +msgstr "&Salvar" + +#: objects/ui_MainWindow.h:736 +msgid "Ctrl+S" +msgstr "Ctrl+S" + +#: objects/ui_MainWindow.h:737 +msgid "Save &As..." +msgstr "S&alvar como..." + +#: objects/ui_MainWindow.h:738 +msgid "Ctrl+Shift+S" +msgstr "Ctrl+Shift+S" + +#: objects/ui_MainWindow.h:739 +msgid "&Reload" +msgstr "&Recargar" + +#: objects/ui_MainWindow.h:740 +msgid "Ctrl+R" +msgstr "Ctrl+R" + +#: objects/ui_MainWindow.h:741 +msgid "&Quit" +msgstr "Salir" + +#: objects/ui_MainWindow.h:742 +msgid "Ctrl+Q" +msgstr "Ctrl+Q" + +#: objects/ui_MainWindow.h:743 +msgid "&Undo" +msgstr "An&ular" + +#: objects/ui_MainWindow.h:744 +msgid "Ctrl+Z" +msgstr "Ctrl+Z" + +#: objects/ui_MainWindow.h:745 +msgid "&Redo" +msgstr "&Repetir" + +#: objects/ui_MainWindow.h:746 +msgid "Ctrl+Shift+Z" +msgstr "Ctrl+Shift+Z" + +#: objects/ui_MainWindow.h:747 +msgid "Cu&t" +msgstr "Co&rtar" + +#: objects/ui_MainWindow.h:748 +msgid "Ctrl+X" +msgstr "Ctrl+X" + +#: objects/ui_MainWindow.h:749 +msgid "&Copy" +msgstr "&Copiar" + +#: objects/ui_MainWindow.h:750 +msgid "Ctrl+C" +msgstr "Ctrl+C" + +#: objects/ui_MainWindow.h:751 +msgid "&Paste" +msgstr "&Pegar" + +#: objects/ui_MainWindow.h:752 +msgid "Ctrl+V" +msgstr "Ctrl+V" + +# no se que es +#: objects/ui_MainWindow.h:753 +msgid "&Indent" +msgstr "&Indenter" + +#: objects/ui_MainWindow.h:754 +msgid "Ctrl+I" +msgstr "Ctrl+I" + +#: objects/ui_MainWindow.h:755 +msgid "U&nindent" +msgstr "Dési&ndenter" + +#: objects/ui_MainWindow.h:756 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:757 +msgid "C&omment" +msgstr "C&omentar" + +#: objects/ui_MainWindow.h:758 +msgid "Ctrl+D" +msgstr "Ctrl+D" + +#: objects/ui_MainWindow.h:759 +msgid "Unco&mment" +msgstr "Desco&mentar" + +#: objects/ui_MainWindow.h:760 +msgid "Ctrl+Shift+D" +msgstr "Ctrl+Shift+D" + +#: objects/ui_MainWindow.h:761 +msgid "Paste viewport translation" +msgstr "Pegar posición de la marco" + +#: objects/ui_MainWindow.h:762 +msgid "Ctrl+T" +msgstr "Ctrl+T" + +#: objects/ui_MainWindow.h:763 +msgid "Paste viewport rotation" +msgstr "Pegar rotación de la ventana" + +#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 +msgid "Zoom In" +msgstr "Acercar" + +#: objects/ui_MainWindow.h:765 +msgid "Ctrl++" +msgstr "Ctrl++" + +#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 +msgid "Zoom Out" +msgstr "Alejar" + +#: objects/ui_MainWindow.h:767 +msgid "Ctrl+-" +msgstr "Ctrl+-" + +#: objects/ui_MainWindow.h:768 +msgid "Hide editor" +msgstr "Ocultar editor" + +#: objects/ui_MainWindow.h:769 +msgid "&Reload and Preview" +msgstr "&Recargar y previsualizar" + +#: objects/ui_MainWindow.h:770 +msgid "F4" +msgstr "F4" + +#: objects/ui_MainWindow.h:771 +msgid "&Preview" +msgstr "&Previsualizar" + +#: objects/ui_MainWindow.h:772 +msgid "F5" +msgstr "F5" + +#: objects/ui_MainWindow.h:773 +msgid "&Render" +msgstr "&Renderizar" + +#: objects/ui_MainWindow.h:774 +msgid "F6" +msgstr "F6" + +#: objects/ui_MainWindow.h:775 +msgid "Check Validity" +msgstr "Chequear validez" + +#: objects/ui_MainWindow.h:776 +msgid "Display &AST..." +msgstr "Mostrar &AST..." + +#: objects/ui_MainWindow.h:777 +msgid "Display CSG &Tree..." +msgstr "Mostrar CSG &Arbre" + +#: objects/ui_MainWindow.h:778 +msgid "Display CSG &Products..." +msgstr "Mostar CSG &Produits" + +#: objects/ui_MainWindow.h:779 +msgid "Export as &STL..." +msgstr "Exportar como &STL..." + +#: objects/ui_MainWindow.h:780 +msgid "Export as &OFF..." +msgstr "Exportar como &OFF..." + +#: objects/ui_MainWindow.h:781 +msgid "Preview" +msgstr "Previsualizar" + +#: objects/ui_MainWindow.h:782 +msgid "F9" +msgstr "F9" + +#: objects/ui_MainWindow.h:783 +msgid "Surfaces" +msgstr "Superficie" + +#: objects/ui_MainWindow.h:784 +msgid "F10" +msgstr "F10" + +#: objects/ui_MainWindow.h:785 +msgid "Wireframe" +msgstr "Estructura" + +#: objects/ui_MainWindow.h:786 +msgid "F11" +msgstr "F11" + +#: objects/ui_MainWindow.h:787 +msgid "Thrown Together" +msgstr "Lanzar Juntos" + +#: objects/ui_MainWindow.h:788 +msgid "F12" +msgstr "F12" + +#: objects/ui_MainWindow.h:789 +msgid "Show Edges" +msgstr "Mostrar puntos" + +#: objects/ui_MainWindow.h:790 +msgid "Ctrl+1" +msgstr "Ctrl+1" + +#: objects/ui_MainWindow.h:791 +msgid "Show Axes" +msgstr "Mostrar ejes" + +#: objects/ui_MainWindow.h:792 +msgid "Ctrl+2" +msgstr "Ctrl+2" + +#: objects/ui_MainWindow.h:793 +msgid "Show Crosshairs" +msgstr "Mostrar punto de mira" + +#: objects/ui_MainWindow.h:794 +msgid "Ctrl+3" +msgstr "Ctrl+3" + +#: objects/ui_MainWindow.h:795 +msgid "Animate" +msgstr "Animar" + +#: objects/ui_MainWindow.h:796 +msgid "Top" +msgstr "Arriba" + +#: objects/ui_MainWindow.h:797 +msgid "Ctrl+4" +msgstr "Ctrl+4" + +#: objects/ui_MainWindow.h:798 +msgid "Bottom" +msgstr "Abajo" + +#: objects/ui_MainWindow.h:799 +msgid "Ctrl+5" +msgstr "Ctrl+5" + +#: objects/ui_MainWindow.h:800 +msgid "Left" +msgstr "Izquierda" + +#: objects/ui_MainWindow.h:801 +msgid "Ctrl+6" +msgstr "Ctrl+6" + +#: objects/ui_MainWindow.h:802 +msgid "Right" +msgstr "Derecha" + +#: objects/ui_MainWindow.h:803 +msgid "Ctrl+7" +msgstr "Ctrl+7" + +#: objects/ui_MainWindow.h:804 +msgid "Front" +msgstr "Frente" + +#: objects/ui_MainWindow.h:805 +msgid "Ctrl+8" +msgstr "Ctrl+8" + +#: objects/ui_MainWindow.h:806 +msgid "Back" +msgstr "Atrás" + +#: objects/ui_MainWindow.h:807 +msgid "Ctrl+9" +msgstr "Ctrl+9" + +#: objects/ui_MainWindow.h:808 +msgid "Diagonal" +msgstr "Diagonal" + +#: objects/ui_MainWindow.h:809 +msgid "Ctrl+0" +msgstr "Ctrl+0" + +#: objects/ui_MainWindow.h:810 +msgid "Center" +msgstr "Centro" + +#: objects/ui_MainWindow.h:811 +msgid "Perspective" +msgstr "Perspectiva" + +#: objects/ui_MainWindow.h:812 +msgid "Orthogonal" +msgstr "Orthogonal" + +#: objects/ui_MainWindow.h:813 +msgid "Hide console" +msgstr "Ocultar consola" + +#: objects/ui_MainWindow.h:814 +msgid "About" +msgstr "Acerca de" + +#: objects/ui_MainWindow.h:815 +msgid "Documentation" +msgstr "Documentación" + +#: objects/ui_MainWindow.h:816 +msgid "Clear Recent" +msgstr "Borrar recientes" + +#: objects/ui_MainWindow.h:817 +msgid "Export as DXF..." +msgstr "Exportar a DXF..." + +#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Cerrar" + +#: objects/ui_MainWindow.h:819 +msgid "Ctrl+W" +msgstr "Ctrl+W" + +#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +msgid "Preferences" +msgstr "Preferencias" + +#: objects/ui_MainWindow.h:821 +msgid "Find..." +msgstr "Buscar..." + +#: objects/ui_MainWindow.h:822 +msgid "Ctrl+F" +msgstr "Ctrl+F" + +#: objects/ui_MainWindow.h:823 +msgid "Find and Replace..." +msgstr "Buscar y reemplazar..." + +#: objects/ui_MainWindow.h:824 +msgid "Ctrl+Alt+F" +msgstr "Ctrl+Alt+F" + +#: objects/ui_MainWindow.h:825 +msgid "Find Next" +msgstr "Buscar próximo" + +#: objects/ui_MainWindow.h:826 +msgid "Ctrl+G" +msgstr "Ctrl+G" + +#: objects/ui_MainWindow.h:827 +msgid "Find Previous" +msgstr "Buscar previo" + +#: objects/ui_MainWindow.h:828 +msgid "Ctrl+Shift+G" +msgstr "Ctrl+Shift+G" + +#: objects/ui_MainWindow.h:829 +msgid "Use Selection for Find" +msgstr "Buscar selección" + +#: objects/ui_MainWindow.h:830 +msgid "Ctrl+E" +msgstr "Ctrl+E" + +#: objects/ui_MainWindow.h:831 +msgid "Flush Caches" +msgstr "Borrar cache" + +#: objects/ui_MainWindow.h:832 +msgid "OpenSCAD Homepage" +msgstr "Pagina de OpenSCAD" + +#: objects/ui_MainWindow.h:833 +msgid "Automatic Reload and Preview" +msgstr "Recargar y previsualizar automáticamente" + +#: objects/ui_MainWindow.h:834 +msgid "Export as Image..." +msgstr "Exportar imagen..." + +#: objects/ui_MainWindow.h:835 +msgid "Export as CSG..." +msgstr "Exportar en CSG..." + +#: objects/ui_MainWindow.h:836 +msgid "Library info" +msgstr "Información de librerías" + +#: objects/ui_MainWindow.h:837 +msgid "Show Library Folder..." +msgstr "Mostrar carpeta de librerías" + +#: objects/ui_MainWindow.h:838 +msgid "Reset View" +msgstr "Reiniciar vista" + +#: objects/ui_MainWindow.h:839 +msgid "Font List" +msgstr "Lista de fuentes" + +#: objects/ui_MainWindow.h:840 +msgid "Export as SVG..." +msgstr "Exportar en SVG..." + +#: objects/ui_MainWindow.h:841 +msgid "Export as AMF..." +msgstr "Exportar en AMF..." + +#: objects/ui_MainWindow.h:843 +msgid "Ctrl+]" +msgstr "Ctrl+]" + +#: objects/ui_MainWindow.h:845 +msgid "Ctrl+[" +msgstr "Ctrl+[" + +#: objects/ui_MainWindow.h:846 +msgid "View All" +msgstr "Ver todo" + +#: objects/ui_MainWindow.h:847 +msgid "Convert Tabs to Spaces" +msgstr "Convertir tabulado en espacios" + +#: objects/ui_MainWindow.h:848 +msgid "Hide toolbars" +msgstr "Ocultar barra de herramientas" + +#: objects/ui_MainWindow.h:849 +msgid "Time:" +msgstr "Tiempo:" + +#: objects/ui_MainWindow.h:850 +msgid "FPS:" +msgstr "FPS:" + +#: objects/ui_MainWindow.h:851 +msgid "Steps:" +msgstr "Pasos:" + +#: objects/ui_MainWindow.h:852 +msgid "Dump Pictures" +msgstr "Grabar imágenes" + +#: objects/ui_MainWindow.h:853 +msgid "&File" +msgstr "&Archivo" + +#: objects/ui_MainWindow.h:854 +msgid "Recent Files" +msgstr "Archivos recientes" + +#: objects/ui_MainWindow.h:856 +msgid "Export" +msgstr "Exportar" + +#: objects/ui_MainWindow.h:857 +msgid "&Edit" +msgstr "&Editar" + +#: objects/ui_MainWindow.h:858 +msgid "&Design" +msgstr "&Diseñar" + +#: objects/ui_MainWindow.h:859 +msgid "&View" +msgstr "&Ver" + +#: objects/ui_MainWindow.h:860 +msgid "&Help" +msgstr "&Ayuda" + +#: objects/ui_MainWindow.h:863 +msgid "Find" +msgstr "Buscar" + +#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +msgid "Replace" +msgstr "Reemplazar" + +#: objects/ui_MainWindow.h:866 +msgid "Search string" +msgstr "Buscar palabra" + +#: objects/ui_MainWindow.h:867 +msgid "<" +msgstr "<" + +#: objects/ui_MainWindow.h:868 +msgid ">" +msgstr ">" + +#: objects/ui_MainWindow.h:869 +msgid "Done" +msgstr "Terminar" + +#: objects/ui_MainWindow.h:870 +msgid "Replacement string" +msgstr "Remplazar palabra" + +#: objects/ui_MainWindow.h:872 +msgid "All" +msgstr "Todo" + +#: objects/ui_OpenCSGWarningDialog.h:86 +msgid "OpenGL Warning" +msgstr "Advertencia OpenGL" + +#: objects/ui_OpenCSGWarningDialog.h:87 +msgid "" +"\n" +"\n" +"

    " +msgstr "" +"\n" +"\n" +"

    " + +#: objects/ui_OpenCSGWarningDialog.h:92 +msgid "Enable OpenCSG" +msgstr "Activar OpenCSG" + +#: objects/ui_OpenCSGWarningDialog.h:93 +msgid "Show this message again" +msgstr "Mostrar el mensaje de nuevo" + +#: objects/ui_Preferences.h:609 +msgid "3D View" +msgstr "Vista 3D" + +#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +msgid "Advanced" +msgstr "Advertencia" + +#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +msgid "Editor" +msgstr "Editar" + +#: objects/ui_Preferences.h:612 +msgid "Update" +msgstr "Actualizar" + +#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +msgid "Features" +msgstr "Mejoras" + +#: objects/ui_Preferences.h:615 +msgid "Enable/Disable experimental features" +msgstr "Activar/desactivar mejoras experimentales" + +#: objects/ui_Preferences.h:617 +msgid "Color scheme:" +msgstr "Paleta de colores:" + +#: objects/ui_Preferences.h:618 +msgid "Editor Type" +msgstr "Editor de texto" + +#: objects/ui_Preferences.h:621 +msgid "Simple Editor" +msgstr "Editor simple" + +#: objects/ui_Preferences.h:622 +msgid "QScintilla Editor" +msgstr "Editor QScintilla" + +#: objects/ui_Preferences.h:624 +msgid "(requires restart)" +msgstr "(necesita reiniciar)" + +#: objects/ui_Preferences.h:625 +msgid "Font" +msgstr "Fuente" + +#: objects/ui_Preferences.h:626 +msgid "Color syntax highlighting" +msgstr "Colorear sintaxis" + +#: objects/ui_Preferences.h:627 +msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +msgstr "Use ctrl/cmd + rueda del mouse para hacer zoom al texto" + +#: objects/ui_Preferences.h:629 +msgid "Automatically check for updates" +msgstr "Comprobar actualización automáticamente" + +#: objects/ui_Preferences.h:630 +msgid "Include development snapshots" +msgstr "Incluir las versiones en desarrollo" + +#: objects/ui_Preferences.h:631 +msgid "Check Now" +msgstr "Chequear ahora" + +#: objects/ui_Preferences.h:632 +msgid "Last checked: " +msgstr "Último chequeo:" + +#: objects/ui_Preferences.h:634 +msgid "OpenCSG" +msgstr "OpenCSG" + +#: objects/ui_Preferences.h:635 +msgid "Show capability warning" +msgstr "Advertir incapacidad" + +#: objects/ui_Preferences.h:636 +msgid "Enable for OpenGL 1.x" +msgstr "Activar OpenGL 1.x" + +#: objects/ui_Preferences.h:637 +msgid "Turn off rendering at " +msgstr "Desactivar el render de" + +#: objects/ui_Preferences.h:638 +msgid "elements" +msgstr "elementos" + +#: objects/ui_Preferences.h:639 +msgid "Force Goldfeather" +msgstr "Forzar Goldfeather" + +#: objects/ui_Preferences.h:640 +msgid "CGAL Cache size" +msgstr "Tamaño de cache de CGAL" + +#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +msgid "bytes" +msgstr "bytes" + +#: objects/ui_Preferences.h:642 +msgid "PolySet Cache size" +msgstr "Tamaño de cache de PolySet" + +#: objects/ui_Preferences.h:644 +msgid "Allow to open multiple documents" +msgstr "Permitir a abrir varios documentos" + +#: objects/ui_Preferences.h:645 +msgid "Enable docking of Editor and Console in different places" +msgstr "Habilitar soporte de editor y consola en diferentes lugares" + +#: objects/ui_Preferences.h:646 +msgid "Enable undocking of Editor and Console to separate windows" +msgstr "" +"Habilitar el desacoplamiento de editor y consola para separar las ventanas" + +#: objects/ui_Preferences.h:647 +msgid "Show Welcome Screen" +msgstr "Pantalla de bienvenida" + +#: objects/ui_Preferences.h:648 +msgid "Enable user interface localization (requires restart of OpenSCAD)" +msgstr "" +"Habilitar interfaz de usuario localización (requiere reiniciar OpenSCAD)" + +#: objects/ui_Preferences.h:649 +msgid "toolBar" +msgstr "barra de herramientas" + +#: objects/ui_ProgressWidget.h:72 +msgid "Form" +msgstr "Formulario" + +#: objects/ui_ProgressWidget.h:73 +msgid "%v / %m" +msgstr "%v / %m" + +#: src/mainwin.cc:768 src/mainwin.cc:1300 +msgid "Untitled.scad" +msgstr "Sintitulo.scad" + +#: src/mainwin.cc:1299 +msgid "Save File" +msgstr "Salver archivo" + +#: src/mainwin.cc:1301 +msgid "OpenSCAD Designs (*.scad)" +msgstr "Diseño OpenSCAD (*.scad)" + +#: src/mainwin.cc:1311 +msgid "" +"%1 already exists.\n" +"Do you want to replace it?" +msgstr "" +"%1 existe.\n" +"Deseas reemplazarlo?" + +#: src/mainwin.cc:1630 +msgid "Application" +msgstr "Aplicación" + +#: src/mainwin.cc:1631 +msgid "" +"The document has been modified.\n" +"Do you really want to reload the file?" +msgstr "" +"El documento ha sido modificado.\n" +"¿Realmente desea volver a cargar el archivo ?" + +#: src/mainwin.cc:1942 src/mainwin.cc:1999 +msgid "Export %1 File" +msgstr "Exportar %1 Archivo" + +#: src/mainwin.cc:1943 src/mainwin.cc:2003 +msgid "%1 Files (*%2)" +msgstr "%1 Archivo (*%2)" + +#: src/mainwin.cc:1944 +msgid "Untitled" +msgstr "Sin titulo" + +#: src/mainwin.cc:2001 +msgid "Untitled%1" +msgstr "Sintitulo%1" + +#: src/mainwin.cc:2052 +msgid "Export CSG File" +msgstr "Exportar archivo CSG" + +#: src/mainwin.cc:2053 +msgid "Untitled.csg" +msgstr "Sintitulo.csg" + +#: src/mainwin.cc:2054 +msgid "CSG Files (*.csg)" +msgstr "Archivo CSG (*.csg)" + +#: src/mainwin.cc:2080 +msgid "Export Image" +msgstr "Exportar una imagen" + +#: src/mainwin.cc:2080 +msgid "PNG Files (*.png)" +msgstr "Archivo PNG (*.png)" + +#: src/mainwin.cc:2320 +msgid "Console" +msgstr "Consola" + +#: src/mainwin.cc:2447 +msgid "The document has been modified." +msgstr "El documento ha sido modificado." + +#: src/mainwin.cc:2448 +msgid "Do you want to save your changes?" +msgstr "¿Quieres guardar los cambios ?" + +#: src/QGLView.cc:114 +msgid "" +"\n" +"Using QGLWidget\n" +"\n" +msgstr "" +"\n" +"Utilizar QGLWidget\n" +"\n" + +#: src/QGLView.cc:131 +msgid "" +"Warning: You may experience OpenCSG rendering errors.\n" +"\n" +msgstr "" +"Advertencia: Usted puede experimentar OpenCSG errores de renderizado.\n" +"\n" + +#: src/QGLView.cc:134 +msgid "" +"Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " +"disabled.\n" +"\n" +msgstr "" +"Advertencia: Manquantes capacités OpenGL vierten OpenCSG - OpenCSG ha sido " +"desactivada. .\n" +"\n" + +#: src/QGLView.cc:137 +msgid "" +"It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " +"later.\n" +"Your renderer information is as follows:\n" +msgstr "" +"Es muy recomendable utilizar OpenSCAD en un sistema con OpenGL 2.0 o " +"posterior.\n" +"Su información renderer es como sigue:\n" + +#: src/QGLView.cc:141 +#, c-format +msgid "" +"GLEW version %s\n" +"%s (%s)\n" +"OpenGL version %s\n" +msgstr "" +"Versión GLEW %s\n" +"%s (%s)\n" +"Versión OpenGL %s\n" + +#: src/QGLView.cc:171 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Marco: posición = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], " +"distancia = %.2f" + +#: src/UIUtils.cc:85 +msgid "Basics" +msgstr "Básico" + +#: src/UIUtils.cc:85 +msgid "Shapes" +msgstr "Formas" + +#: src/UIUtils.cc:85 +msgid "Extrusion" +msgstr "Extrusión" + +#~ msgid "Paste font selector to Editor Window" +#~ msgstr "Coller le sélecteur de polices dans l'éditeur de fenêtres" + +#~ msgid "About OpenSCAD " +#~ msgstr "À propos de OpenSCAD" + +#~ msgid "Check for Update.." +#~ msgstr "Vérifier les mises à jours" + +#~ msgid "OpenGL Info" +#~ msgstr "Information OpenGL" From 7f7369e0643be2e38f24021e67e319ac892e91d0 Mon Sep 17 00:00:00 2001 From: b4zz4 Date: Wed, 21 Jan 2015 22:33:07 -0300 Subject: [PATCH 116/174] add spanish --- locale/LINGUAS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/LINGUAS b/locale/LINGUAS index 9f82de46..ed46eb16 100644 --- a/locale/LINGUAS +++ b/locale/LINGUAS @@ -1,2 +1,2 @@ # available languages -fr ru de cs +fr ru de cs es From ce2e3ec9652e933d2917f1dd4f930b29fc43fa3b Mon Sep 17 00:00:00 2001 From: b4zz4 Date: Wed, 21 Jan 2015 22:36:55 -0300 Subject: [PATCH 117/174] detalles faltantes --- locale/es.po | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/locale/es.po b/locale/es.po index 2cd1b89c..2dc70bfd 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-12-22 23:28+0100\n" -"PO-Revision-Date: 2015-01-21 22:23-0300\n" +"PO-Revision-Date: 2015-01-21 22:36-0300\n" "Last-Translator: Ernesto Bazzano \n" "Language-Team: Español\n" "Language: es\n" @@ -51,13 +51,13 @@ msgid "" "family:'Courier New,courier';\"> text(t = "OpenSCAD", font = " ""Liberation Sans:style=Italic");" msgstr "" -"

    Cette liste affiche les polices présentement chargées " -"avec OpenSCAD

    Example:

      text(t = "
    -""OpenSCAD", font = "DejaVu Sans");

    Esta lista muestra los tipos de letra registrados " +"actualmente en OpenSCAD

    Ejemplo:

      "
    +"text(t = "OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
     ""Liberation Sans:style=Italic");
    " @@ -729,7 +729,7 @@ msgstr "Mejoras" #: objects/ui_Preferences.h:615 msgid "Enable/Disable experimental features" -msgstr "Activar/desactivar mejoras experimentales" +msgstr "Activar/Desactivar mejoras experimentales" #: objects/ui_Preferences.h:617 msgid "Color scheme:" From c80bb8a6243996b55cfa401f43db0871cf23b2f1 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 22 Jan 2015 16:18:07 -0500 Subject: [PATCH 118/174] Bumped freetype to 2.5.5 --- scripts/macosx-build-dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index 109b95a5..d4f7e99e 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -787,7 +787,7 @@ build_gettext 0.19.4 build_libffi 3.2.1 build_glib2 2.42.1 build_opencsg 1.4.0 -build_freetype 2.5.4 --without-png +build_freetype 2.5.5 --without-png build_ragel 6.9 build_harfbuzz 0.9.37 "--with-coretext=auto --with-glib=no" export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" From 60ae33f796c7ff5eb0b88fa89548be56b2ef1f80 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 22 Jan 2015 19:12:32 -0500 Subject: [PATCH 119/174] ignores.. --- .gitignore | 22 +++++++++++++++++----- cgal/.gitignore | 8 ++++++++ tests/.gitignore | 7 +++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 cgal/.gitignore diff --git a/.gitignore b/.gitignore index 09dd7b69..5bfa3546 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,13 @@ *.dmg *~ *.tar* +*.new Makefile objects .gdbinit .qmake.stash parser_yacc.h -*/#*# +**/#*# testdata/scad/features/import_dxf-tests.scad testdata/scad/features/import_stl-tests.scad testdata/scad/misc/include-tests.scad @@ -20,6 +21,18 @@ testdata/scad/misc/use-tests.scad /*.amf /*.png /*.csg +/*.nef3 +/*.blend +/*.obj +/*.rcad +/*.xml +/*.dat +/*.gcode +/*.py +/*.svg +/*.h +/*.dump +/*.pl /lexer_lex.cpp /parser_yacc.cpp /OpenSCAD.app @@ -27,11 +40,10 @@ testdata/scad/misc/use-tests.scad /openscad /locale/*/*/*.mo /locale/POTFILES -/tests/openscad_nogui -/tests/diffpng -/tests/test_pretty_print.log.txt -/tests/*.png /tmp /nbproject /mingw32 /mingw64 +src/*.org +src/*.old +src/*.debug \ No newline at end of file diff --git a/cgal/.gitignore b/cgal/.gitignore new file mode 100644 index 00000000..188301ef --- /dev/null +++ b/cgal/.gitignore @@ -0,0 +1,8 @@ +/*.stl +/*.scad +/*.polygon +polyhole-tessellator +polyhole-tessellator-libtess2 +minkowski +decompose +export_nef \ No newline at end of file diff --git a/tests/.gitignore b/tests/.gitignore index 99ad0be3..2171c5e8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -2,6 +2,7 @@ /*.a /*-output /*.scad +/*.png out.* /CMakeFiles /CMakeCache.txt @@ -18,3 +19,9 @@ out.* /sysinfo.txt /CTestCustom.cmake /openscad_nogui +/openscad_nogui +/diffpng +/test_pretty_print.log.txt +/csgtermtest +/echotest +/dumptest \ No newline at end of file From 25da58afb324f0c2c0a223cff997ff12203551d5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 23 Jan 2015 01:31:17 -0500 Subject: [PATCH 120/174] Updated with new cmd-line switches --- doc/openscad.1 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/doc/openscad.1 b/doc/openscad.1 index d8853eac..26c38be0 100644 --- a/doc/openscad.1 +++ b/doc/openscad.1 @@ -1,4 +1,4 @@ -.TH OPENSCAD 1 "2014.03" +.TH OPENSCAD 1 "2015.02" .\" Please adjust this date whenever revising the manpage. .SH NAME openscad \- script file based graphical CAD environment @@ -19,7 +19,7 @@ the OpenSCAD user manual at http://en.wikibooks.org/wiki/OpenSCAD_User_Manual. .TP \fB-o\fP \fIoutputfile\fP -Export the given file to \fIoutputfile\fP in STL, OFF, DXF, or PNG +Export the given file to \fIoutputfile\fP in STL, OFF, AMF, DXF, SVG, or PNG format, depending on file extension of \fIoutputfile\fP. If this option is given, the GUI will not be started. @@ -49,10 +49,10 @@ strings, care has to be taken that the shell does not consume quotation marks. More than one \fB-D\fP option can be given. .TP .B \-\-render -If exporting an image, use a full CGAL render. (Default is an OpenCSG compile) +If exporting an image, render the model fully. (Default is preview) .TP .B \-\-preview[=throwntogether] -If exporting an image, use an OpenCSG previce (optionally in throwntogether mode for quicker rendering). +If exporting an image, use an OpenCSG preview (optionally in throwntogether mode for quicker rendering). .TP .B \-\-csglimit=limit If exporting an image as an OpenCSG preview, stop rendering after encountering \fIlimit\fP elements to avoid runaway resource usage. @@ -69,6 +69,12 @@ The first three are for the Eye position, while the next three are for the Center (or target) that the camera will look at. The 'up' vector is not currently supported. .TP +.B \-\-viewall +If exporting an image, adjust camera distance to fit the whole design in the frame +.TP +.B \-\-autocenter +If exporting an image, center the design in the frame +.TP .B \-\-imgsize=width,height If exporting an image, specify the pixel width and height .TP @@ -76,6 +82,9 @@ If exporting an image, specify the pixel width and height If exporting an image, specify whether to use orthographic or perspective projection .TP +.B \-\-colorscheme=[Cornfield|Sunset|Metallic|Starnight|BeforeDawn|Nature|DeepOcean] +If exporting an image, use the specified color scheme for the rendering. +.TP .B \-v, \-\-version Show version of program. .TP From 5a0c4b0ba87da0b3f672281eaedf1d3843ca516c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 23 Jan 2015 01:31:41 -0500 Subject: [PATCH 121/174] Updated copyright year --- releases/{2014.QX.md => 2015.02.md} | 0 src/AboutDialog.html | 2 +- src/mainwin.cc | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename releases/{2014.QX.md => 2015.02.md} (100%) diff --git a/releases/2014.QX.md b/releases/2015.02.md similarity index 100% rename from releases/2014.QX.md rename to releases/2015.02.md diff --git a/src/AboutDialog.html b/src/AboutDialog.html index b2c2cc44..478c5e20 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -23,7 +23,7 @@

    -Copyright (C) 2009-2014 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at> +Copyright (C) 2009-2015 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at>

    diff --git a/src/mainwin.cc b/src/mainwin.cc index 6aaa4840..9c1965b1 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -128,7 +128,7 @@ QSet *MainWindow::getWindows() unsigned int GuiLocker::gui_locked = 0; static char copyrighttext[] = - "Copyright (C) 2009-2014 The OpenSCAD Developers\n" + "Copyright (C) 2009-2015 The OpenSCAD Developers\n" "\n" "This program is free software; you can redistribute it and/or modify " "it under the terms of the GNU General Public License as published by " From 181ee4823a9c16402c758a5295adbc30d6b6a2ec Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sat, 24 Jan 2015 20:51:40 +0100 Subject: [PATCH 122/174] Update translations. --- locale/cs.po | 704 +++++++++++++++++++++++++-------------- locale/de.po | 726 +++++++++++++++++++++++++--------------- locale/es.po | 784 ++++++++++++++++++++++++++++---------------- locale/fr.po | 780 +++++++++++++++++++++++++++---------------- locale/openscad.pot | 569 ++++++++++++++++---------------- locale/ru.po | 774 +++++++++++++++++++++++++++---------------- 6 files changed, 2688 insertions(+), 1649 deletions(-) diff --git a/locale/cs.po b/locale/cs.po index d9a8ed71..030853e4 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.24\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2014-12-23 12:24+0100\n" "Last-Translator: Miro HronÄok \n" "Language-Team: Czech \n" @@ -19,27 +19,46 @@ msgstr "" "Plural-Forms: nplurals=3; plural=n==1 ? 0 : n>=2 && n<=4 ? 1 : 2;\n" "X-Poedit-SourceCharset: UTF-8\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "O OpenSCADu" -#: objects/ui_FontListDialog.h:102 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 +msgid "" +"\n" +"

    OpenSCAD

    \n" +"

    The Programmers Solid 3D CAD Modeller

    \n" +"\n" +"\n" +"\n" +msgstr "" + +#: objects/ui_AboutDialog.h:112 +#, fuzzy +msgid "OK" +msgstr "&OK" + +#: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" msgstr "Seznam OpenSCAD písem" -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 +#: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 msgid "&OK" msgstr "&OK" -#: objects/ui_FontListDialog.h:104 +#: objects/ui_FontListDialog.h:107 msgid "Copy to Clipboard" msgstr "Kopírovat do schránky" -#: objects/ui_FontListDialog.h:105 +#: objects/ui_FontListDialog.h:108 msgid "Filter:" msgstr "Filtr:" -#: objects/ui_FontListDialog.h:106 +#: objects/ui_FontListDialog.h:109 msgid "" "

    This list shows the fonts currently registered with " "OpenSCAD.

    Example:

      text(t = "OpenSCAD", font = "
     ""Liberation Sans:style=Italic");
    " -#: objects/ui_launchingscreen.h:276 +#: objects/ui_launchingscreen.h:294 msgid "Welcome to OpenSCAD" msgstr "Vítá vás OpenSCAD" -#: objects/ui_launchingscreen.h:277 +#: objects/ui_launchingscreen.h:295 msgid "New" msgstr "Nový" -#: objects/ui_launchingscreen.h:278 +#: objects/ui_launchingscreen.h:296 msgid "Open" msgstr "Otevřít" -#: objects/ui_launchingscreen.h:279 +#: objects/ui_launchingscreen.h:297 msgid "Help" msgstr "Nápověda" -#: objects/ui_launchingscreen.h:280 +#: objects/ui_launchingscreen.h:298 msgid "Recents" msgstr "Nedávné" -#: objects/ui_launchingscreen.h:281 +#: objects/ui_launchingscreen.h:299 msgid "Open Recent" msgstr "Otevřít nedávný soubor" -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Příklady" -#: objects/ui_launchingscreen.h:285 +#: objects/ui_launchingscreen.h:303 msgid "Open Example" msgstr "Otevřít příklad" -#: objects/ui_launchingscreen.h:287 -msgid "" -"\n" -"

    OpenSCAD

    \n" -"

    The Programmers Solid 3D CAD Modeller

    \n" -"\n" -"\n" -"\n" -msgstr "" - -#: objects/ui_launchingscreen.h:294 +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "PříštÄ› nezobrazovat" +#: objects/ui_launchingscreen.h:313 +#, fuzzy +msgid "Version" +msgstr "Vytažení" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Info o knihovnách a sestavení" @@ -120,543 +130,563 @@ msgstr "Info o knihovnách a sestavení" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Podrobné informace o tomto sestavení OpenSCADu a použitých knihovnách" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "&Nový" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "&Otevřít..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "&Uložit" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "Uložit &jako..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "&Znovu naÄíst" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "U&konÄit" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "&ZpÄ›t" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "Zn&ovu" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "&Vyjmout" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "&Kopírovat" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "V&ložit" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "Odsad&it" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Z&ruÅ¡it odsazení" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "&Zakomentovat" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "&Odkomentovat" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "Vložit posun pohledu" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "Vložit rotaci pohledu" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "PÅ™iblížit" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" +msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Oddálit" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" +msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "Skrýt editor" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:874 msgid "&Reload and Preview" msgstr "Znovu &naÄíst a zobrazit" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "Vy&renderovat" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "Zkontrolovat správnost" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "Ukázat &ATS..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "Ukázat CSG s&trom..." -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "Ukázat CSG &produkty..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "Exportovat jako &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "Exportovat jako &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "Náhled" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:888 msgid "Surfaces" msgstr "Povrchy" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "Drátové zobrazení" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "VÅ¡e spoleÄnÄ›" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "Zobrazit hrany" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "Zobrazit osy" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "Zobrazit zaměřovaÄ" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:900 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "Animovat" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "Shora" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "Zespoda" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "Zleva" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "Zprava" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "ZepÅ™edu" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "Zezadu" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "DiagonálnÄ›" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "Vycentrovat" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "PerspektivnÄ›" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "OrtogonálnÄ›" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "Skrýt terminál" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "O aplikaci" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "Dokumentace" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "Zapomenout nedávné" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "Exportovat jako &DXF" -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "Zavřít" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "PÅ™edvolby" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "Najít..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "Najít a nahradit..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "Najít další" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "Najít pÅ™edchozí" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "Hledat vybraný Å™etÄ›zec" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "Vyprázdnit mezipaměť" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "Domovská stránka OpenSCADu" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:939 msgid "Automatic Reload and Preview" msgstr "Automaticky naÄítat a zobrazovat" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "Exportovat jako obrázek..." -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "Exportovat jako CSG..." -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "Informace o knihovnách" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "Adresář s knihovnami..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "Výchozí pohled" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:945 msgid "Font List" msgstr "Seznam písem" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:946 msgid "Export as SVG..." msgstr "Exportovat jako SVG..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:947 msgid "Export as AMF..." msgstr "Exportovat jako AMF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "PÅ™iblížit" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "Oddálit" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:952 msgid "View All" msgstr "Zobrazit vÅ¡e" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "PÅ™evést tabulátory na mezery" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "Skrýt nástrojové liÅ¡ty" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" +msgstr "Z&ruÅ¡it odsazení" + +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "ÄŒas:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "Kroky:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "Ukládat obrázky" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "&Soubor" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:966 msgid "Recent Files" msgstr "Nedávné soubory" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "Exportovat" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Upravit" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "&Design" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "&NápovÄ›da" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "Najít" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "Nahradit" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "Hledaný Å™etÄ›zec" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "Hotovo" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:982 msgid "Replacement string" msgstr "Nahradit za" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "VÅ¡e" @@ -686,135 +716,285 @@ msgstr "Povolit OpenCSG" msgid "Show this message again" msgstr "Zobrazit tuto zprávu znovu" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D zobrazení" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "PokroÄilé" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Editor" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Aktualizace" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Funkce" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Povolit/Zakázat experimentální funkce" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Barevné téma:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Varianta editoru" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Jednoduchý editor" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "Editor QScintilla" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(vyžaduje restart aplikace)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Písmo" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Barva zvýrazňování syntaxe" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +#, fuzzy +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Použít Ctrl/Cmd a koleÄko myÅ¡i k zmÄ›nÄ› velikosti písma" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Dokumentace" + +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "Odsad&it" + +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "Odsad&it" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Povrchy" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "Odsad&it" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Ukázat &ATS..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "Odsad&it" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Automaticky vyhledávat aktualizace" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "VÄetnÄ› nestabilních verzí" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Zkontrolovat nyní" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Poslední kontrola:" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Zobrazovat varování o vlastnostech" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Povolit pro OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Vypnout renderování pÅ™i" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "prvcích" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Vynutit zobrazení Goldfeather" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Velikost CGAL cache" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "bytů" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Velikost PolySet cache" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Povolit souÄasné otevÅ™ení více dokumentů" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Povolit zaparkování editoru a konzole na různá místa" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "Povolit plovoucí editor a konzoli" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Zobrazovat uvítací obrazovku" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Povolit lokalizaci rozhraní OpenSCADu (vyžaduje restart aplikace)" -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "" @@ -826,23 +1006,48 @@ msgstr "" msgid "%v / %m" msgstr "%v / %m" -#: src/AboutDialog.h:15 -msgid "About OpenSCAD " -msgstr "O OpenSCADu " +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Pohled: posun = [ %.2f %.2f %.2f ], rotace = [ %.2f %.2f %.2f ], vzdálenost " +"= %.2f" -#: src/mainwin.cc:773 src/mainwin.cc:1315 +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Bezejmenný.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +#, fuzzy +msgid "Compile error." +msgstr "Z&kompilovat" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Uložit soubor" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD designy(*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -850,11 +1055,11 @@ msgstr "" "%1 již existuje.\n" "Chcete jej nahradit?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Aplikace" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -862,55 +1067,61 @@ msgstr "" "Dokument byl pozmÄ›nÄ›n.\n" "Opravdu jej chcete znovu naÄíst?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "Exportovat %s soubor(ů)" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Soubor(ů) (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Bezejmenný" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Bezejmenný%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Exportovat CSG soubor" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "Bezejmenný.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "CSG soubory (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Exportovat obrázek" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "PNG Soubory (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Konzole" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Dokument byl pozmÄ›nÄ›n." -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Chcete uložit zmÄ›ny?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" @@ -920,7 +1131,7 @@ msgstr "" "Používám QGLWidget\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -928,7 +1139,7 @@ msgstr "" "Varování: Můžete zaznamenat chyby zobrazení pomocí OpenCSG.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -937,7 +1148,7 @@ msgstr "" "Varování: Chybí OpenGL funkce pro OpenCSG - OpenCSG bylo vypnuto.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -946,7 +1157,7 @@ msgstr "" "Vysoce doporuÄujeme používat OpenSCAD na systému s OpenGL 2.0 nebo novÄ›jší.\n" "Zde je informace o vaÅ¡em vykreslovacím systému:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -957,27 +1168,25 @@ msgstr "" "%s (%s)\n" "OpenGL verze %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -"Pohled: posun = [ %.2f %.2f %.2f ], rotace = [ %.2f %.2f %.2f ], vzdálenost " -"= %.2f" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Základy" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Tvary" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Vytažení" +#~ msgid "About OpenSCAD " +#~ msgstr "O OpenSCADu " + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Vložit výbÄ›r písma do zdrojového kódu" @@ -993,9 +1202,6 @@ msgstr "Vytažení" #~ msgid "Sunset" #~ msgstr "Západ slunce" -#~ msgid "&Compile" -#~ msgstr "Z&kompilovat" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Zkompilovat a vy&renderovat" diff --git a/locale/de.po b/locale/de.po index df48ce1c..552b211c 100644 --- a/locale/de.po +++ b/locale/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2014-12-22 23:12+0100\n" "Last-Translator: Torsten Paul \n" "Language-Team: German\n" @@ -18,27 +18,56 @@ msgstr "" "X-Generator: Poedit 1.6.10\n" "X-Poedit-SourceCharset: UTF-8\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "Ãœber OpenSCAD" -#: objects/ui_FontListDialog.h:102 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 +msgid "" +"\n" +"

    OpenSCAD

    \n" +"

    The Programmers Solid 3D CAD Modeller

    \n" +"\n" +"\n" +"\n" +msgstr "" +"\n" +"

    OpenSCAD

    \n" +"

    The Programmers Solid 3D CAD Modeller

    \n" +"\n" +"\n" +"\n" + +#: objects/ui_AboutDialog.h:112 +#, fuzzy +msgid "OK" +msgstr "OK" + +#: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" msgstr "OpenSCAD Fontliste" -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 +#: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 msgid "&OK" msgstr "OK" -#: objects/ui_FontListDialog.h:104 +#: objects/ui_FontListDialog.h:107 msgid "Copy to Clipboard" msgstr "Kopieren" -#: objects/ui_FontListDialog.h:105 +#: objects/ui_FontListDialog.h:108 msgid "Filter:" msgstr "Filter:" -#: objects/ui_FontListDialog.h:106 +#: objects/ui_FontListDialog.h:109 msgid "" "

    This list shows the fonts currently registered with " "OpenSCAD.

    Example:

      text(t = "OpenSCAD", font = "
     ""Liberation Sans:style=Italic");
    " -#: objects/ui_launchingscreen.h:276 +#: objects/ui_launchingscreen.h:294 msgid "Welcome to OpenSCAD" msgstr "Willkommen zu OpenSCAD" -#: objects/ui_launchingscreen.h:277 +#: objects/ui_launchingscreen.h:295 msgid "New" msgstr "Neu" -#: objects/ui_launchingscreen.h:278 +#: objects/ui_launchingscreen.h:296 msgid "Open" msgstr "Öffnen" -#: objects/ui_launchingscreen.h:279 +#: objects/ui_launchingscreen.h:297 msgid "Help" msgstr "Hilfe" -#: objects/ui_launchingscreen.h:280 +#: objects/ui_launchingscreen.h:298 msgid "Recents" msgstr "Zuletzt benutze Dateien" -#: objects/ui_launchingscreen.h:281 +#: objects/ui_launchingscreen.h:299 msgid "Open Recent" msgstr "Datei öffnen" -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Beispiele" -#: objects/ui_launchingscreen.h:285 +#: objects/ui_launchingscreen.h:303 msgid "Open Example" msgstr "Beispiel öffnen" -#: objects/ui_launchingscreen.h:287 -msgid "" -"\n" -"

    OpenSCAD

    \n" -"

    The Programmers Solid 3D CAD Modeller

    \n" -"\n" -"\n" -"\n" -msgstr "" -"\n" -"

    OpenSCAD

    \n" -"

    The Programmers Solid 3D CAD Modeller

    \n" -"\n" -"\n" -"\n" - -#: objects/ui_launchingscreen.h:294 +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "Dialog nicht wieder anzeigen" +#: objects/ui_launchingscreen.h:313 +#, fuzzy +msgid "Version" +msgstr "Extrusion" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Versionsinformationen" @@ -129,543 +139,564 @@ msgstr "Versionsinformationen" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Detailierte Informationen über diese OpenSCAD Version" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "&Neu" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "Ö&ffnen" -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "&Speichern" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "Speichern &Unter..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "Neu &laden" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "&Beenden" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "&Rückgängig" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "&Wiederholen" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "Ausschneiden" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "Kopieren" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "Einfügen" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "Einzug erhöhen" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Einzug vermindern" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "K&ommentieren" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "Kommentar entfernen" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "Aktuelle Verschiebung einfügen" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "Aktuelle Rotation einfügen" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Vergrößern" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" +msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Verkleinern" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" +msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "Editor verstecken" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:874 msgid "&Reload and Preview" msgstr "Neu laden und Vorschau" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "Vorschau" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "Rendern" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "Design überprüfen" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "&AST Baum anzeigen..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "CSG Baum anzeigen..." -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "CSG Gleichungen anzeigen..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "&STL exportieren..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "&OFF exportieren..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "Vorschau" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:888 msgid "Surfaces" msgstr "Flächen anzeigen" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "Gittermodell" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "Kombinierte Anzeige" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "Kanten anzeigen" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "Koordinatenachsen anzeigen" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "Rotationsmittelpunkt anzeigen" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:900 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "Animation" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "Oben" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "Unten" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "Links" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "Rechts" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "Vorn" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "Hinten" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "Diagonal" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "Zentriert" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "Perspektivisch" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "Orthogonal" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "Konsole verstecken" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "Über OpenSCAD" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "Dokumentation" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "Zuletzt benutze Dateien löschen" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "DXF exportieren..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "Schließen" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "Einstellungen" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "Suchen..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "Suchen und Ersetzen..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "Weiter suchen" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "Rückwärts suchen" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "Auswahl suchen" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "Cache leeren" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "OpenSCAD Homepage" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:939 msgid "Automatic Reload and Preview" msgstr "Automatisch neu Laden und Vorschau" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "Image exportieren..." -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "CSG exportieren..." -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "Versionsinformationen" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "Bibliotheken anzeigen..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "Ansicht zurücksetzen" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:945 msgid "Font List" msgstr "Fontliste" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:946 msgid "Export as SVG..." msgstr "SVG exportieren..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:947 msgid "Export as AMF..." msgstr "AMF exportieren..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "Vergrößern" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "Verkleinern" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:952 msgid "View All" msgstr "Alles anzeigen" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "Tabs in Leerzeichen umwandeln" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "Symbolleisten verstecken" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" +msgstr "Einzug vermindern" + +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 +#, fuzzy +msgid "Message" +msgstr "help message" + +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "Zeit:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "Schritte:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "Bilder ausgeben" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "&Datei" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:966 msgid "Recent Files" msgstr "Zuletzt benutze Dateien" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "Exportieren" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Bearbeiten" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "D&esign" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "&Ansicht" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "&Hilfe" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "Suchen" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "Ersetzen" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "Suchtext" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "Fertig" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:982 msgid "Replacement string" msgstr "Ersetzen mit" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "Alles" @@ -705,136 +736,287 @@ msgstr "OpenCSG benutzen" msgid "Show this message again" msgstr "Diesen Dialog wieder anzeigen" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Ansicht" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Erweitert" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Editor" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Aktualisieren" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Funktionen" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Experimentelle Erweiterungen ein-/ausschalten" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Farbschema:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Editor" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Einfacher Editor" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "QScintilla Editor" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(Neustart erforderlich)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Font" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Syntaxhervorhebung" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +#, fuzzy +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Ctrl/Cmd+Mausrad zum Vergrößern des Textes benutzen" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Dokumentation" + +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "Einzug erhöhen" + +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "Einzug erhöhen" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Flächen anzeigen" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "Einzug erhöhen" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "&AST Baum anzeigen..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "Einzug erhöhen" + +#: objects/ui_Preferences.h:1126 +#, fuzzy +msgid "Start" +msgstr "Starnight" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Automatisch nach Aktualisierungen suchen" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Entwickler-Versionen einschließen" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Jetzt suchen" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Zuletzt gesucht: " -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Kompatibilitätswarnung anzeigen" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Aktivieren bei OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Rendern abbrechen ab " -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "Elementen" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Goldfeather Algorithmus erzwingen" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "CGAL Cache Größe" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "Byte" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "PolySet Cache Größe" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Öffnen von mehreren Dokumenten erlauben" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Verschieben des Editor und Konsole Fensters erlauben" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "Separate Editor und Konsole Fenster erlauben" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Startbildschirm anzeigen" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Lokalisierung der GUI einschalten (benötigt Neustart von OpenSCAD)" # This should not be visible (window title of the ToolBar). -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "toolBar" @@ -846,19 +1028,47 @@ msgstr "Form" msgid "%v / %m" msgstr "%v / %m" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Ansicht: Verschiebung = [ %.2f %.2f %.2f ], Rotation = [ %.2f %.2f %.2f ], " +"Abstand = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Unbenannt.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +#, fuzzy +msgid "Compile error." +msgstr "Übersetzen" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Datei speichern" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD Designs (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -866,11 +1076,11 @@ msgstr "" "%1 existiert bereits.\n" "Mochten Sie die Datei ersetzen?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Application" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -878,55 +1088,61 @@ msgstr "" "Das Dokument ist verändert.\n" "Möchten Sie die Datei wirklich neu laden?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "%1 Datei exportieren" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Dateien (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Unbenannt" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Unbenannt%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Export CSG File" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "Unbenannt.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "CSG Dateien (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Image exportieren" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "PNG Dateien (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Konsole" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Das Dokument ist verändert." -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Möchten Sie die Änderungen speichern?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" @@ -936,7 +1152,7 @@ msgstr "" "Benutze QGLWidget\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -944,7 +1160,7 @@ msgstr "" "Achtung: Es können Darstellungsfehler beim Anzeigen der Vorschau auftreten.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -954,7 +1170,7 @@ msgstr "" "nicht aus - OpenCSG wurde deaktiviert.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -964,7 +1180,7 @@ msgstr "" "2.0.\n" "Informationen zum OpenGL Treiber:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -975,24 +1191,19 @@ msgstr "" "%s (%s)\n" "OpenGL version %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -"Ansicht: Verschiebung = [ %.2f %.2f %.2f ], Rotation = [ %.2f %.2f %.2f ], " -"Abstand = %.2f" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Grundlagen" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Formen" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Extrusion" @@ -1014,9 +1225,6 @@ msgstr "Extrusion" #~ msgid "Sunset" #~ msgstr "Sunset" -#~ msgid "Starnight" -#~ msgstr "Starnight" - #~ msgid "BeforeDawn" #~ msgstr "BeforeDawn" @@ -1813,9 +2021,6 @@ msgstr "Extrusion" #~ msgid "Allowed options" #~ msgstr "Allowed options" -#~ msgid "help message" -#~ msgstr "help message" - #~ msgid "print the version" #~ msgstr "print the version" @@ -1988,9 +2193,6 @@ msgstr "Extrusion" #~ "DEPRECATED: Using ranges of the form [begin:end] with begin value greater " #~ "than the end value is deprecated." -#~ msgid "&Compile" -#~ msgstr "Übersetzen" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Übersetzen und Rendern (CGAL)" diff --git a/locale/es.po b/locale/es.po index 2dc70bfd..f8e95d29 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2015-01-21 22:36-0300\n" "Last-Translator: Ernesto Bazzano \n" "Language-Team: Español\n" @@ -19,82 +19,11 @@ msgstr "" "X-Poedit-SourceCharset: UTF-8\n" "X-Generator: Poedit 1.5.4\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "acerca de OpenSCAD" -#: objects/ui_FontListDialog.h:102 -msgid "OpenSCAD Font List" -msgstr "Lista de fuentes OpenSCAD" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "&Aceptar" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "Copiar al portapapeles" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "Filtro:" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

    This list shows the fonts currently registered with " -"OpenSCAD.

    Example:

      text(t = "
    -""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    -""Liberation Sans:style=Italic");
    " -msgstr "" -"

    Esta lista muestra los tipos de letra registrados " -"actualmente en OpenSCAD

    Ejemplo:

      "
    -"text(t = "OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    -""Liberation Sans:style=Italic");
    " - -#: objects/ui_launchingscreen.h:276 -msgid "Welcome to OpenSCAD" -msgstr "Bienvenido a OpenSCAD" - -#: objects/ui_launchingscreen.h:277 -msgid "New" -msgstr "Nuevo" - -#: objects/ui_launchingscreen.h:278 -msgid "Open" -msgstr "Abrir" - -#: objects/ui_launchingscreen.h:279 -msgid "Help" -msgstr "Ayuda" - -#: objects/ui_launchingscreen.h:280 -msgid "Recents" -msgstr "Recientes" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "Abrir recientes" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "Ejemplos" - -#: objects/ui_launchingscreen.h:285 -msgid "Open Example" -msgstr "Abrir ejemplos" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

    This list shows the fonts currently registered with " +"OpenSCAD.

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " +msgstr "" +"

    Esta lista muestra los tipos de letra registrados " +"actualmente en OpenSCAD

    Ejemplo:

      "
    +"text(t = "OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " + #: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "Bienvenido a OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "Nuevo" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "Abrir" + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "Ayuda" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "Recientes" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Abrir recientes" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:967 +msgid "Examples" +msgstr "Ejemplos" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "Abrir ejemplos" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "No mostrar de nuevo" +#: objects/ui_launchingscreen.h:313 +#, fuzzy +msgid "Version" +msgstr "Extrusión" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Informacion de las librerias y compilación" @@ -130,544 +140,564 @@ msgstr "Informacion de las librerias y compilación" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Informations detalles de las librerias y compilación" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "&Nuevos" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "&Abrir..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "&Salvar" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "S&alvar como..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "&Recargar" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "Salir" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "An&ular" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "&Repetir" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "Co&rtar" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "&Copiar" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "&Pegar" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "Ctrl+V" # no se que es -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "&Indenter" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Dési&ndenter" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "C&omentar" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "Desco&mentar" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "Pegar posición de la marco" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "Pegar rotación de la ventana" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Acercar" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" +msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Alejar" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" +msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "Ocultar editor" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:874 msgid "&Reload and Preview" msgstr "&Recargar y previsualizar" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "&Previsualizar" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "&Renderizar" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "Chequear validez" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "Mostrar &AST..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "Mostrar CSG &Arbre" -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "Mostar CSG &Produits" -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "Exportar como &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "Exportar como &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "Previsualizar" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:888 msgid "Surfaces" msgstr "Superficie" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "Estructura" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "Lanzar Juntos" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "Mostrar puntos" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "Mostrar ejes" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "Mostrar punto de mira" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:900 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "Animar" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "Arriba" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "Abajo" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "Izquierda" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "Derecha" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "Frente" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "Atrás" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "Diagonal" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "Centro" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "Perspectiva" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "Orthogonal" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "Ocultar consola" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "Acerca de" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "Documentación" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "Borrar recientes" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "Exportar a DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "Cerrar" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "Preferencias" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "Buscar..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "Buscar y reemplazar..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "Buscar próximo" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "Buscar previo" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "Buscar selección" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "Borrar cache" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "Pagina de OpenSCAD" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:939 msgid "Automatic Reload and Preview" msgstr "Recargar y previsualizar automáticamente" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "Exportar imagen..." -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "Exportar en CSG..." -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "Información de librerías" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "Mostrar carpeta de librerías" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "Reiniciar vista" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:945 msgid "Font List" msgstr "Lista de fuentes" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:946 msgid "Export as SVG..." msgstr "Exportar en SVG..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:947 msgid "Export as AMF..." msgstr "Exportar en AMF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "Acercar" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "Alejar" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:952 msgid "View All" msgstr "Ver todo" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "Convertir tabulado en espacios" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "Ocultar barra de herramientas" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" +msgstr "Dési&ndenter" + +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "Tiempo:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "Pasos:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "Grabar imágenes" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "&Archivo" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:966 msgid "Recent Files" msgstr "Archivos recientes" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "Exportar" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Editar" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "&Diseñar" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "&Ver" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "&Ayuda" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "Buscar" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "Reemplazar" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "Buscar palabra" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "Terminar" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:982 msgid "Replacement string" msgstr "Remplazar palabra" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "Todo" @@ -707,137 +737,291 @@ msgstr "Activar OpenCSG" msgid "Show this message again" msgstr "Mostrar el mensaje de nuevo" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "Vista 3D" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Advertencia" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Editar" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Actualizar" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Mejoras" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Activar/Desactivar mejoras experimentales" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Paleta de colores:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Editor de texto" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Editor simple" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "Editor QScintilla" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(necesita reiniciar)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Fuente" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Colorear sintaxis" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +#, fuzzy +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Use ctrl/cmd + rueda del mouse para hacer zoom al texto" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Documentación" + +# no se que es +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "&Indenter" + +# no se que es +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Superficie" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +# no se que es +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Mostrar &AST..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +# no se que es +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Comprobar actualización automáticamente" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Incluir las versiones en desarrollo" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Chequear ahora" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Último chequeo:" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Advertir incapacidad" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Activar OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Desactivar el render de" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "elementos" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Forzar Goldfeather" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Tamaño de cache de CGAL" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "bytes" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Tamaño de cache de PolySet" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Permitir a abrir varios documentos" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Habilitar soporte de editor y consola en diferentes lugares" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" "Habilitar el desacoplamiento de editor y consola para separar las ventanas" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Pantalla de bienvenida" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" "Habilitar interfaz de usuario localización (requiere reiniciar OpenSCAD)" -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "barra de herramientas" @@ -849,19 +1033,46 @@ msgstr "Formulario" msgid "%v / %m" msgstr "%v / %m" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Marco: posición = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], " +"distancia = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Sintitulo.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Salver archivo" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "Diseño OpenSCAD (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -869,11 +1080,11 @@ msgstr "" "%1 existe.\n" "Deseas reemplazarlo?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Aplicación" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -881,55 +1092,61 @@ msgstr "" "El documento ha sido modificado.\n" "¿Realmente desea volver a cargar el archivo ?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "Exportar %1 Archivo" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Archivo (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Sin titulo" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Sintitulo%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Exportar archivo CSG" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "Sintitulo.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "Archivo CSG (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Exportar una imagen" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "Archivo PNG (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Consola" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "El documento ha sido modificado." -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "¿Quieres guardar los cambios ?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" @@ -939,7 +1156,7 @@ msgstr "" "Utilizar QGLWidget\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -947,7 +1164,7 @@ msgstr "" "Advertencia: Usted puede experimentar OpenCSG errores de renderizado.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -957,7 +1174,7 @@ msgstr "" "desactivada. .\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -967,7 +1184,7 @@ msgstr "" "posterior.\n" "Su información renderer es como sigue:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -978,24 +1195,19 @@ msgstr "" "%s (%s)\n" "Versión OpenGL %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -"Marco: posición = [ %.2f %.2f %.2f ], rotación = [ %.2f %.2f %.2f ], " -"distancia = %.2f" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Básico" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Formas" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Extrusión" diff --git a/locale/fr.po b/locale/fr.po index b3b892a5..30ea95f2 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2014-12-14 10:20-0500\n" "Last-Translator: Keven Villeneuve \n" "Language-Team: French\n" @@ -19,82 +19,11 @@ msgstr "" "X-Poedit-SourceCharset: utf-8\n" "X-Generator: Poedit 1.7.1\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "À propos de OpenSCAD" -#: objects/ui_FontListDialog.h:102 -msgid "OpenSCAD Font List" -msgstr "Liste des polices OpenSCAD" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "&OK" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "Coller dans le presse-papier" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "Filtre:" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

    This list shows the fonts currently registered with " -"OpenSCAD.

    Example:

      text(t = "
    -""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    -""Liberation Sans:style=Italic");
    " -msgstr "" -"

    Cette liste affiche les polices présentement chargées " -"avec OpenSCAD

    Example:

      text(t = "
    -""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    -""Liberation Sans:style=Italic");
    " - -#: objects/ui_launchingscreen.h:276 -msgid "Welcome to OpenSCAD" -msgstr "Bienvenue dans OpenSCAD" - -#: objects/ui_launchingscreen.h:277 -msgid "New" -msgstr "Nouveau" - -#: objects/ui_launchingscreen.h:278 -msgid "Open" -msgstr "Ouvrir..." - -#: objects/ui_launchingscreen.h:279 -msgid "Help" -msgstr "Aide" - -#: objects/ui_launchingscreen.h:280 -msgid "Recents" -msgstr "Récents" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "Ouvrir un fichier récent" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "Exemples" - -#: objects/ui_launchingscreen.h:285 -msgid "Open Example" -msgstr "&Ouvrir un example" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

    This list shows the fonts currently registered with " +"OpenSCAD.

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " +msgstr "" +"

    Cette liste affiche les polices présentement chargées " +"avec OpenSCAD

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " + #: objects/ui_launchingscreen.h:294 +msgid "Welcome to OpenSCAD" +msgstr "Bienvenue dans OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +msgid "New" +msgstr "Nouveau" + +#: objects/ui_launchingscreen.h:296 +msgid "Open" +msgstr "Ouvrir..." + +#: objects/ui_launchingscreen.h:297 +msgid "Help" +msgstr "Aide" + +#: objects/ui_launchingscreen.h:298 +msgid "Recents" +msgstr "Récents" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Ouvrir un fichier récent" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:967 +msgid "Examples" +msgstr "Exemples" + +#: objects/ui_launchingscreen.h:303 +msgid "Open Example" +msgstr "&Ouvrir un example" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "Ne plus afficher" +#: objects/ui_launchingscreen.h:313 +#, fuzzy +msgid "Version" +msgstr "Extrusion" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "Bibliothèques et Infos de la version" @@ -130,543 +140,563 @@ msgstr "Bibliothèques et Infos de la version" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Informations détaillées des bibliothèques et de la version d'OpenSCAD" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "&Nouveau" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "&Ouvrir..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "Enregi&strer" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "Enregistrer &sous..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "&Recharger" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "&Quitter" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "Ann&uler" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "&Répéter" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "Co&uper" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "&Copier" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "&Coller" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "&Indenter" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "Dési&ndenter" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "Ctrl+Shift+I" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "C&ommenter" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "Déco&mmenter" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "Coller la translation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "Coller la rotation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Zoom Avant" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" +msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Zoom Arrière" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" +msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "Cacher l'éditeur" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:874 msgid "&Reload and Preview" msgstr "&Recharger et Aperçu" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "&Aperçu" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "&Rendu" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "Vérifier la Validité" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "Afficher &AST..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "Afficher CSG &Arbre" -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "Afficher CSG &Produits" -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "Exporter comme &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "Exporter comme &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "Aperçu" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:888 msgid "Surfaces" msgstr "Surfaces" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "Wireframe" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "Jeté ensemble" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "Afficher les Arêtes" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "Afficher les Axes" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "Afficher la Mire" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:900 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "Animer" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "Dessus" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "Dessous" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "Gauche" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "Droite" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "Face" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "Arrière" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "Diagonale" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "Centre" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "Perspective" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "Orthogonale" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "Cache la console" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "À propos" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "Documentation" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "Effacer Récents" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "Exporter comme DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "Fermer" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "Préférences" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "Rechercher..." -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "Rechercher et remplacer..." -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "Rechercher Suivant" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "Rechercher Précédent" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "Utiliser la sélection pour Rechercher" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "Vider les caches" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "Page d'accueil OpenSCAD" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:939 msgid "Automatic Reload and Preview" msgstr "Recharger et Aperçu Automatique" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "Exporter comme Image..." -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "Exporter comme CSG..." -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "Informations Bibliothèques" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "Afficher le dossier des bibliothèques" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "Réinitialiser la vue" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:945 msgid "Font List" msgstr "Liste des polices" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:946 msgid "Export as SVG..." msgstr "Exporter comme SVG..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:947 msgid "Export as AMF..." msgstr "Exporter comme AMF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "Zoom Avant" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "Zoom Arrière" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:952 msgid "View All" msgstr "&Voir Tout" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "Convertir les tabulations par des espaces" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "Cacher les boîtes à outils" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" +msgstr "Dési&ndenter" + +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" +msgstr "Ctrl+Shift+I" + +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "Temps:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "Étapes:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "Vider les photos" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "&Fichier" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:966 msgid "Recent Files" msgstr "Fichiers Récents" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "Exporter" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Édition" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "Conception" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "&Vue" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "&Aide" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "Rechercher" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "Remplacer" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "Rechercher une chaîne de caractères" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "Terminer" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:982 msgid "Replacement string" msgstr "Remplacer une chaîne de caractères" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "Tout" @@ -706,138 +736,288 @@ msgstr "Activer OpenCSG" msgid "Show this message again" msgstr "Affiche ce message à nouveau" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "&Vue 3D" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Avancé" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Éditeur" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "Mettre à jour" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Fonctionnalités" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "Activer/Désactiver les fonctionnalités expérimentales" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Palette de couleurs:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 msgid "Editor Type" msgstr "Type d'éditeur" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 msgid "Simple Editor" msgstr "Éditeur Simple" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "Éditeur QScintilla" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "(nécessite un redémarrage)" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Police" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "Colorer la coloration syntaxique" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +#, fuzzy +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Utiliser Ctrl/Cmd-Roulette-Souris pour agrandir le texte" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "Documentation" + +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "Surfaces" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Afficher &AST..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "&Indenter" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "Vérifier les mises à jour automatiquement" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Inclure les versions de développement" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Vérifier Maintenant" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "Dernière vérification:" -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "OpenCSG" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Afficher les avertissements de capacité" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Activer pour OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Désactiver le rendu à" -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "éléments" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Forcer Goldfeather" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Taille du Cache de CGAL" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "octets" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Taille du Cache PolySet" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "Autoriser l'ouverture de plusieurs documents" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "Activer l'ancrage de l'Éditeur et de la Console à différents endroits" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" "Activer désancrage de l'Éditeur et de la Console dans des fenêtres séparés" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "Affiche l'écran d'accueil" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" "Activer la localisation de l'interface utilisateur (Nécessite un redémarrage " "d'OpenSCAD)" -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "boîte à outils" @@ -849,19 +1029,46 @@ msgstr "Formulaire" msgid "%v / %m" msgstr "%v / %m" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" +"Fenêtre de rendu: translation = [ %.2f %.2f %.2f ], rotation = [ %.2f %.2f " +"%.2f ], distance = %.2f" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "Untitled.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +msgid "Compile error." +msgstr "" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Enregistrer le Fichier" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "OpenSCAD Designs (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" @@ -869,11 +1076,11 @@ msgstr "" "%1 existe déjà.\n" "Voulez-vous le remplacer?" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "Application" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" @@ -881,55 +1088,61 @@ msgstr "" "Ce document a été modifié.\n" "Voulez-vous vraiment recharger le fichier?" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "Exporter %1 Fichier" -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "%1 Fichiers (*%2)" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "Sans Titre" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "Sans Titre%1" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "Exporter un fichier CSG" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "SansTitre.csg" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "Fichiers CSG (*.csg)" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "Exporter une Image" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "Fichiers PNG (*.png)" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "Console" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "Ce document a été modifié" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "Voulez-vous enregistrer vos changements?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" @@ -939,7 +1152,7 @@ msgstr "" "Utilise QGLWidget\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -947,7 +1160,7 @@ msgstr "" "Avertissement: Vous pourriez avoir des erreurs de rendu OpenCSG\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -957,7 +1170,7 @@ msgstr "" "désactivé.\n" "\n" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -967,7 +1180,7 @@ msgstr "" "OpenGL 2.0 ou ultérieur.\n" "Voici les informations de votre moteur de rendu:\n" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -978,24 +1191,19 @@ msgstr "" "%s (%s)\n" "Version OpenGL %s\n" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -"Fenêtre de rendu: translation = [ %.2f %.2f %.2f ], rotation = [ %.2f %.2f " -"%.2f ], distance = %.2f" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "Bases" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "Formes" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "Extrusion" diff --git a/locale/openscad.pot b/locale/openscad.pot index 497a471e..3d590ff3 100644 --- a/locale/openscad.pot +++ b/locale/openscad.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: OpenSCAD 2015.01.12\n" +"Project-Id-Version: OpenSCAD 2015.01.24\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-12 17:12+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,6 +16,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" #: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" @@ -93,7 +94,7 @@ msgid "Open Recent" msgstr "" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:973 +#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "" @@ -117,566 +118,566 @@ msgstr "" msgid "OpenSCAD Detailed Library and Build Information" msgstr "" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "" -#: objects/ui_MainWindow.h:867 -msgid "U&nindent" -msgstr "" - -#: objects/ui_MainWindow.h:868 -msgid "Ctrl+Shift+I" -msgstr "" - -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "" -#: objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "" -#: objects/ui_MainWindow.h:873 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "" -#: objects/ui_MainWindow.h:876 objects/ui_MainWindow.h:955 -msgid "Zoom In" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" msgstr "" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "" -#: objects/ui_MainWindow.h:878 objects/ui_MainWindow.h:957 -msgid "Zoom Out" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" msgstr "" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "" -#: objects/ui_MainWindow.h:880 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "" -#: objects/ui_MainWindow.h:881 +#: objects/ui_MainWindow.h:874 msgid "&Reload and Preview" msgstr "" -#: objects/ui_MainWindow.h:882 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "" -#: objects/ui_MainWindow.h:883 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "" -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "" -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "" -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:888 msgid "Surfaces" msgstr "" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "" -#: objects/ui_MainWindow.h:902 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "" -#: objects/ui_MainWindow.h:904 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "" -#: objects/ui_MainWindow.h:906 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:900 msgid "Show Scale Markers" msgstr "" -#: objects/ui_MainWindow.h:908 +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "" -#: objects/ui_MainWindow.h:910 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "" -#: objects/ui_MainWindow.h:912 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "" -#: objects/ui_MainWindow.h:914 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "" -#: objects/ui_MainWindow.h:916 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "" -#: objects/ui_MainWindow.h:917 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "" -#: objects/ui_MainWindow.h:918 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "" -#: objects/ui_MainWindow.h:919 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "" -#: objects/ui_MainWindow.h:920 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "" -#: objects/ui_MainWindow.h:921 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "" -#: objects/ui_MainWindow.h:922 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "" -#: objects/ui_MainWindow.h:923 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "" -#: objects/ui_MainWindow.h:924 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "" -#: objects/ui_MainWindow.h:926 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "" -#: objects/ui_MainWindow.h:927 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "" -#: objects/ui_MainWindow.h:928 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "" -#: objects/ui_MainWindow.h:929 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "" -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "" -#: objects/ui_MainWindow.h:931 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "" -#: objects/ui_MainWindow.h:933 objects/ui_Preferences.h:1053 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "" -#: objects/ui_MainWindow.h:935 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "" -#: objects/ui_MainWindow.h:937 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "" -#: objects/ui_MainWindow.h:938 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "" -#: objects/ui_MainWindow.h:939 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "" -#: objects/ui_MainWindow.h:940 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "" -#: objects/ui_MainWindow.h:941 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "" -#: objects/ui_MainWindow.h:942 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "" -#: objects/ui_MainWindow.h:943 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "" -#: objects/ui_MainWindow.h:944 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "" -#: objects/ui_MainWindow.h:945 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "" -#: objects/ui_MainWindow.h:946 +#: objects/ui_MainWindow.h:939 msgid "Automatic Reload and Preview" msgstr "" -#: objects/ui_MainWindow.h:947 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "" -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:945 msgid "Font List" msgstr "" -#: objects/ui_MainWindow.h:953 +#: objects/ui_MainWindow.h:946 msgid "Export as SVG..." msgstr "" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:947 msgid "Export as AMF..." msgstr "" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "" -#: objects/ui_MainWindow.h:959 +#: objects/ui_MainWindow.h:952 msgid "View All" msgstr "" -#: objects/ui_MainWindow.h:960 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "" -#: objects/ui_MainWindow.h:962 -msgid "Hide parameters" +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" msgstr "" -#: objects/ui_MainWindow.h:963 -msgid "Hide library" +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" msgstr "" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 msgid "Message" msgstr "" -#: objects/ui_MainWindow.h:967 +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "" -#: objects/ui_MainWindow.h:968 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "" -#: objects/ui_MainWindow.h:969 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:966 msgid "Recent Files" msgstr "" -#: objects/ui_MainWindow.h:974 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "" -#: objects/ui_MainWindow.h:976 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "" -#: objects/ui_MainWindow.h:977 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "" -#: objects/ui_MainWindow.h:982 objects/ui_MainWindow.h:989 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "" -#: objects/ui_MainWindow.h:985 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "" -#: objects/ui_MainWindow.h:986 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr "" -#: objects/ui_MainWindow.h:987 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "" -#: objects/ui_MainWindow.h:988 +#: objects/ui_MainWindow.h:982 msgid "Replacement string" msgstr "" -#: objects/ui_MainWindow.h:990 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "" -#: objects/ui_MainWindow.h:991 -msgid "Libraries" -msgstr "" - #: objects/ui_OpenCSGWarningDialog.h:86 msgid "OpenGL Warning" msgstr "" @@ -703,273 +704,277 @@ msgstr "" msgid "Show this message again" msgstr "" -#: objects/ui_Preferences.h:1054 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "" -#: objects/ui_Preferences.h:1055 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "" -#: objects/ui_Preferences.h:1056 src/mainwin.cc:2410 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "" -#: objects/ui_Preferences.h:1057 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "" -#: objects/ui_Preferences.h:1058 objects/ui_Preferences.h:1138 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "" -#: objects/ui_Preferences.h:1060 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "" -#: objects/ui_Preferences.h:1062 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "" -#: objects/ui_Preferences.h:1063 -msgid "Editor Type" -msgstr "" - -#: objects/ui_Preferences.h:1066 -msgid "Simple Editor" -msgstr "" - -#: objects/ui_Preferences.h:1067 -msgid "QScintilla Editor" -msgstr "" - -#: objects/ui_Preferences.h:1069 -msgid "(requires restart)" -msgstr "" - -#: objects/ui_Preferences.h:1070 -msgid "Font" -msgstr "" - #: objects/ui_Preferences.h:1071 -msgid "Color syntax highlighting" +msgid "Show Warnings and Errors in 3D View" msgstr "" #: objects/ui_Preferences.h:1072 -msgid "Ctrl/Cmd-Mouse-wheel zooms text" -msgstr "" - -#: objects/ui_Preferences.h:1073 -msgid "Indentation" -msgstr "" - -#: objects/ui_Preferences.h:1074 -msgid "Auto Indent" +msgid "Editor Type" msgstr "" #: objects/ui_Preferences.h:1075 -msgid "Indent using" +msgid "Simple Editor" msgstr "" -#: objects/ui_Preferences.h:1078 src/settings.cc:134 -msgid "Spaces" +#: objects/ui_Preferences.h:1076 +msgid "QScintilla Editor" msgstr "" -#: objects/ui_Preferences.h:1079 src/settings.cc:134 -msgid "Tabs" +#: objects/ui_Preferences.h:1078 +msgid "(requires restart)" +msgstr "" + +#: objects/ui_Preferences.h:1079 +msgid "Font" +msgstr "" + +#: objects/ui_Preferences.h:1080 +msgid "Color syntax highlighting" msgstr "" #: objects/ui_Preferences.h:1081 -msgid "Indentation width" +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "" #: objects/ui_Preferences.h:1082 -msgid "Tab width" +msgid "Indentation" msgstr "" #: objects/ui_Preferences.h:1083 -msgid "Tab key function" +msgid "Auto Indent" msgstr "" -#: objects/ui_Preferences.h:1086 objects/ui_Preferences.h:1116 -#: src/settings.cc:135 -msgid "Indent" +#: objects/ui_Preferences.h:1084 +msgid "Indent using" msgstr "" #: objects/ui_Preferences.h:1087 src/settings.cc:135 +msgid "Spaces" +msgstr "" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +msgid "Indent" +msgstr "" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 msgid "Insert Tab" msgstr "" -#: objects/ui_Preferences.h:1089 +#: objects/ui_Preferences.h:1098 msgid "Show whitespace" msgstr "" -#: objects/ui_Preferences.h:1092 src/settings.cc:131 +#: objects/ui_Preferences.h:1101 src/settings.cc:132 msgid "Never" msgstr "" -#: objects/ui_Preferences.h:1093 src/settings.cc:131 +#: objects/ui_Preferences.h:1102 src/settings.cc:132 msgid "Always" msgstr "" -#: objects/ui_Preferences.h:1094 +#: objects/ui_Preferences.h:1103 msgid "Only after indentation" msgstr "" -#: objects/ui_Preferences.h:1096 +#: objects/ui_Preferences.h:1105 msgid "Size" msgstr "" -#: objects/ui_Preferences.h:1097 +#: objects/ui_Preferences.h:1106 msgid "Display" msgstr "" -#: objects/ui_Preferences.h:1098 +#: objects/ui_Preferences.h:1107 msgid "Enable brace matching" msgstr "" -#: objects/ui_Preferences.h:1099 +#: objects/ui_Preferences.h:1108 msgid "Highlight current line" msgstr "" -#: objects/ui_Preferences.h:1100 objects/ui_Preferences.h:1133 +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 msgid "Line wrap" msgstr "" -#: objects/ui_Preferences.h:1103 objects/ui_Preferences.h:1120 -#: objects/ui_Preferences.h:1128 src/settings.cc:126 src/settings.cc:129 -#: src/settings.cc:130 +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 msgid "None" msgstr "" -#: objects/ui_Preferences.h:1104 src/settings.cc:126 +#: objects/ui_Preferences.h:1113 src/settings.cc:127 msgid "Wrap at character boundaries" msgstr "" -#: objects/ui_Preferences.h:1105 src/settings.cc:126 +#: objects/ui_Preferences.h:1114 src/settings.cc:127 msgid "Wrap at word boundaries" msgstr "" -#: objects/ui_Preferences.h:1107 +#: objects/ui_Preferences.h:1116 msgid "Line wrap indentation" msgstr "" -#: objects/ui_Preferences.h:1108 +#: objects/ui_Preferences.h:1117 msgid "Line wrap visualization" msgstr "" -#: objects/ui_Preferences.h:1109 +#: objects/ui_Preferences.h:1118 msgid "Style" msgstr "" -#: objects/ui_Preferences.h:1112 src/settings.cc:127 +#: objects/ui_Preferences.h:1121 src/settings.cc:128 msgid "Fixed" msgstr "" -#: objects/ui_Preferences.h:1113 src/settings.cc:127 +#: objects/ui_Preferences.h:1122 src/settings.cc:128 msgid "Same" msgstr "" -#: objects/ui_Preferences.h:1114 src/settings.cc:127 +#: objects/ui_Preferences.h:1123 src/settings.cc:128 msgid "Indented" msgstr "" -#: objects/ui_Preferences.h:1117 +#: objects/ui_Preferences.h:1126 msgid "Start" msgstr "" -#: objects/ui_Preferences.h:1121 objects/ui_Preferences.h:1129 -#: src/settings.cc:129 src/settings.cc:130 +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 msgid "Text" msgstr "" -#: objects/ui_Preferences.h:1122 objects/ui_Preferences.h:1130 -#: src/settings.cc:129 src/settings.cc:130 +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 msgid "Border" msgstr "" -#: objects/ui_Preferences.h:1123 objects/ui_Preferences.h:1131 -#: src/settings.cc:129 src/settings.cc:130 +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 msgid "Margin" msgstr "" -#: objects/ui_Preferences.h:1125 +#: objects/ui_Preferences.h:1134 msgid "End" msgstr "" -#: objects/ui_Preferences.h:1134 +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "" -#: objects/ui_Preferences.h:1135 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "" -#: objects/ui_Preferences.h:1136 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "" -#: objects/ui_Preferences.h:1137 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "" -#: objects/ui_Preferences.h:1139 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "" -#: objects/ui_Preferences.h:1140 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "" -#: objects/ui_Preferences.h:1141 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "" -#: objects/ui_Preferences.h:1142 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "" -#: objects/ui_Preferences.h:1143 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "" -#: objects/ui_Preferences.h:1144 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "" -#: objects/ui_Preferences.h:1145 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "" -#: objects/ui_Preferences.h:1146 objects/ui_Preferences.h:1148 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "" -#: objects/ui_Preferences.h:1147 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "" -#: objects/ui_Preferences.h:1149 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "" -#: objects/ui_Preferences.h:1150 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "" -#: objects/ui_Preferences.h:1151 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" -#: objects/ui_Preferences.h:1152 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "" -#: objects/ui_Preferences.h:1153 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" -#: objects/ui_Preferences.h:1154 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "" @@ -981,106 +986,108 @@ msgstr "" msgid "%v / %m" msgstr "" -#: src/Camera.cc:129 +#: src/Camera.cc:126 #, c-format msgid "" "Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " "distance = %.2f" msgstr "" -#: src/mainwin.cc:787 src/mainwin.cc:1351 +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "" -#: src/mainwin.cc:975 +#: src/mainwin.cc:971 msgid "Compile error." msgstr "" -#: src/mainwin.cc:978 +#: src/mainwin.cc:974 msgid "Error while compiling '%1'." msgstr "" -#: src/mainwin.cc:982 -msgid "Compilation generated %1 warnings." -msgstr "" +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" -#: src/mainwin.cc:985 +#: src/mainwin.cc:988 msgid " For details see console window." msgstr "" -#: src/mainwin.cc:1350 +#: src/mainwin.cc:1353 msgid "Save File" msgstr "" -#: src/mainwin.cc:1352 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "" -#: src/mainwin.cc:1362 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" -#: src/mainwin.cc:1681 +#: src/mainwin.cc:1684 msgid "Application" msgstr "" -#: src/mainwin.cc:1682 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" -#: src/mainwin.cc:2029 src/mainwin.cc:2086 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 msgid "Export %1 File" msgstr "" -#: src/mainwin.cc:2030 src/mainwin.cc:2090 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "" -#: src/mainwin.cc:2031 +#: src/mainwin.cc:2040 msgid "Untitled" msgstr "" -#: src/mainwin.cc:2088 +#: src/mainwin.cc:2096 msgid "Untitled%1" msgstr "" -#: src/mainwin.cc:2139 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "" -#: src/mainwin.cc:2140 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "" -#: src/mainwin.cc:2141 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "" -#: src/mainwin.cc:2167 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "" -#: src/mainwin.cc:2167 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "" -#: src/mainwin.cc:2415 +#: src/mainwin.cc:2423 msgid "Console" msgstr "" -#: src/mainwin.cc:2547 +#: src/mainwin.cc:2560 msgid "The document has been modified." msgstr "" -#: src/mainwin.cc:2548 +#: src/mainwin.cc:2561 msgid "Do you want to save your changes?" msgstr "" -#: src/openscad.cc:602 +#: src/openscad.cc:604 msgid "" "Fontconfig needs to update its font cache.\n" "This can take up to a couple of minutes." @@ -1121,18 +1128,18 @@ msgid "" "OpenGL version %s\n" msgstr "" -#: src/settings.cc:131 +#: src/settings.cc:132 msgid "After indentation" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "" diff --git a/locale/ru.po b/locale/ru.po index 8fc11980..80617612 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2013-02-24 17:50+0100\n" "Last-Translator: \n" "Language-Team: Russian\n" @@ -18,80 +18,11 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +#: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" msgstr "О программе OpenSCAD" -#: objects/ui_FontListDialog.h:102 -#, fuzzy -msgid "OpenSCAD Font List" -msgstr "Шрифт" - -#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 -msgid "&OK" -msgstr "" - -#: objects/ui_FontListDialog.h:104 -msgid "Copy to Clipboard" -msgstr "" - -#: objects/ui_FontListDialog.h:105 -msgid "Filter:" -msgstr "" - -#: objects/ui_FontListDialog.h:106 -msgid "" -"

    This list shows the fonts currently registered with " -"OpenSCAD.

    Example:

      text(t = "
    -""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    -""Liberation Sans:style=Italic");
    " -msgstr "" - -#: objects/ui_launchingscreen.h:276 -#, fuzzy -msgid "Welcome to OpenSCAD" -msgstr "О программе OpenSCAD" - -#: objects/ui_launchingscreen.h:277 -#, fuzzy -msgid "New" -msgstr "&Создать" - -#: objects/ui_launchingscreen.h:278 -#, fuzzy -msgid "Open" -msgstr "&Открыть..." - -#: objects/ui_launchingscreen.h:279 -#, fuzzy -msgid "Help" -msgstr "&Справка" - -#: objects/ui_launchingscreen.h:280 -#, fuzzy -msgid "Recents" -msgstr "Открыть файл" - -#: objects/ui_launchingscreen.h:281 -msgid "Open Recent" -msgstr "Открыть недавние" - -#: objects/ui_launchingscreen.h:282 objects/ui_launchingscreen.h:284 -#: objects/ui_MainWindow.h:855 -msgid "Examples" -msgstr "Примеры" - -#: objects/ui_launchingscreen.h:285 -#, fuzzy -msgid "Open Example" -msgstr "Примеры" - -#: objects/ui_launchingscreen.h:287 +#: objects/ui_AboutDialog.h:105 objects/ui_launchingscreen.h:305 msgid "" "\n" "

    This list shows the fonts currently registered with " +"OpenSCAD.

    Example:

      text(t = "
    +""OpenSCAD", font = "DejaVu Sans");
      text(t = "OpenSCAD", font = "
    +""Liberation Sans:style=Italic");
    " +msgstr "" + #: objects/ui_launchingscreen.h:294 +#, fuzzy +msgid "Welcome to OpenSCAD" +msgstr "О программе OpenSCAD" + +#: objects/ui_launchingscreen.h:295 +#, fuzzy +msgid "New" +msgstr "&Создать" + +#: objects/ui_launchingscreen.h:296 +#, fuzzy +msgid "Open" +msgstr "&Открыть..." + +#: objects/ui_launchingscreen.h:297 +#, fuzzy +msgid "Help" +msgstr "&Справка" + +#: objects/ui_launchingscreen.h:298 +#, fuzzy +msgid "Recents" +msgstr "Открыть файл" + +#: objects/ui_launchingscreen.h:299 +msgid "Open Recent" +msgstr "Открыть недавние" + +#: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 +#: objects/ui_MainWindow.h:967 +msgid "Examples" +msgstr "Примеры" + +#: objects/ui_launchingscreen.h:303 +#, fuzzy +msgid "Open Example" +msgstr "Примеры" + +#: objects/ui_launchingscreen.h:312 msgid "Don't show again" msgstr "" +#: objects/ui_launchingscreen.h:313 +msgid "Version" +msgstr "" + #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" msgstr "" @@ -117,553 +125,573 @@ msgstr "" msgid "OpenSCAD Detailed Library and Build Information" msgstr "ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ библиотеках и Ñборке OpenSCAD" -#: objects/ui_MainWindow.h:731 +#: objects/ui_MainWindow.h:838 msgid "&New" msgstr "&Создать" -#: objects/ui_MainWindow.h:732 +#: objects/ui_MainWindow.h:839 msgid "Ctrl+N" msgstr "" -#: objects/ui_MainWindow.h:733 +#: objects/ui_MainWindow.h:840 msgid "&Open..." msgstr "&Открыть..." -#: objects/ui_MainWindow.h:734 +#: objects/ui_MainWindow.h:841 msgid "Ctrl+O" msgstr "" -#: objects/ui_MainWindow.h:735 +#: objects/ui_MainWindow.h:842 msgid "&Save" msgstr "&Сохранить" -#: objects/ui_MainWindow.h:736 +#: objects/ui_MainWindow.h:843 msgid "Ctrl+S" msgstr "" -#: objects/ui_MainWindow.h:737 +#: objects/ui_MainWindow.h:844 msgid "Save &As..." msgstr "Сохранить &как..." -#: objects/ui_MainWindow.h:738 +#: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" msgstr "" -#: objects/ui_MainWindow.h:739 +#: objects/ui_MainWindow.h:846 msgid "&Reload" msgstr "&Обновить" -#: objects/ui_MainWindow.h:740 +#: objects/ui_MainWindow.h:847 msgid "Ctrl+R" msgstr "" -#: objects/ui_MainWindow.h:741 +#: objects/ui_MainWindow.h:848 msgid "&Quit" msgstr "&Выход" -#: objects/ui_MainWindow.h:742 +#: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" msgstr "" -#: objects/ui_MainWindow.h:743 +#: objects/ui_MainWindow.h:850 msgid "&Undo" msgstr "&Отменить" -#: objects/ui_MainWindow.h:744 +#: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" msgstr "" -#: objects/ui_MainWindow.h:745 +#: objects/ui_MainWindow.h:852 msgid "&Redo" msgstr "&Повторить" -#: objects/ui_MainWindow.h:746 +#: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" msgstr "" -#: objects/ui_MainWindow.h:747 +#: objects/ui_MainWindow.h:854 msgid "Cu&t" msgstr "Ð’Ñ‹&резать" -#: objects/ui_MainWindow.h:748 +#: objects/ui_MainWindow.h:855 msgid "Ctrl+X" msgstr "" -#: objects/ui_MainWindow.h:749 +#: objects/ui_MainWindow.h:856 msgid "&Copy" msgstr "&Копировать" -#: objects/ui_MainWindow.h:750 +#: objects/ui_MainWindow.h:857 msgid "Ctrl+C" msgstr "" -#: objects/ui_MainWindow.h:751 +#: objects/ui_MainWindow.h:858 msgid "&Paste" msgstr "&Ð’Ñтавить" -#: objects/ui_MainWindow.h:752 +#: objects/ui_MainWindow.h:859 msgid "Ctrl+V" msgstr "" -#: objects/ui_MainWindow.h:753 +#: objects/ui_MainWindow.h:860 msgid "&Indent" msgstr "&Добавить отÑтуп" -#: objects/ui_MainWindow.h:754 +#: objects/ui_MainWindow.h:861 msgid "Ctrl+I" msgstr "" -#: objects/ui_MainWindow.h:755 -msgid "U&nindent" -msgstr "У&брать отÑтуп" - -#: objects/ui_MainWindow.h:756 -msgid "Ctrl+Shift+I" -msgstr "" - -#: objects/ui_MainWindow.h:757 +#: objects/ui_MainWindow.h:862 msgid "C&omment" msgstr "Зако&мментировать" -#: objects/ui_MainWindow.h:758 +#: objects/ui_MainWindow.h:863 msgid "Ctrl+D" msgstr "" -#: objects/ui_MainWindow.h:759 +#: objects/ui_MainWindow.h:864 msgid "Unco&mment" msgstr "Р&аÑкомментировать" -#: objects/ui_MainWindow.h:760 +#: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" msgstr "" -#: objects/ui_MainWindow.h:761 +#: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" msgstr "Ð’Ñтавить Ñмещение точки обзора" -#: objects/ui_MainWindow.h:762 +#: objects/ui_MainWindow.h:867 msgid "Ctrl+T" msgstr "" -#: objects/ui_MainWindow.h:763 +#: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" msgstr "Ð’Ñтавить поворот точки обзора" -#: objects/ui_MainWindow.h:764 objects/ui_MainWindow.h:842 -msgid "Zoom In" -msgstr "Увеличить маÑштаб" +#: objects/ui_MainWindow.h:869 +msgid "Increase Font Size" +msgstr "" -#: objects/ui_MainWindow.h:765 +#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "" -#: objects/ui_MainWindow.h:766 objects/ui_MainWindow.h:844 -msgid "Zoom Out" -msgstr "Уменьшить маÑштаб" +#: objects/ui_MainWindow.h:871 +msgid "Decrease Font Size" +msgstr "" -#: objects/ui_MainWindow.h:767 +#: objects/ui_MainWindow.h:872 msgid "Ctrl+-" msgstr "" -#: objects/ui_MainWindow.h:768 +#: objects/ui_MainWindow.h:873 msgid "Hide editor" msgstr "Скрыть редактор" -#: objects/ui_MainWindow.h:769 +#: objects/ui_MainWindow.h:874 #, fuzzy msgid "&Reload and Preview" msgstr "&Обновить и компилировать" -#: objects/ui_MainWindow.h:770 +#: objects/ui_MainWindow.h:875 msgid "F4" msgstr "" -#: objects/ui_MainWindow.h:771 +#: objects/ui_MainWindow.h:876 msgid "&Preview" msgstr "" -#: objects/ui_MainWindow.h:772 +#: objects/ui_MainWindow.h:877 msgid "F5" msgstr "" -#: objects/ui_MainWindow.h:773 +#: objects/ui_MainWindow.h:878 msgid "&Render" msgstr "" -#: objects/ui_MainWindow.h:774 +#: objects/ui_MainWindow.h:879 msgid "F6" msgstr "" -#: objects/ui_MainWindow.h:775 +#: objects/ui_MainWindow.h:880 msgid "Check Validity" msgstr "" -#: objects/ui_MainWindow.h:776 +#: objects/ui_MainWindow.h:881 msgid "Display &AST..." msgstr "Показать &AST..." -#: objects/ui_MainWindow.h:777 +#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "Показать &дерево CSG..." -#: objects/ui_MainWindow.h:778 +#: objects/ui_MainWindow.h:883 msgid "Display CSG &Products..." msgstr "Показать &результаты CSG..." -#: objects/ui_MainWindow.h:779 +#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "ЭкÑпортировать в &STL..." -#: objects/ui_MainWindow.h:780 +#: objects/ui_MainWindow.h:885 msgid "Export as &OFF..." msgstr "ЭкÑпортировать в &OFF..." -#: objects/ui_MainWindow.h:781 +#: objects/ui_MainWindow.h:886 msgid "Preview" msgstr "" -#: objects/ui_MainWindow.h:782 +#: objects/ui_MainWindow.h:887 msgid "F9" msgstr "" -#: objects/ui_MainWindow.h:783 +#: objects/ui_MainWindow.h:888 #, fuzzy msgid "Surfaces" msgstr "ПоверхноÑти CGAL" -#: objects/ui_MainWindow.h:784 +#: objects/ui_MainWindow.h:889 msgid "F10" msgstr "" -#: objects/ui_MainWindow.h:785 +#: objects/ui_MainWindow.h:890 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:786 +#: objects/ui_MainWindow.h:891 msgid "F11" msgstr "" -#: objects/ui_MainWindow.h:787 +#: objects/ui_MainWindow.h:892 msgid "Thrown Together" msgstr "Ð’ÑÑ‘ вмеÑте" -#: objects/ui_MainWindow.h:788 +#: objects/ui_MainWindow.h:893 msgid "F12" msgstr "" -#: objects/ui_MainWindow.h:789 +#: objects/ui_MainWindow.h:894 msgid "Show Edges" msgstr "Показывать рёбра" -#: objects/ui_MainWindow.h:790 +#: objects/ui_MainWindow.h:895 msgid "Ctrl+1" msgstr "" -#: objects/ui_MainWindow.h:791 +#: objects/ui_MainWindow.h:896 msgid "Show Axes" msgstr "Показывать оÑи" -#: objects/ui_MainWindow.h:792 +#: objects/ui_MainWindow.h:897 msgid "Ctrl+2" msgstr "" -#: objects/ui_MainWindow.h:793 +#: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" msgstr "Показывать перекреÑтиÑ" -#: objects/ui_MainWindow.h:794 +#: objects/ui_MainWindow.h:899 msgid "Ctrl+3" msgstr "" -#: objects/ui_MainWindow.h:795 +#: objects/ui_MainWindow.h:900 +msgid "Show Scale Markers" +msgstr "" + +#: objects/ui_MainWindow.h:901 msgid "Animate" msgstr "ÐнимациÑ" -#: objects/ui_MainWindow.h:796 +#: objects/ui_MainWindow.h:902 msgid "Top" msgstr "Сверху" -#: objects/ui_MainWindow.h:797 +#: objects/ui_MainWindow.h:903 msgid "Ctrl+4" msgstr "" -#: objects/ui_MainWindow.h:798 +#: objects/ui_MainWindow.h:904 msgid "Bottom" msgstr "Снизу" -#: objects/ui_MainWindow.h:799 +#: objects/ui_MainWindow.h:905 msgid "Ctrl+5" msgstr "" -#: objects/ui_MainWindow.h:800 +#: objects/ui_MainWindow.h:906 msgid "Left" msgstr "Слева" -#: objects/ui_MainWindow.h:801 +#: objects/ui_MainWindow.h:907 msgid "Ctrl+6" msgstr "" -#: objects/ui_MainWindow.h:802 +#: objects/ui_MainWindow.h:908 msgid "Right" msgstr "Справа" -#: objects/ui_MainWindow.h:803 +#: objects/ui_MainWindow.h:909 msgid "Ctrl+7" msgstr "" -#: objects/ui_MainWindow.h:804 +#: objects/ui_MainWindow.h:910 msgid "Front" msgstr "Спереди" -#: objects/ui_MainWindow.h:805 +#: objects/ui_MainWindow.h:911 msgid "Ctrl+8" msgstr "" -#: objects/ui_MainWindow.h:806 +#: objects/ui_MainWindow.h:912 msgid "Back" msgstr "Сзади" -#: objects/ui_MainWindow.h:807 +#: objects/ui_MainWindow.h:913 msgid "Ctrl+9" msgstr "" -#: objects/ui_MainWindow.h:808 +#: objects/ui_MainWindow.h:914 msgid "Diagonal" msgstr "ÐкÑонометричеÑкий" -#: objects/ui_MainWindow.h:809 +#: objects/ui_MainWindow.h:915 msgid "Ctrl+0" msgstr "" -#: objects/ui_MainWindow.h:810 +#: objects/ui_MainWindow.h:916 msgid "Center" msgstr "По центру" -#: objects/ui_MainWindow.h:811 +#: objects/ui_MainWindow.h:917 msgid "Perspective" msgstr "ПерÑпектива" -#: objects/ui_MainWindow.h:812 +#: objects/ui_MainWindow.h:918 msgid "Orthogonal" msgstr "ПрÑÐ¼Ð¾ÑƒÐ³Ð¾Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾ÐµÐºÑ†Ð¸Ñ" -#: objects/ui_MainWindow.h:813 +#: objects/ui_MainWindow.h:919 msgid "Hide console" msgstr "Скрыть конÑоль" -#: objects/ui_MainWindow.h:814 +#: objects/ui_MainWindow.h:920 msgid "About" msgstr "О программе" -#: objects/ui_MainWindow.h:815 +#: objects/ui_MainWindow.h:921 msgid "Documentation" msgstr "ДокументациÑ" -#: objects/ui_MainWindow.h:816 +#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "ОчиÑтить ÑпиÑок" -#: objects/ui_MainWindow.h:817 +#: objects/ui_MainWindow.h:923 msgid "Export as DXF..." msgstr "ЭкÑпортировать в DXF..." -#: objects/ui_MainWindow.h:818 objects/ui_OpenCSGWarningDialog.h:94 +#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 msgid "Close" msgstr "Закрыть" -#: objects/ui_MainWindow.h:819 +#: objects/ui_MainWindow.h:925 msgid "Ctrl+W" msgstr "" -#: objects/ui_MainWindow.h:820 objects/ui_Preferences.h:608 +#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" msgstr "ÐаÑтройки" -#: objects/ui_MainWindow.h:821 +#: objects/ui_MainWindow.h:927 msgid "Find..." msgstr "" -#: objects/ui_MainWindow.h:822 +#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "" -#: objects/ui_MainWindow.h:823 +#: objects/ui_MainWindow.h:929 msgid "Find and Replace..." msgstr "" -#: objects/ui_MainWindow.h:824 +#: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" msgstr "" -#: objects/ui_MainWindow.h:825 +#: objects/ui_MainWindow.h:931 msgid "Find Next" msgstr "" -#: objects/ui_MainWindow.h:826 +#: objects/ui_MainWindow.h:932 msgid "Ctrl+G" msgstr "" -#: objects/ui_MainWindow.h:827 +#: objects/ui_MainWindow.h:933 msgid "Find Previous" msgstr "" -#: objects/ui_MainWindow.h:828 +#: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" msgstr "" -#: objects/ui_MainWindow.h:829 +#: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" msgstr "" -#: objects/ui_MainWindow.h:830 +#: objects/ui_MainWindow.h:936 msgid "Ctrl+E" msgstr "" -#: objects/ui_MainWindow.h:831 +#: objects/ui_MainWindow.h:937 msgid "Flush Caches" msgstr "ОчиÑтить кÑш" -#: objects/ui_MainWindow.h:832 +#: objects/ui_MainWindow.h:938 msgid "OpenSCAD Homepage" msgstr "ДомашнÑÑ Ñтраница OpenSCAD" -#: objects/ui_MainWindow.h:833 +#: objects/ui_MainWindow.h:939 #, fuzzy msgid "Automatic Reload and Preview" msgstr "ÐвтоматичеÑки обновлÑÑ‚ÑŒ и комилировать" -#: objects/ui_MainWindow.h:834 +#: objects/ui_MainWindow.h:940 msgid "Export as Image..." msgstr "ЭкÑпортировать в раÑÑ‚Ñ€..." -#: objects/ui_MainWindow.h:835 +#: objects/ui_MainWindow.h:941 msgid "Export as CSG..." msgstr "ЭкÑпортировать в CSG..." -#: objects/ui_MainWindow.h:836 +#: objects/ui_MainWindow.h:942 msgid "Library info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ библиотеках" -#: objects/ui_MainWindow.h:837 +#: objects/ui_MainWindow.h:943 msgid "Show Library Folder..." msgstr "Открыть каталог библиотек..." -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "СброÑить наÑтройки вида" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:945 #, fuzzy msgid "Font List" msgstr "Шрифт" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:946 #, fuzzy msgid "Export as SVG..." msgstr "ЭкÑпортировать в CSG..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:947 #, fuzzy msgid "Export as AMF..." msgstr "ЭкÑпортировать в DXF..." -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:948 +msgid "Zoom In" +msgstr "Увеличить маÑштаб" + +#: objects/ui_MainWindow.h:949 msgid "Ctrl+]" msgstr "" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:950 +msgid "Zoom Out" +msgstr "Уменьшить маÑштаб" + +#: objects/ui_MainWindow.h:951 msgid "Ctrl+[" msgstr "" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:952 #, fuzzy msgid "View All" msgstr "&Вид" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" msgstr "" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:954 #, fuzzy msgid "Hide toolbars" msgstr "Скрыть редактор" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:955 +msgid "U&nindent" +msgstr "У&брать отÑтуп" + +#: objects/ui_MainWindow.h:956 +msgid "Ctrl+Shift+I" +msgstr "" + +#: objects/ui_MainWindow.h:957 +msgid "Cheat Sheet" +msgstr "" + +#: objects/ui_MainWindow.h:958 +msgid "Message" +msgstr "" + +#: objects/ui_MainWindow.h:961 msgid "Time:" msgstr "ВремÑ:" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:962 msgid "FPS:" msgstr "Кадров в Ñекунду:" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:963 msgid "Steps:" msgstr "Шагов:" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:964 msgid "Dump Pictures" msgstr "СохранÑÑ‚ÑŒ кадры" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:965 msgid "&File" msgstr "&Файл" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:966 #, fuzzy msgid "Recent Files" msgstr "Открыть файл" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:968 msgid "Export" msgstr "" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Правка" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:970 msgid "&Design" msgstr "&Модель" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:971 msgid "&View" msgstr "&Вид" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:972 msgid "&Help" msgstr "&Справка" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:975 msgid "Find" msgstr "" -#: objects/ui_MainWindow.h:864 objects/ui_MainWindow.h:871 +#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" msgstr "" -#: objects/ui_MainWindow.h:866 +#: objects/ui_MainWindow.h:978 msgid "Search string" msgstr "" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:979 msgid "<" msgstr "" -#: objects/ui_MainWindow.h:868 +#: objects/ui_MainWindow.h:980 msgid ">" msgstr "" -#: objects/ui_MainWindow.h:869 +#: objects/ui_MainWindow.h:981 msgid "Done" msgstr "" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:982 #, fuzzy msgid "Replacement string" msgstr "Ñлементах" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:984 msgid "All" msgstr "" @@ -694,137 +722,286 @@ msgstr "Включить Ð´Ð»Ñ OpenGL 1.x" msgid "Show this message again" msgstr "" -#: objects/ui_Preferences.h:609 +#: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Вид" -#: objects/ui_Preferences.h:610 src/UIUtils.cc:85 +#: objects/ui_Preferences.h:1063 src/UIUtils.cc:86 msgid "Advanced" msgstr "Дополнительные" -#: objects/ui_Preferences.h:611 src/mainwin.cc:2315 +#: objects/ui_Preferences.h:1064 src/mainwin.cc:2418 msgid "Editor" msgstr "Редактор" -#: objects/ui_Preferences.h:612 +#: objects/ui_Preferences.h:1065 msgid "Update" msgstr "ОбновлениÑ" -#: objects/ui_Preferences.h:613 objects/ui_Preferences.h:633 +#: objects/ui_Preferences.h:1066 objects/ui_Preferences.h:1147 msgid "Features" msgstr "Функции" -#: objects/ui_Preferences.h:615 +#: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" msgstr "" -#: objects/ui_Preferences.h:617 +#: objects/ui_Preferences.h:1070 msgid "Color scheme:" msgstr "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñхема:" -#: objects/ui_Preferences.h:618 +#: objects/ui_Preferences.h:1071 +msgid "Show Warnings and Errors in 3D View" +msgstr "" + +#: objects/ui_Preferences.h:1072 #, fuzzy msgid "Editor Type" msgstr "Редактор" -#: objects/ui_Preferences.h:621 +#: objects/ui_Preferences.h:1075 #, fuzzy msgid "Simple Editor" msgstr "Скрыть редактор" -#: objects/ui_Preferences.h:622 +#: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" msgstr "" -#: objects/ui_Preferences.h:624 +#: objects/ui_Preferences.h:1078 msgid "(requires restart)" msgstr "" -#: objects/ui_Preferences.h:625 +#: objects/ui_Preferences.h:1079 msgid "Font" msgstr "Шрифт" -#: objects/ui_Preferences.h:626 +#: objects/ui_Preferences.h:1080 msgid "Color syntax highlighting" msgstr "ПодÑветка ÑинтакÑиÑа" -#: objects/ui_Preferences.h:627 -msgid "Use Ctrl/Cmd-Mouse-wheel to zoom text" +#: objects/ui_Preferences.h:1081 +msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "" -#: objects/ui_Preferences.h:629 +#: objects/ui_Preferences.h:1082 +#, fuzzy +msgid "Indentation" +msgstr "ДокументациÑ" + +#: objects/ui_Preferences.h:1083 +#, fuzzy +msgid "Auto Indent" +msgstr "&Добавить отÑтуп" + +#: objects/ui_Preferences.h:1084 +#, fuzzy +msgid "Indent using" +msgstr "&Добавить отÑтуп" + +#: objects/ui_Preferences.h:1087 src/settings.cc:135 +#, fuzzy +msgid "Spaces" +msgstr "ПоверхноÑти CGAL" + +#: objects/ui_Preferences.h:1088 src/settings.cc:135 +msgid "Tabs" +msgstr "" + +#: objects/ui_Preferences.h:1090 +msgid "Indentation width" +msgstr "" + +#: objects/ui_Preferences.h:1091 +msgid "Tab width" +msgstr "" + +#: objects/ui_Preferences.h:1092 +msgid "Tab key function" +msgstr "" + +#: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 +#: src/settings.cc:136 +#, fuzzy +msgid "Indent" +msgstr "&Добавить отÑтуп" + +#: objects/ui_Preferences.h:1096 src/settings.cc:136 +msgid "Insert Tab" +msgstr "" + +#: objects/ui_Preferences.h:1098 +msgid "Show whitespace" +msgstr "" + +#: objects/ui_Preferences.h:1101 src/settings.cc:132 +msgid "Never" +msgstr "" + +#: objects/ui_Preferences.h:1102 src/settings.cc:132 +msgid "Always" +msgstr "" + +#: objects/ui_Preferences.h:1103 +msgid "Only after indentation" +msgstr "" + +#: objects/ui_Preferences.h:1105 +msgid "Size" +msgstr "" + +#: objects/ui_Preferences.h:1106 +#, fuzzy +msgid "Display" +msgstr "Показать &AST..." + +#: objects/ui_Preferences.h:1107 +msgid "Enable brace matching" +msgstr "" + +#: objects/ui_Preferences.h:1108 +msgid "Highlight current line" +msgstr "" + +#: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 +msgid "Line wrap" +msgstr "" + +#: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 +#: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 +#: src/settings.cc:131 +msgid "None" +msgstr "" + +#: objects/ui_Preferences.h:1113 src/settings.cc:127 +msgid "Wrap at character boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1114 src/settings.cc:127 +msgid "Wrap at word boundaries" +msgstr "" + +#: objects/ui_Preferences.h:1116 +msgid "Line wrap indentation" +msgstr "" + +#: objects/ui_Preferences.h:1117 +msgid "Line wrap visualization" +msgstr "" + +#: objects/ui_Preferences.h:1118 +msgid "Style" +msgstr "" + +#: objects/ui_Preferences.h:1121 src/settings.cc:128 +msgid "Fixed" +msgstr "" + +#: objects/ui_Preferences.h:1122 src/settings.cc:128 +msgid "Same" +msgstr "" + +#: objects/ui_Preferences.h:1123 src/settings.cc:128 +#, fuzzy +msgid "Indented" +msgstr "&Добавить отÑтуп" + +#: objects/ui_Preferences.h:1126 +msgid "Start" +msgstr "" + +#: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Text" +msgstr "" + +#: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Border" +msgstr "" + +#: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 +#: src/settings.cc:130 src/settings.cc:131 +msgid "Margin" +msgstr "" + +#: objects/ui_Preferences.h:1134 +msgid "End" +msgstr "" + +#: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" msgstr "ÐвтоматичеÑки проверÑÑ‚ÑŒ обновлениÑ" -#: objects/ui_Preferences.h:630 +#: objects/ui_Preferences.h:1144 msgid "Include development snapshots" msgstr "Ð’ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ€Ð°Ð±Ð¾Ñ‡Ð¸Ðµ Ñборки" -#: objects/ui_Preferences.h:631 +#: objects/ui_Preferences.h:1145 msgid "Check Now" msgstr "Проверить ÑейчаÑ" -#: objects/ui_Preferences.h:632 +#: objects/ui_Preferences.h:1146 msgid "Last checked: " msgstr "ПоÑледнÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: " -#: objects/ui_Preferences.h:634 +#: objects/ui_Preferences.h:1148 msgid "OpenCSG" msgstr "" -#: objects/ui_Preferences.h:635 +#: objects/ui_Preferences.h:1149 msgid "Show capability warning" msgstr "Показывать предупреждение о возможноÑÑ‚ÑÑ…" -#: objects/ui_Preferences.h:636 +#: objects/ui_Preferences.h:1150 msgid "Enable for OpenGL 1.x" msgstr "Включить Ð´Ð»Ñ OpenGL 1.x" -#: objects/ui_Preferences.h:637 +#: objects/ui_Preferences.h:1151 msgid "Turn off rendering at " msgstr "Отключать отриÑовку на " -#: objects/ui_Preferences.h:638 +#: objects/ui_Preferences.h:1152 msgid "elements" msgstr "Ñлементах" -#: objects/ui_Preferences.h:639 +#: objects/ui_Preferences.h:1153 msgid "Force Goldfeather" msgstr "Принудительно иÑпользовать алгоритм Goldfeather («Золотое перо»)" -#: objects/ui_Preferences.h:640 +#: objects/ui_Preferences.h:1154 msgid "CGAL Cache size" msgstr "Размер кÑша CGAL" -#: objects/ui_Preferences.h:641 objects/ui_Preferences.h:643 +#: objects/ui_Preferences.h:1155 objects/ui_Preferences.h:1157 msgid "bytes" msgstr "байт" -#: objects/ui_Preferences.h:642 +#: objects/ui_Preferences.h:1156 msgid "PolySet Cache size" msgstr "Размер кÑша PolySet" -#: objects/ui_Preferences.h:644 +#: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" msgstr "" -#: objects/ui_Preferences.h:645 +#: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" msgstr "" -#: objects/ui_Preferences.h:646 +#: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" msgstr "" -#: objects/ui_Preferences.h:647 +#: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" msgstr "" -#: objects/ui_Preferences.h:648 +#: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" -#: objects/ui_Preferences.h:649 +#: objects/ui_Preferences.h:1163 msgid "toolBar" msgstr "" @@ -836,119 +1013,152 @@ msgstr "" msgid "%v / %m" msgstr "" -#: src/mainwin.cc:768 src/mainwin.cc:1300 +#: src/Camera.cc:126 +#, c-format +msgid "" +"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " +"distance = %.2f" +msgstr "" + +#: src/mainwin.cc:778 src/mainwin.cc:1354 msgid "Untitled.scad" msgstr "БезымÑнный.scad" -#: src/mainwin.cc:1299 +#: src/mainwin.cc:971 +#, fuzzy +msgid "Compile error." +msgstr "&Компилировать" + +#: src/mainwin.cc:974 +msgid "Error while compiling '%1'." +msgstr "" + +#: src/mainwin.cc:978 +msgid "Compilation generated %1 warning." +msgid_plural "Compilation generated %1 warnings." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: src/mainwin.cc:988 +msgid " For details see console window." +msgstr "" + +#: src/mainwin.cc:1353 msgid "Save File" msgstr "Сохранить файл" -#: src/mainwin.cc:1301 +#: src/mainwin.cc:1355 msgid "OpenSCAD Designs (*.scad)" msgstr "Модели OpenSCAD (*.scad)" -#: src/mainwin.cc:1311 +#: src/mainwin.cc:1365 msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" -#: src/mainwin.cc:1630 +#: src/mainwin.cc:1684 msgid "Application" msgstr "" -#: src/mainwin.cc:1631 +#: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" -#: src/mainwin.cc:1942 src/mainwin.cc:1999 +#: src/mainwin.cc:2038 src/mainwin.cc:2094 #, fuzzy msgid "Export %1 File" msgstr "ЭкÑпортировать в DXF..." -#: src/mainwin.cc:1943 src/mainwin.cc:2003 +#: src/mainwin.cc:2039 src/mainwin.cc:2098 msgid "%1 Files (*%2)" msgstr "" -#: src/mainwin.cc:1944 +#: src/mainwin.cc:2040 #, fuzzy msgid "Untitled" msgstr "БезымÑнный.scad" -#: src/mainwin.cc:2001 +#: src/mainwin.cc:2096 #, fuzzy msgid "Untitled%1" msgstr "БезымÑнный.scad" -#: src/mainwin.cc:2052 +#: src/mainwin.cc:2147 msgid "Export CSG File" msgstr "" -#: src/mainwin.cc:2053 +#: src/mainwin.cc:2148 msgid "Untitled.csg" msgstr "" -#: src/mainwin.cc:2054 +#: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "Export Image" msgstr "" -#: src/mainwin.cc:2080 +#: src/mainwin.cc:2175 msgid "PNG Files (*.png)" msgstr "" -#: src/mainwin.cc:2320 +#: src/mainwin.cc:2423 msgid "Console" msgstr "" -#: src/mainwin.cc:2447 +#: src/mainwin.cc:2560 #, fuzzy msgid "The document has been modified." msgstr "" "Документ был изменен.\n" "Сохранить изменениÑ?" -#: src/mainwin.cc:2448 +#: src/mainwin.cc:2561 #, fuzzy msgid "Do you want to save your changes?" msgstr "" "Документ был изменен.\n" "Сохранить изменениÑ?" -#: src/QGLView.cc:114 +#: src/openscad.cc:604 +msgid "" +"Fontconfig needs to update its font cache.\n" +"This can take up to a couple of minutes." +msgstr "" + +#: src/QGLView.cc:111 msgid "" "\n" "Using QGLWidget\n" "\n" msgstr "" -#: src/QGLView.cc:131 +#: src/QGLView.cc:128 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" -#: src/QGLView.cc:134 +#: src/QGLView.cc:131 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" -#: src/QGLView.cc:137 +#: src/QGLView.cc:134 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" -#: src/QGLView.cc:141 +#: src/QGLView.cc:138 #, c-format msgid "" "GLEW version %s\n" @@ -956,22 +1166,19 @@ msgid "" "OpenGL version %s\n" msgstr "" -#: src/QGLView.cc:171 -#, c-format -msgid "" -"Viewport: translate = [ %.2f %.2f %.2f ], rotate = [ %.2f %.2f %.2f ], " -"distance = %.2f" +#: src/settings.cc:132 +msgid "After indentation" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Basics" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Shapes" msgstr "" -#: src/UIUtils.cc:85 +#: src/UIUtils.cc:86 msgid "Extrusion" msgstr "" @@ -990,9 +1197,6 @@ msgstr "" #~ msgid "OpenSCAD Designs (*.scad *.csg)" #~ msgstr "Модели OpenSCAD (*.scad *.csg)" -#~ msgid "&Compile" -#~ msgstr "&Компилировать" - #~ msgid "Compile and &Render (CGAL)" #~ msgstr "Компилировать и &отриÑовать (CGAL)" From 4ba92ece615614825eecb134ac20a22954df33f1 Mon Sep 17 00:00:00 2001 From: NeoTheFox Date: Sat, 24 Jan 2015 23:32:06 +0300 Subject: [PATCH 123/174] Update ru.po Translated most of recent changes --- locale/ru.po | 261 ++++++++++++++++++++++++++++----------------------- 1 file changed, 142 insertions(+), 119 deletions(-) diff --git a/locale/ru.po b/locale/ru.po index 80617612..b60383c8 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2013-02-24 17:50+0100\n" -"Last-Translator: \n" +"Last-Translator: \n" "Language-Team: Russian\n" "Language: ru\n" "MIME-Version: 1.0\n" @@ -38,7 +38,7 @@ msgstr "" #: objects/ui_AboutDialog.h:112 msgid "OK" -msgstr "" +msgstr "ОК" #: objects/ui_FontListDialog.h:105 #, fuzzy @@ -47,15 +47,15 @@ msgstr "Шрифт" #: objects/ui_FontListDialog.h:106 objects/ui_LibraryInfoDialog.h:77 msgid "&OK" -msgstr "" +msgstr "&ОК" #: objects/ui_FontListDialog.h:107 msgid "Copy to Clipboard" -msgstr "" +msgstr "Скопировать в буфер" #: objects/ui_FontListDialog.h:108 msgid "Filter:" -msgstr "" +msgstr "Фильтр:" #: objects/ui_FontListDialog.h:109 msgid "" @@ -111,15 +111,15 @@ msgstr "Примеры" #: objects/ui_launchingscreen.h:312 msgid "Don't show again" -msgstr "" +msgstr "Ðе показывать Ñнова" #: objects/ui_launchingscreen.h:313 msgid "Version" -msgstr "" +msgstr "ВерÑиÑ" #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" -msgstr "" +msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñборке" #: objects/ui_LibraryInfoDialog.h:76 msgid "OpenSCAD Detailed Library and Build Information" @@ -131,7 +131,7 @@ msgstr "&Создать" #: objects/ui_MainWindow.h:839 msgid "Ctrl+N" -msgstr "" +msgstr "Ctrl+N" #: objects/ui_MainWindow.h:840 msgid "&Open..." @@ -139,7 +139,7 @@ msgstr "&Открыть..." #: objects/ui_MainWindow.h:841 msgid "Ctrl+O" -msgstr "" +msgstr "Ctrl+O" #: objects/ui_MainWindow.h:842 msgid "&Save" @@ -147,7 +147,7 @@ msgstr "&Сохранить" #: objects/ui_MainWindow.h:843 msgid "Ctrl+S" -msgstr "" +msgstr "Ctrl+S" #: objects/ui_MainWindow.h:844 msgid "Save &As..." @@ -155,7 +155,7 @@ msgstr "Сохранить &как..." #: objects/ui_MainWindow.h:845 msgid "Ctrl+Shift+S" -msgstr "" +msgstr "Ctrl+Shift+S" #: objects/ui_MainWindow.h:846 msgid "&Reload" @@ -163,7 +163,7 @@ msgstr "&Обновить" #: objects/ui_MainWindow.h:847 msgid "Ctrl+R" -msgstr "" +msgstr "Ctrl+R" #: objects/ui_MainWindow.h:848 msgid "&Quit" @@ -171,7 +171,7 @@ msgstr "&Выход" #: objects/ui_MainWindow.h:849 msgid "Ctrl+Q" -msgstr "" +msgstr "Ctrl+Q" #: objects/ui_MainWindow.h:850 msgid "&Undo" @@ -179,7 +179,7 @@ msgstr "&Отменить" #: objects/ui_MainWindow.h:851 msgid "Ctrl+Z" -msgstr "" +msgstr "Ctrl+Z" #: objects/ui_MainWindow.h:852 msgid "&Redo" @@ -187,7 +187,7 @@ msgstr "&Повторить" #: objects/ui_MainWindow.h:853 msgid "Ctrl+Shift+Z" -msgstr "" +msgstr "Ctrl+Shift+Z" #: objects/ui_MainWindow.h:854 msgid "Cu&t" @@ -195,7 +195,7 @@ msgstr "Ð’Ñ‹&резать" #: objects/ui_MainWindow.h:855 msgid "Ctrl+X" -msgstr "" +msgstr "Ctrl+X" #: objects/ui_MainWindow.h:856 msgid "&Copy" @@ -203,7 +203,7 @@ msgstr "&Копировать" #: objects/ui_MainWindow.h:857 msgid "Ctrl+C" -msgstr "" +msgstr "Ctrl+C" #: objects/ui_MainWindow.h:858 msgid "&Paste" @@ -211,7 +211,7 @@ msgstr "&Ð’Ñтавить" #: objects/ui_MainWindow.h:859 msgid "Ctrl+V" -msgstr "" +msgstr "Ctrl+V" #: objects/ui_MainWindow.h:860 msgid "&Indent" @@ -219,7 +219,7 @@ msgstr "&Добавить отÑтуп" #: objects/ui_MainWindow.h:861 msgid "Ctrl+I" -msgstr "" +msgstr "Ctrl+I" #: objects/ui_MainWindow.h:862 msgid "C&omment" @@ -227,7 +227,7 @@ msgstr "Зако&мментировать" #: objects/ui_MainWindow.h:863 msgid "Ctrl+D" -msgstr "" +msgstr "Ctrl+D" #: objects/ui_MainWindow.h:864 msgid "Unco&mment" @@ -235,7 +235,7 @@ msgstr "Р&аÑкомментировать" #: objects/ui_MainWindow.h:865 msgid "Ctrl+Shift+D" -msgstr "" +msgstr "Ctrl+Shift+D" #: objects/ui_MainWindow.h:866 msgid "Paste viewport translation" @@ -243,7 +243,7 @@ msgstr "Ð’Ñтавить Ñмещение точки обзора" #: objects/ui_MainWindow.h:867 msgid "Ctrl+T" -msgstr "" +msgstr "Ctrl+T" #: objects/ui_MainWindow.h:868 msgid "Paste viewport rotation" @@ -251,19 +251,19 @@ msgstr "Ð’Ñтавить поворот точки обзора" #: objects/ui_MainWindow.h:869 msgid "Increase Font Size" -msgstr "" +msgstr "Увеличить размер шрифта" #: objects/ui_MainWindow.h:870 msgid "Ctrl++" -msgstr "" +msgstr "Ctrl++" #: objects/ui_MainWindow.h:871 msgid "Decrease Font Size" -msgstr "" +msgstr "Уменьшить размер шрифта" #: objects/ui_MainWindow.h:872 msgid "Ctrl+-" -msgstr "" +msgstr "Ctrl+-" #: objects/ui_MainWindow.h:873 msgid "Hide editor" @@ -276,27 +276,30 @@ msgstr "&Обновить и компилировать" #: objects/ui_MainWindow.h:875 msgid "F4" -msgstr "" +msgstr "F4" #: objects/ui_MainWindow.h:876 +#, fuzzy msgid "&Preview" -msgstr "" +msgstr "&Превью" #: objects/ui_MainWindow.h:877 msgid "F5" -msgstr "" +msgstr "F5" #: objects/ui_MainWindow.h:878 +#, fuzzy msgid "&Render" -msgstr "" +msgstr "&Рендер" #: objects/ui_MainWindow.h:879 msgid "F6" -msgstr "" +msgstr "F6" #: objects/ui_MainWindow.h:880 +#, fuzzy msgid "Check Validity" -msgstr "" +msgstr "Проверить" #: objects/ui_MainWindow.h:881 msgid "Display &AST..." @@ -320,11 +323,11 @@ msgstr "ЭкÑпортировать в &OFF..." #: objects/ui_MainWindow.h:886 msgid "Preview" -msgstr "" +msgstr "Превью" #: objects/ui_MainWindow.h:887 msgid "F9" -msgstr "" +msgstr "F9" #: objects/ui_MainWindow.h:888 #, fuzzy @@ -333,7 +336,7 @@ msgstr "ПоверхноÑти CGAL" #: objects/ui_MainWindow.h:889 msgid "F10" -msgstr "" +msgstr "F10" #: objects/ui_MainWindow.h:890 msgid "Wireframe" @@ -341,7 +344,7 @@ msgstr "" #: objects/ui_MainWindow.h:891 msgid "F11" -msgstr "" +msgstr "F11" #: objects/ui_MainWindow.h:892 msgid "Thrown Together" @@ -349,7 +352,7 @@ msgstr "Ð’ÑÑ‘ вмеÑте" #: objects/ui_MainWindow.h:893 msgid "F12" -msgstr "" +msgstr "F12" #: objects/ui_MainWindow.h:894 msgid "Show Edges" @@ -357,7 +360,7 @@ msgstr "Показывать рёбра" #: objects/ui_MainWindow.h:895 msgid "Ctrl+1" -msgstr "" +msgstr "Ctrl+1" #: objects/ui_MainWindow.h:896 msgid "Show Axes" @@ -365,7 +368,7 @@ msgstr "Показывать оÑи" #: objects/ui_MainWindow.h:897 msgid "Ctrl+2" -msgstr "" +msgstr "Ctrl+2" #: objects/ui_MainWindow.h:898 msgid "Show Crosshairs" @@ -373,11 +376,12 @@ msgstr "Показывать перекреÑтиÑ" #: objects/ui_MainWindow.h:899 msgid "Ctrl+3" -msgstr "" +msgstr "Ctrl+3" #: objects/ui_MainWindow.h:900 +#, fuzzy msgid "Show Scale Markers" -msgstr "" +msgstr "Показать метки маÑштаба" #: objects/ui_MainWindow.h:901 msgid "Animate" @@ -389,7 +393,7 @@ msgstr "Сверху" #: objects/ui_MainWindow.h:903 msgid "Ctrl+4" -msgstr "" +msgstr "Ctrl+4" #: objects/ui_MainWindow.h:904 msgid "Bottom" @@ -397,7 +401,7 @@ msgstr "Снизу" #: objects/ui_MainWindow.h:905 msgid "Ctrl+5" -msgstr "" +msgstr "Ctrl+5" #: objects/ui_MainWindow.h:906 msgid "Left" @@ -405,7 +409,7 @@ msgstr "Слева" #: objects/ui_MainWindow.h:907 msgid "Ctrl+6" -msgstr "" +msgstr "Ctrl+6" #: objects/ui_MainWindow.h:908 msgid "Right" @@ -413,7 +417,7 @@ msgstr "Справа" #: objects/ui_MainWindow.h:909 msgid "Ctrl+7" -msgstr "" +msgstr "Ctrl+7" #: objects/ui_MainWindow.h:910 msgid "Front" @@ -421,7 +425,7 @@ msgstr "Спереди" #: objects/ui_MainWindow.h:911 msgid "Ctrl+8" -msgstr "" +msgstr "Ctrl+8" #: objects/ui_MainWindow.h:912 msgid "Back" @@ -429,7 +433,7 @@ msgstr "Сзади" #: objects/ui_MainWindow.h:913 msgid "Ctrl+9" -msgstr "" +msgstr "Ctrl+9" #: objects/ui_MainWindow.h:914 msgid "Diagonal" @@ -437,7 +441,7 @@ msgstr "ÐкÑонометричеÑкий" #: objects/ui_MainWindow.h:915 msgid "Ctrl+0" -msgstr "" +msgstr "Ctrl+0" #: objects/ui_MainWindow.h:916 msgid "Center" @@ -477,7 +481,7 @@ msgstr "Закрыть" #: objects/ui_MainWindow.h:925 msgid "Ctrl+W" -msgstr "" +msgstr "Ctrl+W" #: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 msgid "Preferences" @@ -485,43 +489,43 @@ msgstr "ÐаÑтройки" #: objects/ui_MainWindow.h:927 msgid "Find..." -msgstr "" +msgstr "Ðайти..." #: objects/ui_MainWindow.h:928 msgid "Ctrl+F" -msgstr "" +msgstr "Ctrl+F" #: objects/ui_MainWindow.h:929 msgid "Find and Replace..." -msgstr "" +msgstr "Ðайти и замена..." #: objects/ui_MainWindow.h:930 msgid "Ctrl+Alt+F" -msgstr "" +msgstr "Ctrl+Alt+F" #: objects/ui_MainWindow.h:931 msgid "Find Next" -msgstr "" +msgstr "ИÑкать дальше" #: objects/ui_MainWindow.h:932 msgid "Ctrl+G" -msgstr "" +msgstr "Ctrl+G" #: objects/ui_MainWindow.h:933 msgid "Find Previous" -msgstr "" +msgstr "ИÑкать раньше" #: objects/ui_MainWindow.h:934 msgid "Ctrl+Shift+G" -msgstr "" +msgstr "Ctrl+Shift+G" #: objects/ui_MainWindow.h:935 msgid "Use Selection for Find" -msgstr "" +msgstr "Ðайти выделенный текÑÑ‚" #: objects/ui_MainWindow.h:936 msgid "Ctrl+E" -msgstr "" +msgstr "Ctrl+E" #: objects/ui_MainWindow.h:937 msgid "Flush Caches" @@ -577,7 +581,7 @@ msgstr "Увеличить маÑштаб" #: objects/ui_MainWindow.h:949 msgid "Ctrl+]" -msgstr "" +msgstr "Ctrl+]" #: objects/ui_MainWindow.h:950 msgid "Zoom Out" @@ -585,7 +589,7 @@ msgstr "Уменьшить маÑштаб" #: objects/ui_MainWindow.h:951 msgid "Ctrl+[" -msgstr "" +msgstr "Ctrl+[" #: objects/ui_MainWindow.h:952 #, fuzzy @@ -594,12 +598,12 @@ msgstr "&Вид" #: objects/ui_MainWindow.h:953 msgid "Convert Tabs to Spaces" -msgstr "" +msgstr "Преобразовать табулÑции в пробелы" #: objects/ui_MainWindow.h:954 #, fuzzy msgid "Hide toolbars" -msgstr "Скрыть редактор" +msgstr "Скрыть панель" #: objects/ui_MainWindow.h:955 msgid "U&nindent" @@ -607,15 +611,16 @@ msgstr "У&брать отÑтуп" #: objects/ui_MainWindow.h:956 msgid "Ctrl+Shift+I" -msgstr "" +msgstr "Ctrl+Shift+I" #: objects/ui_MainWindow.h:957 +#, fuzzy msgid "Cheat Sheet" -msgstr "" +msgstr "Указатель" #: objects/ui_MainWindow.h:958 msgid "Message" -msgstr "" +msgstr "Сообщение" #: objects/ui_MainWindow.h:961 msgid "Time:" @@ -644,7 +649,7 @@ msgstr "Открыть файл" #: objects/ui_MainWindow.h:968 msgid "Export" -msgstr "" +msgstr "ЭкÑпорт" #: objects/ui_MainWindow.h:969 msgid "&Edit" @@ -664,27 +669,27 @@ msgstr "&Справка" #: objects/ui_MainWindow.h:975 msgid "Find" -msgstr "" +msgstr "Ðайти" #: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 msgid "Replace" -msgstr "" +msgstr "Заменить" #: objects/ui_MainWindow.h:978 msgid "Search string" -msgstr "" +msgstr "Строка поиÑка" #: objects/ui_MainWindow.h:979 msgid "<" -msgstr "" +msgstr "<" #: objects/ui_MainWindow.h:980 msgid ">" -msgstr "" +msgstr ">" #: objects/ui_MainWindow.h:981 msgid "Done" -msgstr "" +msgstr "Готово" #: objects/ui_MainWindow.h:982 #, fuzzy @@ -693,7 +698,7 @@ msgstr "Ñлементах" #: objects/ui_MainWindow.h:984 msgid "All" -msgstr "" +msgstr "Ð’Ñе" #: objects/ui_OpenCSGWarningDialog.h:86 msgid "OpenGL Warning" @@ -744,7 +749,7 @@ msgstr "Функции" #: objects/ui_Preferences.h:1068 msgid "Enable/Disable experimental features" -msgstr "" +msgstr "Включить/Выключить ÑкÑпериментальные возможноÑти" #: objects/ui_Preferences.h:1070 msgid "Color scheme:" @@ -752,7 +757,7 @@ msgstr "Ð¦Ð²ÐµÑ‚Ð¾Ð²Ð°Ñ Ñхема:" #: objects/ui_Preferences.h:1071 msgid "Show Warnings and Errors in 3D View" -msgstr "" +msgstr "Показывать ошибки и Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð² 3D виде" #: objects/ui_Preferences.h:1072 #, fuzzy @@ -762,7 +767,7 @@ msgstr "Редактор" #: objects/ui_Preferences.h:1075 #, fuzzy msgid "Simple Editor" -msgstr "Скрыть редактор" +msgstr "ПроÑтой редактор" #: objects/ui_Preferences.h:1076 msgid "QScintilla Editor" @@ -770,7 +775,7 @@ msgstr "" #: objects/ui_Preferences.h:1078 msgid "(requires restart)" -msgstr "" +msgstr "(требуетÑÑ Ð¿ÐµÑ€ÐµÐ·Ð°Ð¿ÑƒÑк)" #: objects/ui_Preferences.h:1079 msgid "Font" @@ -782,7 +787,7 @@ msgstr "ПодÑветка ÑинтакÑиÑа" #: objects/ui_Preferences.h:1081 msgid "Ctrl/Cmd-Mouse-wheel zooms text" -msgstr "" +msgstr "Ctrl/Cmd-КолеÑико-мыши увеличивает текÑÑ‚" #: objects/ui_Preferences.h:1082 #, fuzzy @@ -810,15 +815,15 @@ msgstr "" #: objects/ui_Preferences.h:1090 msgid "Indentation width" -msgstr "" +msgstr "Ширина отÑтупа" #: objects/ui_Preferences.h:1091 msgid "Tab width" -msgstr "" +msgstr "Ширина табулÑции" #: objects/ui_Preferences.h:1092 msgid "Tab key function" -msgstr "" +msgstr "Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ¸ Tab" #: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 #: src/settings.cc:136 @@ -828,27 +833,27 @@ msgstr "&Добавить отÑтуп" #: objects/ui_Preferences.h:1096 src/settings.cc:136 msgid "Insert Tab" -msgstr "" +msgstr "Ð’Ñтавить Tab" #: objects/ui_Preferences.h:1098 msgid "Show whitespace" -msgstr "" +msgstr "Показать пробел" #: objects/ui_Preferences.h:1101 src/settings.cc:132 msgid "Never" -msgstr "" +msgstr "Ðикогда" #: objects/ui_Preferences.h:1102 src/settings.cc:132 msgid "Always" -msgstr "" +msgstr "Ð’Ñегда" #: objects/ui_Preferences.h:1103 msgid "Only after indentation" -msgstr "" +msgstr "Только поÑле отÑтупа" #: objects/ui_Preferences.h:1105 msgid "Size" -msgstr "" +msgstr "Размер" #: objects/ui_Preferences.h:1106 #, fuzzy @@ -856,12 +861,13 @@ msgid "Display" msgstr "Показать &AST..." #: objects/ui_Preferences.h:1107 +#, fuzzy msgid "Enable brace matching" -msgstr "" +msgstr "Вклчить автозакрытие Ñкобок" #: objects/ui_Preferences.h:1108 msgid "Highlight current line" -msgstr "" +msgstr "Выделить текущую Ñтрочку" #: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 msgid "Line wrap" @@ -870,8 +876,9 @@ msgstr "" #: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 #: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 #: src/settings.cc:131 +#, fuzzy msgid "None" -msgstr "" +msgstr "Ðет" #: objects/ui_Preferences.h:1113 src/settings.cc:127 msgid "Wrap at character boundaries" @@ -891,15 +898,16 @@ msgstr "" #: objects/ui_Preferences.h:1118 msgid "Style" -msgstr "" +msgstr "Стиль" #: objects/ui_Preferences.h:1121 src/settings.cc:128 msgid "Fixed" -msgstr "" +msgstr "ФикÑированный" #: objects/ui_Preferences.h:1122 src/settings.cc:128 msgid "Same" -msgstr "" +#, fuzzy +msgstr "Так же" #: objects/ui_Preferences.h:1123 src/settings.cc:128 #, fuzzy @@ -907,18 +915,19 @@ msgid "Indented" msgstr "&Добавить отÑтуп" #: objects/ui_Preferences.h:1126 +#, fuzzy msgid "Start" -msgstr "" +msgstr "Ðачало" #: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 #: src/settings.cc:130 src/settings.cc:131 msgid "Text" -msgstr "" +msgstr "ТекÑÑ‚" #: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 #: src/settings.cc:130 src/settings.cc:131 msgid "Border" -msgstr "" +msgstr "Граница" #: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 #: src/settings.cc:130 src/settings.cc:131 @@ -927,7 +936,7 @@ msgstr "" #: objects/ui_Preferences.h:1134 msgid "End" -msgstr "" +msgstr "Конец" #: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" @@ -947,7 +956,7 @@ msgstr "ПоÑледнÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ°: " #: objects/ui_Preferences.h:1148 msgid "OpenCSG" -msgstr "" +msgstr "OpenCSG" #: objects/ui_Preferences.h:1149 msgid "Show capability warning" @@ -983,27 +992,27 @@ msgstr "Размер кÑша PolySet" #: objects/ui_Preferences.h:1158 msgid "Allow to open multiple documents" -msgstr "" +msgstr "Разрешить открытие неÑкольких документов" #: objects/ui_Preferences.h:1159 msgid "Enable docking of Editor and Console in different places" -msgstr "" +msgstr "Включить прилипание Редактора и КонÑоли в разных меÑтах" #: objects/ui_Preferences.h:1160 msgid "Enable undocking of Editor and Console to separate windows" -msgstr "" +msgstr "Включить перетаÑкивание Редактора и КонÑоли в разные окна" #: objects/ui_Preferences.h:1161 msgid "Show Welcome Screen" -msgstr "" +msgstr "Показать Ñкран преветÑтвиÑ" #: objects/ui_Preferences.h:1162 msgid "Enable user interface localization (requires restart of OpenSCAD)" -msgstr "" +msgstr "Включить локализацию интерфейÑа (необходимо перезапуÑтить OpenSCAD)" #: objects/ui_Preferences.h:1163 msgid "toolBar" -msgstr "" +msgstr "Панель инÑтрументов" #: objects/ui_ProgressWidget.h:72 msgid "Form" @@ -1031,7 +1040,7 @@ msgstr "&Компилировать" #: src/mainwin.cc:974 msgid "Error while compiling '%1'." -msgstr "" +msgstr "Ошибка во Ð²Ñ€ÐµÐ¼Ñ ÐºÐ¾Ð¼Ð¿Ð¸Ð»Ñции '%1'." #: src/mainwin.cc:978 msgid "Compilation generated %1 warning." @@ -1042,7 +1051,7 @@ msgstr[2] "" #: src/mainwin.cc:988 msgid " For details see console window." -msgstr "" +msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ñтей Ñмотреть окно конÑоли." #: src/mainwin.cc:1353 msgid "Save File" @@ -1057,16 +1066,20 @@ msgid "" "%1 already exists.\n" "Do you want to replace it?" msgstr "" +"%1 уже ÑущеÑтвует.\n" +"ПерезапиÑать?" #: src/mainwin.cc:1684 msgid "Application" -msgstr "" +msgstr "Приложение" #: src/mainwin.cc:1685 msgid "" "The document has been modified.\n" "Do you really want to reload the file?" msgstr "" +"Документ был изменен.\n" +"Хотите перезагрузить документ?" #: src/mainwin.cc:2038 src/mainwin.cc:2094 #, fuzzy @@ -1089,27 +1102,27 @@ msgstr "БезымÑнный.scad" #: src/mainwin.cc:2147 msgid "Export CSG File" -msgstr "" +msgstr "ЭкÑпортировать файл CSG" #: src/mainwin.cc:2148 msgid "Untitled.csg" -msgstr "" +msgstr "БезимÑнный.csg" #: src/mainwin.cc:2149 msgid "CSG Files (*.csg)" -msgstr "" +msgstr "Файлы CSG (*.csg)" #: src/mainwin.cc:2175 msgid "Export Image" -msgstr "" +msgstr "ЭкÑпортировать изображение" #: src/mainwin.cc:2175 msgid "PNG Files (*.png)" -msgstr "" +msgstr "Файлы PNG (*.png)" #: src/mainwin.cc:2423 msgid "Console" -msgstr "" +msgstr "КонÑоль" #: src/mainwin.cc:2560 #, fuzzy @@ -1130,6 +1143,8 @@ msgid "" "Fontconfig needs to update its font cache.\n" "This can take up to a couple of minutes." msgstr "" +"Fontconfig требуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ кеш шрифтов.\n" +"Это может занÑÑ‚ÑŒ пару минут." #: src/QGLView.cc:111 msgid "" @@ -1143,6 +1158,8 @@ msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" +"Предупреждение: Возможны ошибки рендринга OpenCSG.\n" +"\n" #: src/QGLView.cc:131 msgid "" @@ -1150,6 +1167,9 @@ msgid "" "disabled.\n" "\n" msgstr "" +"Предупреждение: Ðе найдены OpenGL раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð´Ð»Ñ OpenCSG - OpenCSG " +"был отключен.\n" +"\n" #: src/QGLView.cc:134 msgid "" @@ -1157,6 +1177,9 @@ msgid "" "later.\n" "Your renderer information is as follows:\n" msgstr "" +"Крайне рекомендуетÑÑ Ð¸Ñпользовать OpenSCAD на ÑиÑтеме Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ " +" OpenGL 2.0 или новее.\n" +"Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ рендере:\n" #: src/QGLView.cc:138 #, c-format @@ -1168,19 +1191,19 @@ msgstr "" #: src/settings.cc:132 msgid "After indentation" -msgstr "" +msgstr "ПоÑле отÑтупа" #: src/UIUtils.cc:86 msgid "Basics" -msgstr "" +msgstr "Примитивы" #: src/UIUtils.cc:86 msgid "Shapes" -msgstr "" +msgstr "Формы" #: src/UIUtils.cc:86 msgid "Extrusion" -msgstr "" +msgstr "Выдавливание" #~ msgid "Check for Update.." #~ msgstr "Проверить обновлениÑ..." From 4a3245056bfdd423f979a3e2ac5afb6c745fe6b4 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sat, 24 Jan 2015 23:51:07 -0500 Subject: [PATCH 124/174] Cosmetics --- releases/2015.02.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/releases/2015.02.md b/releases/2015.02.md index c8e9a87f..2904cd18 100644 --- a/releases/2015.02.md +++ b/releases/2015.02.md @@ -1,10 +1,10 @@ **Language Features:** -* surface() can now take PNG images as input -* List comprehensions, let() * text() module * offset() -* min() and max() can now take a wvector argument +* List comprehensions, let() * concat() +* surface() can now take PNG images as input +* min() and max() can now take a vector argument * 2D minkowski and holes * chr() @@ -19,19 +19,19 @@ * Improved editor * Splash screen * Docking of GUI components -* Toolbar +* Toolbars * More robust STL export **Bugfixes/improvements:** * Internal cavity fix * Performance: 2D (clipper), preview, hull, minkowski, surface, n-ary-union, transforms (polyset) * Performance: Reduce duplicate evaluation of identical expressions -* STL export/import fixes +* STL export/import stability fixes * F6 stability fixes * Better recursion behavior * Reorganized examples a bit * improved search() behavior -* Mac: Timestamps is output fixed +* Mac: Timestamps in output fixed **Deprecations:** * polyhedron triangles From 4c26959cf2b2c4a77007b9573bec6d92fb638eea Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 25 Jan 2015 01:49:36 -0500 Subject: [PATCH 125/174] #1174 Added testcase --- testdata/scad/3D/features/mirror-tests.scad | 1 + tests/CMakeLists.txt | 1 + .../cgalpngtest/mirror-tests-expected.png | Bin 0 -> 7079 bytes .../dumptest/mirror-tests-expected.csg | 7 +++++++ .../monotonepngtest/mirror-tests-expected.png | Bin 0 -> 7079 bytes .../opencsgtest/mirror-tests-expected.png | Bin 0 -> 7349 bytes .../throwntogethertest/mirror-tests-expected.png | Bin 0 -> 7349 bytes 7 files changed, 9 insertions(+) create mode 100644 testdata/scad/3D/features/mirror-tests.scad create mode 100644 tests/regression/cgalpngtest/mirror-tests-expected.png create mode 100644 tests/regression/dumptest/mirror-tests-expected.csg create mode 100644 tests/regression/monotonepngtest/mirror-tests-expected.png create mode 100644 tests/regression/opencsgtest/mirror-tests-expected.png create mode 100644 tests/regression/throwntogethertest/mirror-tests-expected.png diff --git a/testdata/scad/3D/features/mirror-tests.scad b/testdata/scad/3D/features/mirror-tests.scad new file mode 100644 index 00000000..93f064bc --- /dev/null +++ b/testdata/scad/3D/features/mirror-tests.scad @@ -0,0 +1 @@ +render() mirror([1,0,0]) cube(); \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5d9bbbbf..864be15b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1122,6 +1122,7 @@ list(APPEND EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/polyhedron-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/rotate_extrude-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/union-coincident-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/3D/features/mirror-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/null-polygons.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/internal-cavity.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/internal-cavity-polyhedron.scad diff --git a/tests/regression/cgalpngtest/mirror-tests-expected.png b/tests/regression/cgalpngtest/mirror-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..677d52ca8bc001554d27e59b4decd40abbad783a GIT binary patch literal 7079 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 XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 0 HcmV?d00001 diff --git a/tests/regression/dumptest/mirror-tests-expected.csg b/tests/regression/dumptest/mirror-tests-expected.csg new file mode 100644 index 00000000..3af81c1a --- /dev/null +++ b/tests/regression/dumptest/mirror-tests-expected.csg @@ -0,0 +1,7 @@ +group() { + render(convexity = 1) { + multmatrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cube(size = [1, 1, 1], center = false); + } + } +} diff --git a/tests/regression/monotonepngtest/mirror-tests-expected.png b/tests/regression/monotonepngtest/mirror-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..677d52ca8bc001554d27e59b4decd40abbad783a GIT binary patch literal 7079 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 XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/mirror-tests-expected.png b/tests/regression/opencsgtest/mirror-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..989385eeab098d42872e7f5bb7cc356639c5261c GIT binary patch literal 7349 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 literal 0 HcmV?d00001 diff --git a/tests/regression/throwntogethertest/mirror-tests-expected.png b/tests/regression/throwntogethertest/mirror-tests-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..989385eeab098d42872e7f5bb7cc356639c5261c GIT binary patch literal 7349 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 literal 0 HcmV?d00001 From d6f0b7dc50d6a1c69a00f0090f86704d75404862 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 25 Jan 2015 01:53:04 -0500 Subject: [PATCH 126/174] Flip faces when transforming using a mirroring transform. Fixes #1174 --- src/polyset.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/polyset.cc b/src/polyset.cc index a8a08a2b..1ed10999 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -146,10 +146,14 @@ void PolySet::append(const PolySet &ps) void PolySet::transform(const Transform3d &mat) { + // If mirroring transform, flip faces to avoid the object to end up being inside-out + bool mirrored = mat.matrix().determinant() < 0; + BOOST_FOREACH(Polygon &p, this->polygons) { BOOST_FOREACH(Vector3d &v, p) { v = mat * v; } + if (mirrored) std::reverse(p.begin(), p.end()); } } From c7558542514dea0681bb33c56b76d567cc2f30e7 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 25 Jan 2015 01:55:46 -0500 Subject: [PATCH 127/174] Don't translate messages going to the Library Info dialog --- src/QGLView.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/QGLView.cc b/src/QGLView.cc index 372e0e16..9c23cb96 100644 --- a/src/QGLView.cc +++ b/src/QGLView.cc @@ -108,7 +108,8 @@ std::string QGLView::getRendererInfo() const { std::string glewinfo = glew_dump(); std::string glextlist = glew_extensions_dump(); - return glewinfo + std::string(_("\nUsing QGLWidget\n\n")) + glextlist; + // Don't translate as translated text in the Library Info dialog is not wanted + return glewinfo + std::string("\nUsing QGLWidget\n\n") + glextlist; } #ifdef ENABLE_OPENCSG From b5ee931d13a46b4f1a23d027d3e52c4b5761f5e5 Mon Sep 17 00:00:00 2001 From: Andrew Plumb Date: Sun, 25 Jan 2015 09:51:11 -0500 Subject: [PATCH 128/174] Mac build failing on line 908-909 Looks like lines 908-909 need to be reversed for my Mac OS X build to work on my latest git pull. Error message is: --snip-- msgfmt -c -v -o ./locale/ru/LC_MESSAGES/openscad.mo ./locale/ru.po ./locale/ru.po:908: missing 'msgstr' section ./locale/ru.po:910:7: syntax error msgfmt: found 2 fatal errors error running msgfmt make: *** [OpenSCAD.app/Contents/MacOS/OpenSCAD] Error 1 --end-snip-- Andrew. --- locale/ru.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locale/ru.po b/locale/ru.po index b60383c8..f08ac497 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -905,8 +905,8 @@ msgid "Fixed" msgstr "ФикÑированный" #: objects/ui_Preferences.h:1122 src/settings.cc:128 -msgid "Same" #, fuzzy +msgid "Same" msgstr "Так же" #: objects/ui_Preferences.h:1123 src/settings.cc:128 From 44d846f16e1a2d3467c41c01d055ba8ebfe29dff Mon Sep 17 00:00:00 2001 From: Bazza Date: Tue, 27 Jan 2015 21:38:20 +0000 Subject: [PATCH 129/174] update es.po add my name in code --- locale/es.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locale/es.po b/locale/es.po index f8e95d29..e5184516 100644 --- a/locale/es.po +++ b/locale/es.po @@ -1,11 +1,11 @@ -# French translations for OpenSCAD package. -# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER +# Spanish translations for OpenSCAD package. +# Copyright (C) 2015 THE OpenSCAD'S COPYRIGHT HOLDER # This file is distributed under the same license as the OpenSCAD package. -# don , 2013. +# bazza , 2015. # msgid "" msgstr "" -"Project-Id-Version: OpenSCAD 2013.02.07\n" +"Project-Id-Version: OpenSCAD 2015.01.21\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-24 20:49+0100\n" "PO-Revision-Date: 2015-01-21 22:36-0300\n" From d347b72e494de852b647f18e7e659656486317ee Mon Sep 17 00:00:00 2001 From: Keven Villeneuve Date: Tue, 27 Jan 2015 18:53:02 -0500 Subject: [PATCH 130/174] Update french translation --- locale/fr.po | 122 ++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 65 deletions(-) diff --git a/locale/fr.po b/locale/fr.po index 30ea95f2..5964c052 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -1,14 +1,14 @@ -# French translations for OpenSCAD package. -# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER -# This file is distributed under the same license as the OpenSCAD package. -# don , 2013. -# +# French translations for OpenSCAD package. +# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER +# This file is distributed under the same license as the OpenSCAD package. +# don , 2013. +# msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-24 20:49+0100\n" -"PO-Revision-Date: 2014-12-14 10:20-0500\n" +"PO-Revision-Date: 2015-01-27 18:47-0500\n" "Last-Translator: Keven Villeneuve \n" "Language-Team: French\n" "Language: fr\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Poedit-SourceCharset: utf-8\n" -"X-Generator: Poedit 1.7.1\n" +"X-Generator: Poedit 1.7.4\n" #: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" @@ -48,9 +48,8 @@ msgstr "" "\n" #: objects/ui_AboutDialog.h:112 -#, fuzzy msgid "OK" -msgstr "&OK" +msgstr "OK" #: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" @@ -128,9 +127,8 @@ msgid "Don't show again" msgstr "Ne plus afficher" #: objects/ui_launchingscreen.h:313 -#, fuzzy msgid "Version" -msgstr "Extrusion" +msgstr "Version" #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" @@ -266,7 +264,7 @@ msgstr "Coller la rotation de la fenêtre de rendu" #: objects/ui_MainWindow.h:869 msgid "Increase Font Size" -msgstr "" +msgstr "Agrandir la police" #: objects/ui_MainWindow.h:870 msgid "Ctrl++" @@ -274,7 +272,7 @@ msgstr "Ctrl++" #: objects/ui_MainWindow.h:871 msgid "Decrease Font Size" -msgstr "" +msgstr "Réduire la police" #: objects/ui_MainWindow.h:872 msgid "Ctrl+-" @@ -390,7 +388,7 @@ msgstr "Ctrl+3" #: objects/ui_MainWindow.h:900 msgid "Show Scale Markers" -msgstr "" +msgstr "Afficher les Marqueurs d'Échelle" #: objects/ui_MainWindow.h:901 msgid "Animate" @@ -618,11 +616,11 @@ msgstr "Ctrl+Shift+I" #: objects/ui_MainWindow.h:957 msgid "Cheat Sheet" -msgstr "" +msgstr "Aide-Mémoire" #: objects/ui_MainWindow.h:958 msgid "Message" -msgstr "" +msgstr "Message" #: objects/ui_MainWindow.h:961 msgid "Time:" @@ -766,7 +764,7 @@ msgstr "Palette de couleurs:" #: objects/ui_Preferences.h:1071 msgid "Show Warnings and Errors in 3D View" -msgstr "" +msgstr "Afficher les Avertissements et les Erreurs dans la fenêtre de rendu" #: objects/ui_Preferences.h:1072 msgid "Editor Type" @@ -793,154 +791,146 @@ msgid "Color syntax highlighting" msgstr "Colorer la coloration syntaxique" #: objects/ui_Preferences.h:1081 -#, fuzzy msgid "Ctrl/Cmd-Mouse-wheel zooms text" -msgstr "Utiliser Ctrl/Cmd-Roulette-Souris pour agrandir le texte" +msgstr "Ctrl/Cmd-Roulette-Souris agrandit le texte" #: objects/ui_Preferences.h:1082 -#, fuzzy msgid "Indentation" -msgstr "Documentation" +msgstr "Indentation" #: objects/ui_Preferences.h:1083 -#, fuzzy msgid "Auto Indent" -msgstr "&Indenter" +msgstr "Indentation Auto" #: objects/ui_Preferences.h:1084 -#, fuzzy msgid "Indent using" -msgstr "&Indenter" +msgstr "Indenter en utilisant" #: objects/ui_Preferences.h:1087 src/settings.cc:135 -#, fuzzy msgid "Spaces" -msgstr "Surfaces" +msgstr "Espaces" #: objects/ui_Preferences.h:1088 src/settings.cc:135 msgid "Tabs" -msgstr "" +msgstr "Tabulations" #: objects/ui_Preferences.h:1090 msgid "Indentation width" -msgstr "" +msgstr "Largeur d'Indentation" #: objects/ui_Preferences.h:1091 msgid "Tab width" -msgstr "" +msgstr "Largeur des tabulations" #: objects/ui_Preferences.h:1092 msgid "Tab key function" -msgstr "" +msgstr "Fonction de la touche Tab" #: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 #: src/settings.cc:136 -#, fuzzy msgid "Indent" -msgstr "&Indenter" +msgstr "Indenter" #: objects/ui_Preferences.h:1096 src/settings.cc:136 msgid "Insert Tab" -msgstr "" +msgstr "Insérer une Tabulation" #: objects/ui_Preferences.h:1098 msgid "Show whitespace" -msgstr "" +msgstr "Afficher les espaces blancs" #: objects/ui_Preferences.h:1101 src/settings.cc:132 msgid "Never" -msgstr "" +msgstr "Jamais" #: objects/ui_Preferences.h:1102 src/settings.cc:132 msgid "Always" -msgstr "" +msgstr "Toujours" #: objects/ui_Preferences.h:1103 msgid "Only after indentation" -msgstr "" +msgstr "Seulement après indentation" #: objects/ui_Preferences.h:1105 msgid "Size" -msgstr "" +msgstr "Taille" #: objects/ui_Preferences.h:1106 -#, fuzzy msgid "Display" -msgstr "Afficher &AST..." +msgstr "Afficher" #: objects/ui_Preferences.h:1107 msgid "Enable brace matching" -msgstr "" +msgstr "Activer la correspondance d'accolades" #: objects/ui_Preferences.h:1108 msgid "Highlight current line" -msgstr "" +msgstr "Surligner la ligne courante" #: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 msgid "Line wrap" -msgstr "" +msgstr "Retour à la ligne" #: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 #: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 #: src/settings.cc:131 msgid "None" -msgstr "" +msgstr "Aucun" #: objects/ui_Preferences.h:1113 src/settings.cc:127 msgid "Wrap at character boundaries" -msgstr "" +msgstr "Enveloppez aux limites des caractères" #: objects/ui_Preferences.h:1114 src/settings.cc:127 msgid "Wrap at word boundaries" -msgstr "" +msgstr "Enveloppez aux limites des mots" #: objects/ui_Preferences.h:1116 msgid "Line wrap indentation" -msgstr "" +msgstr "Indentation des retours à la ligne" #: objects/ui_Preferences.h:1117 msgid "Line wrap visualization" -msgstr "" +msgstr "Visualisation des retours à la ligne" #: objects/ui_Preferences.h:1118 msgid "Style" -msgstr "" +msgstr "Style" #: objects/ui_Preferences.h:1121 src/settings.cc:128 msgid "Fixed" -msgstr "" +msgstr "Fixé" #: objects/ui_Preferences.h:1122 src/settings.cc:128 msgid "Same" -msgstr "" +msgstr "Identique" #: objects/ui_Preferences.h:1123 src/settings.cc:128 -#, fuzzy msgid "Indented" -msgstr "&Indenter" +msgstr "Indenté" #: objects/ui_Preferences.h:1126 msgid "Start" -msgstr "" +msgstr "Début" #: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 #: src/settings.cc:130 src/settings.cc:131 msgid "Text" -msgstr "" +msgstr "Texte" #: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 #: src/settings.cc:130 src/settings.cc:131 msgid "Border" -msgstr "" +msgstr "Bordure" #: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 #: src/settings.cc:130 src/settings.cc:131 msgid "Margin" -msgstr "" +msgstr "Marge" #: objects/ui_Preferences.h:1134 msgid "End" -msgstr "" +msgstr "Fin" #: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" @@ -1044,21 +1034,21 @@ msgstr "Untitled.scad" #: src/mainwin.cc:971 msgid "Compile error." -msgstr "" +msgstr "Erreur de Compilation." #: src/mainwin.cc:974 msgid "Error while compiling '%1'." -msgstr "" +msgstr "Erreur lors de la compilation de '%1'." #: src/mainwin.cc:978 msgid "Compilation generated %1 warning." msgid_plural "Compilation generated %1 warnings." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "La compilation a généré %1 avertissement" +msgstr[1] "La compilation a généré %1 avertissements" #: src/mainwin.cc:988 msgid " For details see console window." -msgstr "" +msgstr " Pour détails voir Fenêtre de la Console." #: src/mainwin.cc:1353 msgid "Save File" @@ -1141,6 +1131,8 @@ msgid "" "Fontconfig needs to update its font cache.\n" "This can take up to a couple of minutes." msgstr "" +"Fontconfig a besoin de mettre à jour son cache de polices.\n" +"Celà peut prendre quelques minutes." #: src/QGLView.cc:111 msgid "" @@ -1193,7 +1185,7 @@ msgstr "" #: src/settings.cc:132 msgid "After indentation" -msgstr "" +msgstr "Après indentation" #: src/UIUtils.cc:86 msgid "Basics" From f2c263a1f4c9b1e988fc07bf2f82809daadab1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Wed, 28 Jan 2015 10:50:55 +0100 Subject: [PATCH 131/174] Updated the Czech translation --- locale/cs.po | 113 ++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 61 deletions(-) diff --git a/locale/cs.po b/locale/cs.po index 030853e4..6b2aed79 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: OpenSCAD 2013.02.24\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-24 20:49+0100\n" -"PO-Revision-Date: 2014-12-23 12:24+0100\n" +"PO-Revision-Date: 2015-01-28 10:50+0100\n" "Last-Translator: Miro HronÄok \n" "Language-Team: Czech \n" "Language: cs\n" @@ -38,9 +38,8 @@ msgid "" msgstr "" #: objects/ui_AboutDialog.h:112 -#, fuzzy msgid "OK" -msgstr "&OK" +msgstr "OK" #: objects/ui_FontListDialog.h:105 msgid "OpenSCAD Font List" @@ -118,9 +117,8 @@ msgid "Don't show again" msgstr "PříštÄ› nezobrazovat" #: objects/ui_launchingscreen.h:313 -#, fuzzy msgid "Version" -msgstr "Vytažení" +msgstr "Verze" #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" @@ -256,7 +254,7 @@ msgstr "Vložit rotaci pohledu" #: objects/ui_MainWindow.h:869 msgid "Increase Font Size" -msgstr "" +msgstr "ZvÄ›tÅ¡it písmo" #: objects/ui_MainWindow.h:870 msgid "Ctrl++" @@ -264,7 +262,7 @@ msgstr "Ctrl++" #: objects/ui_MainWindow.h:871 msgid "Decrease Font Size" -msgstr "" +msgstr "ZmenÅ¡it písmo" #: objects/ui_MainWindow.h:872 msgid "Ctrl+-" @@ -380,7 +378,7 @@ msgstr "Ctrl+3" #: objects/ui_MainWindow.h:900 msgid "Show Scale Markers" -msgstr "" +msgstr "Zobrazit pravítko" #: objects/ui_MainWindow.h:901 msgid "Animate" @@ -608,11 +606,11 @@ msgstr "Ctrl+Shift+I" #: objects/ui_MainWindow.h:957 msgid "Cheat Sheet" -msgstr "" +msgstr "Tahák" #: objects/ui_MainWindow.h:958 msgid "Message" -msgstr "" +msgstr "Zpráva" #: objects/ui_MainWindow.h:961 msgid "Time:" @@ -746,7 +744,7 @@ msgstr "Barevné téma:" #: objects/ui_Preferences.h:1071 msgid "Show Warnings and Errors in 3D View" -msgstr "" +msgstr "Zobrazovat varování a chyby v 3D oknÄ›" #: objects/ui_Preferences.h:1072 msgid "Editor Type" @@ -773,154 +771,146 @@ msgid "Color syntax highlighting" msgstr "Barva zvýrazňování syntaxe" #: objects/ui_Preferences.h:1081 -#, fuzzy msgid "Ctrl/Cmd-Mouse-wheel zooms text" -msgstr "Použít Ctrl/Cmd a koleÄko myÅ¡i k zmÄ›nÄ› velikosti písma" +msgstr "Ctrl/Cmd a koleÄko myÅ¡i mÄ›ní velikost písma" #: objects/ui_Preferences.h:1082 -#, fuzzy msgid "Indentation" -msgstr "Dokumentace" +msgstr "Odsazování" #: objects/ui_Preferences.h:1083 -#, fuzzy msgid "Auto Indent" -msgstr "Odsad&it" +msgstr "Automatické odsazování" #: objects/ui_Preferences.h:1084 -#, fuzzy msgid "Indent using" -msgstr "Odsad&it" +msgstr "Odsazovat pomocí" #: objects/ui_Preferences.h:1087 src/settings.cc:135 -#, fuzzy msgid "Spaces" -msgstr "Povrchy" +msgstr "mezer" #: objects/ui_Preferences.h:1088 src/settings.cc:135 msgid "Tabs" -msgstr "" +msgstr "tabulátorů" #: objects/ui_Preferences.h:1090 msgid "Indentation width" -msgstr "" +msgstr "Velikost odsazení" #: objects/ui_Preferences.h:1091 msgid "Tab width" -msgstr "" +msgstr "Šířka tabulátoru" #: objects/ui_Preferences.h:1092 msgid "Tab key function" -msgstr "" +msgstr "Funkce klávesy tabulátor" #: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 #: src/settings.cc:136 -#, fuzzy msgid "Indent" -msgstr "Odsad&it" +msgstr "odsadí" #: objects/ui_Preferences.h:1096 src/settings.cc:136 msgid "Insert Tab" -msgstr "" +msgstr "vloží znak tabulátoru" #: objects/ui_Preferences.h:1098 msgid "Show whitespace" -msgstr "" +msgstr "Zobrazovat mazery" #: objects/ui_Preferences.h:1101 src/settings.cc:132 msgid "Never" -msgstr "" +msgstr "nikdy" #: objects/ui_Preferences.h:1102 src/settings.cc:132 msgid "Always" -msgstr "" +msgstr "vždy" #: objects/ui_Preferences.h:1103 msgid "Only after indentation" -msgstr "" +msgstr "pouze za odsazením" #: objects/ui_Preferences.h:1105 msgid "Size" -msgstr "" +msgstr "Velikost" #: objects/ui_Preferences.h:1106 -#, fuzzy msgid "Display" -msgstr "Ukázat &ATS..." +msgstr "Vzhled" #: objects/ui_Preferences.h:1107 msgid "Enable brace matching" -msgstr "" +msgstr "Zvýrazňovat párové závorky" #: objects/ui_Preferences.h:1108 msgid "Highlight current line" -msgstr "" +msgstr "Zvýrazňovat aktuální řádek" #: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 msgid "Line wrap" -msgstr "" +msgstr "Zalamování řádek" #: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 #: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 #: src/settings.cc:131 msgid "None" -msgstr "" +msgstr "vypnout" #: objects/ui_Preferences.h:1113 src/settings.cc:127 msgid "Wrap at character boundaries" -msgstr "" +msgstr "zalamovat na úrovni znaků" #: objects/ui_Preferences.h:1114 src/settings.cc:127 msgid "Wrap at word boundaries" -msgstr "" +msgstr "zalamovat na úrovni slov" #: objects/ui_Preferences.h:1116 msgid "Line wrap indentation" -msgstr "" +msgstr "Odsazení zalomených řádek" #: objects/ui_Preferences.h:1117 msgid "Line wrap visualization" -msgstr "" +msgstr "Pozice symbolu zalomení" #: objects/ui_Preferences.h:1118 msgid "Style" -msgstr "" +msgstr "Styl" #: objects/ui_Preferences.h:1121 src/settings.cc:128 msgid "Fixed" -msgstr "" +msgstr "vždy stejný" #: objects/ui_Preferences.h:1122 src/settings.cc:128 msgid "Same" -msgstr "" +msgstr "jako poÄátek" #: objects/ui_Preferences.h:1123 src/settings.cc:128 -#, fuzzy msgid "Indented" -msgstr "Odsad&it" +msgstr "odsazený" #: objects/ui_Preferences.h:1126 msgid "Start" -msgstr "" +msgstr "ZaÄátek" #: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 #: src/settings.cc:130 src/settings.cc:131 msgid "Text" -msgstr "" +msgstr "za textem" #: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 #: src/settings.cc:130 src/settings.cc:131 msgid "Border" -msgstr "" +msgstr "konec řádky" #: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 #: src/settings.cc:130 src/settings.cc:131 msgid "Margin" -msgstr "" +msgstr "levý okraj" #: objects/ui_Preferences.h:1134 msgid "End" -msgstr "" +msgstr "Konec" #: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" @@ -1020,24 +1010,23 @@ msgid "Untitled.scad" msgstr "Bezejmenný.scad" #: src/mainwin.cc:971 -#, fuzzy msgid "Compile error." -msgstr "Z&kompilovat" +msgstr "Chyba kompilace." #: src/mainwin.cc:974 msgid "Error while compiling '%1'." -msgstr "" +msgstr "Chyba pÅ™i kompilaci '%1'." #: src/mainwin.cc:978 msgid "Compilation generated %1 warning." msgid_plural "Compilation generated %1 warnings." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Kompilace vyvolala %1 varování." +msgstr[1] "Kompilace vyvolala %1 varování." +msgstr[2] "Kompilace vyvolala %1 varování." #: src/mainwin.cc:988 msgid " For details see console window." -msgstr "" +msgstr "Pro podrobnosti nahlédnÄ›te do konzole." #: src/mainwin.cc:1353 msgid "Save File" @@ -1120,6 +1109,8 @@ msgid "" "Fontconfig needs to update its font cache.\n" "This can take up to a couple of minutes." msgstr "" +"Fontconfig potÅ™ebuje aktualizovat cache.\n" +"To může trvat až nÄ›kolik minut." #: src/QGLView.cc:111 msgid "" @@ -1170,7 +1161,7 @@ msgstr "" #: src/settings.cc:132 msgid "After indentation" -msgstr "" +msgstr "za odsazením" #: src/UIUtils.cc:86 msgid "Basics" From ab2fa92eb5e6b8e9ada6ca2ccbc9145d8f1f852d Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 28 Jan 2015 14:49:06 -0500 Subject: [PATCH 132/174] Added test triggering #1192 --- testdata/scad/misc/recursion-tests.scad | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testdata/scad/misc/recursion-tests.scad b/testdata/scad/misc/recursion-tests.scad index 78b31e35..1732354a 100644 --- a/testdata/scad/misc/recursion-tests.scad +++ b/testdata/scad/misc/recursion-tests.scad @@ -1,5 +1,8 @@ function crash() = crash(); +// Recursion as module parameter echo(crash()); +// Recursion as assignment +a = crash(); module crash() crash(); crash(); From 597d07f357e971473454ea1992fee7ba35c9fdc9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 28 Jan 2015 20:07:15 -0500 Subject: [PATCH 133/174] Catch infinite recursion in top-level assignments. Fixes #1192 --- src/module.cc | 9 +++++---- ...recursion-tests.scad => recursion-test-function.scad} | 5 ----- testdata/scad/misc/recursion-test-function2.scad | 3 +++ testdata/scad/misc/recursion-test-module.scad | 3 +++ tests/CMakeLists.txt | 4 +++- ...pected.echo => recursion-test-function-expected.echo} | 1 - .../echotest/recursion-test-function2-expected.echo | 1 + .../echotest/recursion-test-module-expected.echo | 1 + 8 files changed, 16 insertions(+), 11 deletions(-) rename testdata/scad/misc/{recursion-tests.scad => recursion-test-function.scad} (50%) create mode 100644 testdata/scad/misc/recursion-test-function2.scad create mode 100644 testdata/scad/misc/recursion-test-module.scad rename tests/regression/echotest/{recursion-tests-expected.echo => recursion-test-function-expected.echo} (51%) create mode 100644 tests/regression/echotest/recursion-test-function2-expected.echo create mode 100644 tests/regression/echotest/recursion-test-module-expected.echo diff --git a/src/module.cc b/src/module.cc index 8cf6498e..715cd337 100644 --- a/src/module.cc +++ b/src/module.cc @@ -349,15 +349,16 @@ AbstractNode *FileModule::instantiate(const Context *ctx, const ModuleInstantiat delete context; context = new FileContext(*this, ctx); - context->initializeModule(*this); + AbstractNode *node = new AbstractNode(inst); + + try { + context->initializeModule(*this); // FIXME: Set document path to the path of the module #if 0 && DEBUG - c.dump(this, inst); + c.dump(this, inst); #endif - AbstractNode *node = new AbstractNode(inst); - try { std::vector instantiatednodes = this->scope.instantiateChildren(context); node->children.insert(node->children.end(), instantiatednodes.begin(), instantiatednodes.end()); } diff --git a/testdata/scad/misc/recursion-tests.scad b/testdata/scad/misc/recursion-test-function.scad similarity index 50% rename from testdata/scad/misc/recursion-tests.scad rename to testdata/scad/misc/recursion-test-function.scad index 1732354a..d01ce36d 100644 --- a/testdata/scad/misc/recursion-tests.scad +++ b/testdata/scad/misc/recursion-test-function.scad @@ -1,8 +1,3 @@ function crash() = crash(); // Recursion as module parameter echo(crash()); -// Recursion as assignment -a = crash(); - -module crash() crash(); -crash(); diff --git a/testdata/scad/misc/recursion-test-function2.scad b/testdata/scad/misc/recursion-test-function2.scad new file mode 100644 index 00000000..369f3775 --- /dev/null +++ b/testdata/scad/misc/recursion-test-function2.scad @@ -0,0 +1,3 @@ +// Recursion as assignment +function crash() = crash(); +a = crash(); diff --git a/testdata/scad/misc/recursion-test-module.scad b/testdata/scad/misc/recursion-test-module.scad new file mode 100644 index 00000000..0ad24b88 --- /dev/null +++ b/testdata/scad/misc/recursion-test-module.scad @@ -0,0 +1,3 @@ +// Module recursion +module crash() crash(); +crash(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 864be15b..c3eefcf0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1055,7 +1055,9 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/vector-values.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/search-tests-unicode.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-function2.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/recursion-test-module.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/tail-recursion-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/value-reassignment-tests2.scad diff --git a/tests/regression/echotest/recursion-tests-expected.echo b/tests/regression/echotest/recursion-test-function-expected.echo similarity index 51% rename from tests/regression/echotest/recursion-tests-expected.echo rename to tests/regression/echotest/recursion-test-function-expected.echo index 747e6d47..ef9ebaaf 100644 --- a/tests/regression/echotest/recursion-tests-expected.echo +++ b/tests/regression/echotest/recursion-test-function-expected.echo @@ -1,2 +1 @@ ERROR: Recursion detected calling function 'crash' -ERROR: Recursion detected calling module 'crash' diff --git a/tests/regression/echotest/recursion-test-function2-expected.echo b/tests/regression/echotest/recursion-test-function2-expected.echo new file mode 100644 index 00000000..ef9ebaaf --- /dev/null +++ b/tests/regression/echotest/recursion-test-function2-expected.echo @@ -0,0 +1 @@ +ERROR: Recursion detected calling function 'crash' diff --git a/tests/regression/echotest/recursion-test-module-expected.echo b/tests/regression/echotest/recursion-test-module-expected.echo new file mode 100644 index 00000000..2840a9a9 --- /dev/null +++ b/tests/regression/echotest/recursion-test-module-expected.echo @@ -0,0 +1 @@ +ERROR: Recursion detected calling module 'crash' From 5f496b25547a31af3e9d3f87f9c51a69967860d5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 00:11:52 -0500 Subject: [PATCH 134/174] Be helpful and set default convexity of rotate_extrude to 2 --- src/rotateextrude.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index 48b029a6..bbe84905 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -79,7 +79,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI node->scale = scale->toDouble(); if (node->convexity <= 0) - node->convexity = 1; + node->convexity = 2; if (node->scale <= 0) node->scale = 1; From 79b45e62b6dc280f6d8bfd94d67901c9c24e509e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 00:52:53 -0500 Subject: [PATCH 135/174] Fix test results after modifying default convexity for rotate_extrude --- tests/regression/dumptest/allmodules-expected.csg | 4 ++-- .../dumptest/linear_extrude-tests-expected.csg | 6 +++--- .../localfiles-compatibility-test-expected.csg | 2 +- .../regression/dumptest/localfiles-test-expected.csg | 2 +- .../dumptest/rotate_extrude-tests-expected.csg | 12 ++++++------ .../dumptest/rotate_extrude_dxf-tests-expected.csg | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/regression/dumptest/allmodules-expected.csg b/tests/regression/dumptest/allmodules-expected.csg index 9af5da4b..64bb2921 100644 --- a/tests/regression/dumptest/allmodules-expected.csg +++ b/tests/regression/dumptest/allmodules-expected.csg @@ -16,8 +16,8 @@ group() { intersection(); linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); linear_extrude(height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); import(file = "", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); diff --git a/tests/regression/dumptest/linear_extrude-tests-expected.csg b/tests/regression/dumptest/linear_extrude-tests-expected.csg index 539412d6..23bdb899 100644 --- a/tests/regression/dumptest/linear_extrude-tests-expected.csg +++ b/tests/regression/dumptest/linear_extrude-tests-expected.csg @@ -1,7 +1,7 @@ group() { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { cube(size = [1, 1, 1], center = false); } linear_extrude(height = 10, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2) { diff --git a/tests/regression/dumptest/localfiles-compatibility-test-expected.csg b/tests/regression/dumptest/localfiles-compatibility-test-expected.csg index e8dd8066..e3be61a8 100644 --- a/tests/regression/dumptest/localfiles-compatibility-test-expected.csg +++ b/tests/regression/dumptest/localfiles-compatibility-test-expected.csg @@ -7,7 +7,7 @@ group() { linear_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { diff --git a/tests/regression/dumptest/localfiles-test-expected.csg b/tests/regression/dumptest/localfiles-test-expected.csg index d4db2548..8649c3b8 100644 --- a/tests/regression/dumptest/localfiles-test-expected.csg +++ b/tests/regression/dumptest/localfiles-test-expected.csg @@ -7,7 +7,7 @@ group() { linear_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], height = 100, center = false, convexity = 1, scale = [1, 1], $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 0], [0, 1, 0, 350], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "localfiles_dir/localfile.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } multmatrix([[1, 0, 0, 250], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { multmatrix([[200, 0, 0, 0], [0, 200, 0, 0], [0, 0, 50, 0], [0, 0, 0, 1]]) { diff --git a/tests/regression/dumptest/rotate_extrude-tests-expected.csg b/tests/regression/dumptest/rotate_extrude-tests-expected.csg index 23c8d6e9..d97d4376 100644 --- a/tests/regression/dumptest/rotate_extrude-tests-expected.csg +++ b/tests/regression/dumptest/rotate_extrude-tests-expected.csg @@ -1,10 +1,10 @@ group() { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2); - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { cube(size = [1, 1, 1], center = false); } - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { circle($fn = 0, $fa = 12, $fs = 2, r = 10); } @@ -44,14 +44,14 @@ group() { } } multmatrix([[1, 0, 0, 0], [0, 1, 0, -60], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(convexity = 1, $fn = 1, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 1, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, 20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { circle($fn = 1, $fa = 12, $fs = 2, r = 10); } } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 60], [0, 0, 1, 0], [0, 0, 0, 1]]) { - rotate_extrude(convexity = 1, $fn = 0, $fa = 12, $fs = 2) { + rotate_extrude(convexity = 2, $fn = 0, $fa = 12, $fs = 2) { multmatrix([[1, 0, 0, -20], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { square(size = [10, 10], center = false); } diff --git a/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg b/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg index 63c60ebe..5f4d6c9c 100644 --- a/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg +++ b/tests/regression/dumptest/rotate_extrude_dxf-tests-expected.csg @@ -1,3 +1,3 @@ group() { - rotate_extrude(file = "../../../dxf/open-polyline.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 1, $fn = 0, $fa = 12, $fs = 2); + rotate_extrude(file = "../../../dxf/open-polyline.dxf", layer = "", origin = [0, 0], scale = 1, convexity = 2, $fn = 0, $fa = 12, $fs = 2); } From 41642f2cb59713d0362fc90a712ac07f6130eb10 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 11:16:31 -0500 Subject: [PATCH 136/174] Updated menu mnemonics to cover most of the entries --- src/MainWindow.ui | 129 +++++++++++++++++++++++----------------------- src/mainwin.cc | 28 +++++----- 2 files changed, 78 insertions(+), 79 deletions(-) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 89ba4524..a92889b0 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -6,8 +6,8 @@ 0 0 - 1397 - 586 + 1118 + 636 @@ -244,7 +244,7 @@ 0 0 - 1397 + 1118 22 @@ -254,26 +254,26 @@ - Recent Files + Recen&t Files - Examples + &Examples - Export + E&xport - - - - - - + + + + + + - + @@ -361,12 +361,11 @@ + - - @@ -418,7 +417,7 @@ - + @@ -704,7 +703,7 @@ - Paste viewport translation + P&aste viewport translation Ctrl+T @@ -712,12 +711,12 @@ - Paste viewport rotation + Past&e viewport rotation - Increase Font Size + Increase Font &Size Ctrl++ @@ -725,7 +724,7 @@ - Decrease Font Size + Decrease Font Si&ze Ctrl+- @@ -736,7 +735,7 @@ true - Hide editor + H&ide editor @@ -765,7 +764,7 @@ :/images/render-32.png:/images/render-32.png - &Render + R&ender F6 @@ -773,12 +772,12 @@ - Check Validity + &Check Validity - Display &AST... + Display A&ST... @@ -788,10 +787,10 @@ - Display CSG &Products... + Display CSG Pr&oducts... - + :/images/STL.png:/images/STL.png @@ -800,7 +799,7 @@ Export as &STL... - + :/images/OFF.png:/images/OFF.png @@ -924,7 +923,7 @@ :/images/blackUp.png:/images/blackUp.png - Top + &Top Ctrl+4 @@ -936,7 +935,7 @@ :/images/blackbottom.png:/images/blackbottom.png - Bottom + &Bottom Ctrl+5 @@ -948,7 +947,7 @@ :/images/blackleft (copy).png:/images/blackleft (copy).png - Left + &Left Ctrl+6 @@ -960,7 +959,7 @@ :/images/rightright.png:/images/rightright.png - Right + &Right Ctrl+7 @@ -972,7 +971,7 @@ :/images/blackfront.png:/images/blackfront.png - Front + &Front Ctrl+8 @@ -984,7 +983,7 @@ :/images/blackback.png:/images/blackback.png - Back + Bac&k Ctrl+9 @@ -992,7 +991,7 @@ - Diagonal + &Diagonal Ctrl+0 @@ -1000,7 +999,7 @@ - Center + Ce&nter @@ -1012,7 +1011,7 @@ :/images/perspective1.png:/images/perspective1.png - Perspective + &Perspective @@ -1024,7 +1023,7 @@ :/images/orthogonal.png:/images/orthogonal.png - Orthogonal + &Orthogonal @@ -1032,7 +1031,7 @@ true - Hide console + H&ide console @@ -1040,7 +1039,7 @@ true - About + &About QAction::AboutRole @@ -1048,7 +1047,7 @@ - Documentation + &Documentation @@ -1056,18 +1055,18 @@ Clear Recent - + :/images/DXF.png:/images/DXF.png - Export as DXF... + Export as &DXF... - Close + &Close Ctrl+W @@ -1075,7 +1074,7 @@ - Preferences + &Preferences QAction::PreferencesRole @@ -1083,7 +1082,7 @@ - Find... + &Find... Ctrl+F @@ -1091,7 +1090,7 @@ - Find and Replace... + Fin&d and Replace... Ctrl+Alt+F @@ -1099,7 +1098,7 @@ - Find Next + Find Ne&xt Ctrl+G @@ -1107,7 +1106,7 @@ - Find Previous + Find Pre&vious Ctrl+Shift+G @@ -1115,7 +1114,7 @@ - Use Selection for Find + Use Se&lection for Find Ctrl+E @@ -1123,12 +1122,12 @@ - Flush Caches + &Flush Caches - OpenSCAD Homepage + &OpenSCAD Homepage @@ -1136,35 +1135,35 @@ true - Automatic Reload and Preview + &Automatic Reload and Preview - + :/images/PNG.png:/images/PNG.png - Export as Image... + Export as &Image... - + :/images/CSG.png:/images/CSG.png - Export as CSG... + Export as &CSG... - Library info + &Library info - Show Library Folder... + Show &Library Folder... @@ -1178,25 +1177,25 @@ - Font List + &Font List - + :/images/CSG.png:/images/CSG.png - Export as SVG... + Export as S&VG... - + :/images/AMF.png:/images/AMF.png - Export as AMF... + Export as &AMF... @@ -1234,7 +1233,7 @@ - Convert Tabs to Spaces + Conv&ert Tabs to Spaces @@ -1259,7 +1258,7 @@ - Cheat Sheet + &Cheat Sheet diff --git a/src/mainwin.cc b/src/mainwin.cc index 9c1965b1..7052c9f5 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -353,13 +353,13 @@ MainWindow::MainWindow(const QString &filename) connect(this->designActionDisplayAST, SIGNAL(triggered()), this, SLOT(actionDisplayAST())); connect(this->designActionDisplayCSGTree, SIGNAL(triggered()), this, SLOT(actionDisplayCSGTree())); connect(this->designActionDisplayCSGProducts, SIGNAL(triggered()), this, SLOT(actionDisplayCSGProducts())); - connect(this->designActionExportSTL, SIGNAL(triggered()), this, SLOT(actionExportSTL())); - connect(this->designActionExportOFF, SIGNAL(triggered()), this, SLOT(actionExportOFF())); - connect(this->designActionExportAMF, SIGNAL(triggered()), this, SLOT(actionExportAMF())); - connect(this->designActionExportDXF, SIGNAL(triggered()), this, SLOT(actionExportDXF())); - connect(this->designActionExportSVG, SIGNAL(triggered()), this, SLOT(actionExportSVG())); - connect(this->designActionExportCSG, SIGNAL(triggered()), this, SLOT(actionExportCSG())); - connect(this->designActionExportImage, SIGNAL(triggered()), this, SLOT(actionExportImage())); + connect(this->fileActionExportSTL, SIGNAL(triggered()), this, SLOT(actionExportSTL())); + connect(this->fileActionExportOFF, SIGNAL(triggered()), this, SLOT(actionExportOFF())); + connect(this->fileActionExportAMF, SIGNAL(triggered()), this, SLOT(actionExportAMF())); + connect(this->fileActionExportDXF, SIGNAL(triggered()), this, SLOT(actionExportDXF())); + connect(this->fileActionExportSVG, SIGNAL(triggered()), this, SLOT(actionExportSVG())); + connect(this->fileActionExportCSG, SIGNAL(triggered()), this, SLOT(actionExportCSG())); + connect(this->fileActionExportImage, SIGNAL(triggered()), this, SLOT(actionExportImage())); connect(this->designActionFlushCaches, SIGNAL(triggered()), this, SLOT(actionFlushCaches())); // View menu @@ -497,13 +497,13 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(viewActionOrthogonal, ":/images/orthogonal.png", ":/images/orthogonalwhite.png"); initActionIcon(designActionPreview, ":/images/preview-32.png", ":/images/preview-32-white.png"); initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); - initActionIcon(designActionExportSTL, ":/images/STL.png", ":/images/STL-white.png"); - initActionIcon(designActionExportAMF, ":/images/AMF.png", ":/images/AMF-white.png"); - initActionIcon(designActionExportOFF, ":/images/OFF.png", ":/images/OFF-white.png"); - initActionIcon(designActionExportDXF, ":/images/DXF.png", ":/images/DXF-white.png"); - initActionIcon(designActionExportSVG, ":/images/SVG.png", ":/images/SVG-white.png"); - initActionIcon(designActionExportCSG, ":/images/CSG.png", ":/images/CSG-white.png"); - initActionIcon(designActionExportImage, ":/images/PNG.png", ":/images/PNG-white.png"); + initActionIcon(fileActionExportSTL, ":/images/STL.png", ":/images/STL-white.png"); + initActionIcon(fileActionExportAMF, ":/images/AMF.png", ":/images/AMF-white.png"); + initActionIcon(fileActionExportOFF, ":/images/OFF.png", ":/images/OFF-white.png"); + initActionIcon(fileActionExportDXF, ":/images/DXF.png", ":/images/DXF-white.png"); + initActionIcon(fileActionExportSVG, ":/images/SVG.png", ":/images/SVG-white.png"); + initActionIcon(fileActionExportCSG, ":/images/CSG.png", ":/images/CSG-white.png"); + initActionIcon(fileActionExportImage, ":/images/PNG.png", ":/images/PNG-white.png"); initActionIcon(viewActionViewAll, ":/images/zoom-all.png", ":/images/zoom-all-white.png"); initActionIcon(editActionUndo, ":/images/Command-Undo-32.png", ":/images/Command-Undo-32-white.png"); initActionIcon(editActionRedo, ":/images/Command-Redo-32.png", ":/images/Command-Redo-32-white.png"); From 3fa33172334ceb0f2c82eeb7db7cf7c63702fecf Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 11:18:53 -0500 Subject: [PATCH 137/174] minor fix: Call this->quit to correctly end application --- src/mainwin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mainwin.cc b/src/mainwin.cc index 7052c9f5..1287fad7 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -691,7 +691,7 @@ MainWindow::~MainWindow() if (MainWindow::getWindows()->size() == 0) { // Quit application even in case some other windows like // Preferences are still open. - qApp->quit(); + this->quit(); } } From c68533d3c66d212504aea6256050ea9e960601b2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 11:26:38 -0500 Subject: [PATCH 138/174] #1189 Removed unused titles for progressbar and preferences toolbar --- src/Preferences.ui | 17 +++++++---------- src/ProgressWidget.ui | 3 --- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/Preferences.ui b/src/Preferences.ui index 2e20dc70..df9a1733 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -108,8 +108,8 @@ 0 0 - 659 - 769 + 605 + 662 @@ -226,7 +226,7 @@ - Liberation Sans + Helvetica 12 @@ -1160,8 +1160,8 @@ 0 0 - 100 - 30 + 98 + 36 @@ -1214,8 +1214,8 @@ 0 0 - 596 - 499 + 440 + 339 @@ -1389,9 +1389,6 @@ - - toolBar - false diff --git a/src/ProgressWidget.ui b/src/ProgressWidget.ui index 24aefdb2..1ed3e7ea 100644 --- a/src/ProgressWidget.ui +++ b/src/ProgressWidget.ui @@ -10,9 +10,6 @@ 20 - - Form - 5 From b5c60a22e57021bc9195b5108a185b00a100aeac Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 12:24:12 -0500 Subject: [PATCH 139/174] #1196 Added testcase --- testdata/scad/bugs/issue1196.scad | 9 +++++++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1196-expected.png | Bin 0 -> 7079 bytes .../monotonepngtest/issue1196-expected.png | Bin 0 -> 7079 bytes .../opencsgtest/issue1196-expected.png | Bin 0 -> 7349 bytes 5 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue1196.scad create mode 100644 tests/regression/cgalpngtest/issue1196-expected.png create mode 100644 tests/regression/monotonepngtest/issue1196-expected.png create mode 100644 tests/regression/opencsgtest/issue1196-expected.png diff --git a/testdata/scad/bugs/issue1196.scad b/testdata/scad/bugs/issue1196.scad new file mode 100644 index 00000000..6fe6db45 --- /dev/null +++ b/testdata/scad/bugs/issue1196.scad @@ -0,0 +1,9 @@ +minkowski() { + cube(); + linear_extrude() { + import("notfound.dxf"); + } + linear_extrude() { + import("notfound.dxf"); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3eefcf0..c0db89a0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1234,7 +1234,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1196-expected.png b/tests/regression/cgalpngtest/issue1196-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..677d52ca8bc001554d27e59b4decd40abbad783a GIT binary patch literal 7079 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 XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue1196-expected.png b/tests/regression/monotonepngtest/issue1196-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..677d52ca8bc001554d27e59b4decd40abbad783a GIT binary patch literal 7079 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 XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue1196-expected.png b/tests/regression/opencsgtest/issue1196-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..989385eeab098d42872e7f5bb7cc356639c5261c GIT binary patch literal 7349 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 literal 0 HcmV?d00001 From 07e1894f6e767708b5417c18dbfffb1d4881896c Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 12:59:56 -0500 Subject: [PATCH 140/174] Fixes crash when using rands() with min == max --- src/func.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/func.cc b/src/func.cc index 8fc10da2..d4e6cbbe 100644 --- a/src/func.cc +++ b/src/func.cc @@ -255,12 +255,12 @@ ValuePtr builtin_rands(const Context *, const EvalContext *evalctx) deterministic_rng.seed((unsigned int) v3->toDouble()); deterministic = true; } - boost::uniform_real<> distributor( min, max ); Value::VectorType vec; - if (min==max) { // workaround boost bug + if (min==max) { // Boost doesn't allow min == max for (size_t i=0; i < numresults; i++) vec.push_back( Value( min ) ); } else { + boost::uniform_real<> distributor( min, max ); for (size_t i=0; i < numresults; i++) { if ( deterministic ) { vec.push_back(Value(distributor(deterministic_rng))); From 2b727e8ea22ef9dad472d41bae00aa7667eb3f6b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 17:06:30 -0500 Subject: [PATCH 141/174] #1198 Added testcase --- testdata/scad/bugs/issue1198.scad | 23 ++++++++++++++++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1198-expected.png | Bin 0 -> 6377 bytes .../monotonepngtest/issue1198-expected.png | Bin 0 -> 6377 bytes .../opencsgtest/issue1198-expected.png | Bin 0 -> 6588 bytes 5 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue1198.scad create mode 100644 tests/regression/cgalpngtest/issue1198-expected.png create mode 100644 tests/regression/monotonepngtest/issue1198-expected.png create mode 100644 tests/regression/opencsgtest/issue1198-expected.png diff --git a/testdata/scad/bugs/issue1198.scad b/testdata/scad/bugs/issue1198.scad new file mode 100644 index 00000000..86600289 --- /dev/null +++ b/testdata/scad/bugs/issue1198.scad @@ -0,0 +1,23 @@ +polyhedron(points = [ + [6.46538, 45.0434, -0.5185], + [7.45793, 45.0119, -0.636215], + [7.45793, 45.9778, -0.895034], + [6.46538, 46.0094, -0.77732], + [6.46538, 45.5264, -0.64791], + [6.18882, 44.4605, -2.69418], + [7.18137, 44.4289, -2.8119], + [7.18137, 45.3948, -3.07072], + [6.18882, 45.4264, -2.953], + [6.18882, 44.9434, -2.82359]], + + faces = + + + + [[0, 1, 6, 5], + [1, 2, 7, 6], + [2, 3, 8, 7], + [3, 4, 9, 8], + [4, 0, 5, 9], + [4, 3, 2, 1, 0], + [5, 6, 7, 8, 9]]); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c0db89a0..6273f331 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1235,7 +1235,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1198.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1198-expected.png b/tests/regression/cgalpngtest/issue1198-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..ad9c8a86fb2f3b45325ab7c077876bd5f614d025 GIT binary patch literal 6377 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 Date: Thu, 29 Jan 2015 17:45:09 -0500 Subject: [PATCH 142/174] Bugfix: We forgot to align the first passed vertex. Fixes #1198 --- src/grid.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/grid.h b/src/grid.h index f467ba3c..55010aaf 100644 --- a/src/grid.h +++ b/src/grid.h @@ -137,18 +137,24 @@ public: } } } + + T data; if (iter == db.end()) { // Not found: insert using key - T data = db.size(); + data = db.size(); db[key] = data; - return data; + } + else { + // If found return existing data + key = iter->first; + data = iter->second; } - // If found, align vertex and return existing data - key = iter->first; + // Align vertex v[0] = key[0] * this->res; v[1] = key[1] * this->res; v[2] = key[2] * this->res; - return iter->second; + + return data; } bool has(const Vector3d &v, T *data = NULL) { From e4d7de133b7e892f4d5a2cd86045f1893ae89556 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 17:54:58 -0500 Subject: [PATCH 143/174] #1198 moved test to fixed issues --- testdata/scad/{bugs => 3D/issues}/issue1198.scad | 0 tests/CMakeLists.txt | 3 +-- .../throwntogethertest/issue1198-expected.png | Bin 0 -> 6588 bytes 3 files changed, 1 insertion(+), 2 deletions(-) rename testdata/scad/{bugs => 3D/issues}/issue1198.scad (100%) create mode 100644 tests/regression/throwntogethertest/issue1198-expected.png diff --git a/testdata/scad/bugs/issue1198.scad b/testdata/scad/3D/issues/issue1198.scad similarity index 100% rename from testdata/scad/bugs/issue1198.scad rename to testdata/scad/3D/issues/issue1198.scad diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6273f331..c0db89a0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1235,8 +1235,7 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1198.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/throwntogethertest/issue1198-expected.png b/tests/regression/throwntogethertest/issue1198-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..32ecddb2284e67334bc90d6b91cef0dcb4ec672d GIT binary patch literal 6588 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 Date: Thu, 29 Jan 2015 18:35:12 -0500 Subject: [PATCH 144/174] Filter empty children before performing minkowski sum. Fixes #1196 --- src/GeometryEvaluator.cc | 10 +++++++++- src/cgalutils.cc | 3 +++ testdata/scad/bugs/issue1196.scad | 11 +++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index f950ce12..658c6d7f 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -123,7 +123,15 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr // Only one child -> this is a noop if (children.size() == 1) return ResultObject(children.front().second); - if (op == OPENSCAD_MINKOWSKI) return ResultObject(CGALUtils::applyMinkowski(children)); + if (op == OPENSCAD_MINKOWSKI) { + Geometry::ChildList actualchildren; + BOOST_FOREACH(const Geometry::ChildItem &item, children) { + if (!item.second->isEmpty()) actualchildren.push_back(item); + } + if (actualchildren.empty()) return ResultObject(); + if (actualchildren.size() == 1) return ResultObject(actualchildren.front().second); + return ResultObject(CGALUtils::applyMinkowski(actualchildren)); + } CGAL_Nef_polyhedron *N = CGALUtils::applyOperator(children, op); // FIXME: Clarify when we can return NULL and what that means diff --git a/src/cgalutils.cc b/src/cgalutils.cc index f8010f6a..c934ad4f 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -207,6 +207,9 @@ namespace CGALUtils { return visited.size() == p.size_of_facets(); } + /*! + children cannot contain NULL objects + */ Geometry const * applyMinkowski(const Geometry::ChildList &children) { CGAL::Timer t,t_tot; diff --git a/testdata/scad/bugs/issue1196.scad b/testdata/scad/bugs/issue1196.scad index 6fe6db45..4bc1149c 100644 --- a/testdata/scad/bugs/issue1196.scad +++ b/testdata/scad/bugs/issue1196.scad @@ -7,3 +7,14 @@ minkowski() { import("notfound.dxf"); } } + +minkowski() { + linear_extrude() { + import("notfound.dxf"); + } + linear_extrude() { + import("notfound.dxf"); + } + cube(); + cube(); +} From f01826b28b6665b6b86c07004d357a23fa5a4d8b Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 18:36:33 -0500 Subject: [PATCH 145/174] #1196 moved test to fixed issues --- testdata/scad/{bugs => 3D/issues}/issue1196.scad | 0 tests/CMakeLists.txt | 3 +-- .../throwntogethertest/issue1196-expected.png | Bin 0 -> 7349 bytes 3 files changed, 1 insertion(+), 2 deletions(-) rename testdata/scad/{bugs => 3D/issues}/issue1196.scad (100%) create mode 100644 tests/regression/throwntogethertest/issue1196-expected.png diff --git a/testdata/scad/bugs/issue1196.scad b/testdata/scad/3D/issues/issue1196.scad similarity index 100% rename from testdata/scad/bugs/issue1196.scad rename to testdata/scad/3D/issues/issue1196.scad diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c0db89a0..c3eefcf0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1234,8 +1234,7 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1196.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/throwntogethertest/issue1196-expected.png b/tests/regression/throwntogethertest/issue1196-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..989385eeab098d42872e7f5bb7cc356639c5261c GIT binary patch literal 7349 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 literal 0 HcmV?d00001 From 5b216a5bd48ac87a1b3e48d252c618ea9b983271 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 29 Jan 2015 18:50:57 -0500 Subject: [PATCH 146/174] Changed behavior of something minkowski'ed with nothing: It should return the actual object without changes --- .../nullspace-minkowski-expected.png | Bin 4408 -> 7079 bytes ...lspace-minkowski-intersection-expected.png | Bin 4408 -> 7079 bytes .../nullspace-minkowski-expected.png | Bin 4408 -> 7349 bytes ...lspace-minkowski-intersection-expected.png | Bin 4408 -> 7349 bytes .../nullspace-minkowski-expected.png | Bin 4408 -> 7349 bytes ...lspace-minkowski-intersection-expected.png | Bin 4408 -> 7349 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/regression/cgalpngtest/nullspace-minkowski-expected.png b/tests/regression/cgalpngtest/nullspace-minkowski-expected.png index 08ee92b2216f45ca6b83efbc3b78c9fdabf45a71..677d52ca8bc001554d27e59b4decd40abbad783a 100644 GIT binary patch literal 7079 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 XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 4408 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_puuo-U3d6^w7MGV(Gg@Gv_b z*za4?v*2+)UsdcS+v4fU4h;;A^A5apoi>Akk%?tr1LFsF77l?9E{TSWk4eG`4hI;1 z0L3|6Sa}?_RBYrFP)K0-15&w&iA^DD&kdkj1BSW=phzGivw&_~4p6NGgFVR96%C9X zV)|x4wLA^-3JwhpAqN;-y2WP$)v_Jn7f^6e&`MxfbhO(SsGIo#JBNURfT#h(#Yacg z92$VmU>mI zkPrlsva{W?6G2dbC_)te30K*ik07dkc3U<&hvLS%EEDwYl0{pNkd+s^F%i* z2b@_G9Fuj2`JW;78@ zj0}yVrWEUq4RDC*tt^J}+0QhD?RL8Pd~ zn`zOhhp+WtbyS^=_?V1NiPL{Lsv7mM_t!EVa#f0u?7hQ3mP>jzz)?%-)OoUp&vt0Ic0gB-!FntHsmK*PU`$;cjMB6H}0 zWWk@kVrVaZe{D&ood~wc>JEN`JT=}(`2-&0Mg6$JhuLvnIw9+ipQ(J~aca$BZGu~a~ z9aDTDy$#9x{xasIhAVlHhF#=57DpMm-18RPZ3Cj{7oyvw>TUu}BhA8x5M;#)!|9!V z>e7^qrdc1ZUHfj46?KY@d!30_!t2jV7>X@bLd2*BmU~r1;Y3zu&Zx4ip0#VPaRJbb0Vo1iMvgj50xW>_htD9POQFSc-07> zH+Lwz)XJ#Igr)B6Q7zeN5I!ou@H1wgrRA6}E8TTL(_7?pBhH*zEKu*g@x>|1TT}At zn(3qr!a1+0xM#}!r%=Y_4GuPDQZWqyrwr>SfBc5i<0pSSRArB(q=yX|eXhyutnfZq zFY_S^N6t$Jza{6oJ>nDvUV>tt0rFa@`p1tMF%uI;Nt?%{&4}B(Py$V!=WpWl9phLi z7ewkvaqmUR`3m9`h5eZ)>sZ?}DSgUcDJZJ>ao=oPVz{*?@-<+5BL7=jZPwDYntJ>l z2{m^$km$8j>=U1A_9TT^Jii!qem-=(amt~`Cd8WmtG{dFtMN;fM;i7S(ibw;Cww`I z$*eJFW@I@OeBr8hb|2T{kF6paA~hrTafqNVICvWPDUgvXOh2ABRmQ6-Z*Dd9bk$B8;`wlF zcOfeN9lI!4FTN0w%0$YWyKnRGS*OTD-fC`Byx+%YOF#lHty8Xhf`N-e4KGFX_~Dx= zL)&Rc5LaRIE!jZ}nY=k8%fRe#9IhqulBB<5&x{4TulaHPqZ)j|;>uW?kcG9eHCcmq zd+$#ET&~Bz>v%cXDTgC6>2sBW`53(q)x%4-tGi9=-QWFdDHBnC5@qeJVb~P&Z2-IH z-9L285Y~=udWt)>456Y@ocU>9j$fcGD;Bl7`)*2dPHx0>Ct%!!TWf=iadtR!0 z5#R`lGP<5C!bU?}Nkul5y6gbxwuFp~SQiKvBU@GkZsNPu8Q=T&h-4py=QC@2#9XTp zpA-#09r#%Rha+bu4#S<8H4ev?ZTt+6$1bNL_kwm(0CHDQk#*4(Dd1@b9#2bh%!vW0 z3UX&{cpVli>P03J`_}HHFun{X!X*xzK=H&avSeh(`iIg0eHCnfLHH_l&)oY?puGe+ zJ|))1X_qK%t|E^HKRXkNOp@kx;hJ?1EOA}d!aA1*GVM&QI0K$!A=A2ooC^RIp+x8l zEn$2R)bd~#2Y}hI$SK+yEQ3_GKq`-Nk1Pjxmi7UeIM8$PMXwxchd*&zYVJ*E9xi^r zmtG2fN1jXG~|q5VIM%YJ{7rkEJbMD2dq~< zy{G|16)_RF(tvYdDIKC4oYB4dm(dF%*mc(R2WO4&--!1YRVFg(FNjc^@vbXjw;aIZ zv6PGZAYfZ66_GP`zX0%tJQ)epy$T6aS#UD6?AMY579D9w<3m$x*hKNr5*rhfZ2_9$ zaE1^1l);i55QcZ4FaKXg?XSf4jXUeFS&RzP9{ofZ*;E) zD<0)b*Ola>jGSI0D6X71k-4Rbt_v^=M(J<6SlBdkpr=sn^m4KtB4HB2XO8V z^j~w#70&)@6zw6@#R2EfLF9^pe!l}S6iltA^50Dyr%IEF%X-FXRb@Mns@tZUz@q{< z-+Eh7=sX0R`}Gka@15XL;TT;LU^i&tlM5PP#&#JM*;(TLhtMJj@VNF>p{$*S(SCDq zt1u!E@c%Z-C};wY!ueNrg>(;v>mUc+muf=YBcKI14Y~laJSKAEKtMbMJ_%B@pq49y z#X$PC`i+oy9k`hc&)WpB5n9k)Nemi->`g=J#vhRY8tPI1hf#LRK5tPkX21>1AFURx zdjBhqt=TV})@T^;9x1vSz-xFsmTKf6YZJDb7H@1A0V)eXJtt*_FG*_st=R0ZK_KZ&|Kq(&N z0e3q`6X1JjS{1D}VH{~tMy|6K#F1v*({SsO=l97)o`_)a`U)a>&=ceE^N+_o6s~Ho5Z6*f7VgOPV3yc1V;<^4%Y3#wsT0FPfhjLxR&HpJ4?aU0aw~FG?3g-Va88 zc5X1j=#0YDpTwoh8AHeSl!*Ae`FWXDdZ_$1!ip5$<=6aV6uGMqZZ)S)97_&VXLX_1 z_+3HoRL77k6{*z4r)i=VWpZ3i#x$?arJO6B#w?yp%KvNW;Oa7lc)IlJZt1kq;>Emt zEZ8W7oGr_qZ(DJ!@)^YF+ErhQo^&i&zI`QQsPN3ku$u^1mmc|4IXmmbGU!lyK|7KCf z&5{%6KYeA-zLo~cLe|zx_Za+WRxTf3?B13phRYRP+07OymlYU^_!9h%MPKJ>F@`wy z{2yNCOr82j^#z$TUyEl4o`AiO7f!sRVur2d=VDH4ABclk(^m=NM zVtGoZ#A+q>ytky+={po!`m zTOj$Qc4&qCxYDB4=yf88*(z}Ees;bCXN=yBc#@C3z|^Adf+LHLjJv*K{z;#1Ha}7{ z-PKmyOlHrgriaZLjUm!HmS0$<=$G=a;a+f6Yu6l}M!`;%>R7bXd+^S27TdAmDCz(q zu1KUD`O)IaB`tk9w8uu=Z9Xoc>YG_G;(A1V*1&_+uW$KqH#W@k3w;G_`t7mm%Pd80 zR)kq+Ff%!_6WtwS$k*xPr=R50jMBwMA=B}!kx$mGgJKcoZ1>j9j}@V7_FMt))`#nk;<4D>xvIs=*?}iqHezqRF>(Kwg-q1=ky|v6 zsCX(xpXjzIVY7u6kD3V|twlgaq!`C)EfLhr7@g;^ryX)no`&jV?W6o#D$y{s{ zd0WcwuccE1zNcn-ET$@mTXAukzVr9@d$7cs`a-6(sMNG6M^=S%hc1{558X?E5$UrIEy>5&yGy2I zIx0s*{lxt5Ok>B36qWN&(FJeT2RDa8?E=)t^Gnf~sm8Zfwi%VmSrpomW6B4~rD$Z? z%VAzfRHZ7kZOE#jNLnenJNWrq-T{v=^&|>yoH85~QHolweKyS7Wn!&ziGta74Ij-b zMJZFYZ+RQ#Mb)Ay7}hkhcd!(leOxmfl^Pju(t*Pt{&eR6m*iP+e29}`F(5GpqB?yp z$CpsBscha`iz2WLh7&Ym_t{cZ$HQaZNz`#R)SMZ#%IYb@gB2K?&;L@MbvlPa8=gsZ zsmjOFi>~oEn^}%p!5U$uw1J{e6}`1_)nd~bwe4~fdT9w)1I37-C|+A~1zu*ett2k) z{cjb194082xxD~hnZ^~^B3$t=rA;VE)PA~Py^bq|$`JEM?%BL2aY+i9`iooDbmEq< zMNGTj%e&%z2?NYLK6J+&J-Dl&@IkW#m$c1Oe^FjieYGO!MpDPCY9f~u5#hGT*(Pq~ zDZDMetn4XKvzz2L?>!K$UI@m@yE|2R_;1Ic?T#m6ELA+r7H#(BFDzpZn1OAxluA2H zx<@;-@Qz|^wIX}IxwNb13EcEGVYZvVN)z6+i9@O0MMF9tj(1%`S$na!9PR;~uS$^h z6Z4)$0&6l#WB>H(lD3B(1TcP_g;OA$>w*w2MV>5@fDai49~oplG(#AIp47=o8Mw4z zo}rM7#`r?x=iUk0XoUtNi&KBv>f+}i_C>wl2NSMB4C{}aOLrCzs!(K4xlX^{dPkg# z3;IB=eW);aSdTGX=zHr`m^@o#Fkj=@u2n5HbePJnRZC`8FvME+xn4dTgGG9P#-3YO zQDQHQqGRv&+js*W1ZFbbP~Qa=3hGc1=~&_4N(YH}w8miE6_ft!Yv4gvVi}BX6D43X z4MGc%)HWjc+S@Lr#0cdmR_nwcmZj-R{M z#WKBdQg2t(cCKR2nrxyAx<2_W-HJ&wk{o|I6oWm32RSt#^EDu)%kNk1J0_Ri0g2y^ z@3Kf@Qn2k~zjCcveUK3^dt{~;s5p1@CeB2nQOIFao|@rZxGB`qs80m1EvyjkuG*R` zOomszXgu)z$}LzY@VD>_r0fgLO|V5M!-vbu9p)OsxBf&X;?ox>+~uFaZqYyU`Z+9% zEt*v1)?BCXH822n+VZDH!dH1?SoXCyn85DG@PwC8zwyh$ZvhUlIQ?VxKY#?5Kx|vL XY6R=pD>nQC4zb(nxTRndBl^DpPSBy0 literal 4408 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 literal 4408 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 literal 4408 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 literal 4408 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 literal 4408 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_puuo-U3d6^w7MGV(Gg@Gv_b z*za4?v*2+)UsdcS+v4fU4h;;A^A5apoi>Akk%?tr1LFsF77l?9E{TSWk4eG`4hI;1 z0L3|6Sa}?_RBYrFP)K0-15&w&iA^DD&kdkj1BSW=phzGivw&_~4p6NGgFVR96%C9X zV)|x4wLA^-3JwhpAqN;-y2WP$)v_Jn7f^6e&`MxfbhO(SsGIo#JBNURfT#h(#Yacg z92$VmU> Date: Thu, 29 Jan 2015 20:43:13 -0500 Subject: [PATCH 147/174] Wops, accidentally committed a change made for testing --- src/FontCache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FontCache.cc b/src/FontCache.cc index c353fe6f..1786dca8 100644 --- a/src/FontCache.cc +++ b/src/FontCache.cc @@ -83,7 +83,7 @@ const std::string &FontInfo::get_file() const FontCache * FontCache::self = NULL; FontCache::InitHandlerFunc *FontCache::cb_handler = FontCache::defaultInitHandler; void *FontCache::cb_userdata = NULL; -const std::string FontCache::DEFAULT_FONT("XXX"); +const std::string FontCache::DEFAULT_FONT("Liberation Sans:style=Regular"); /** * Default implementation for the font cache initialization. In case no other From ef8cdc42d3827cc7697d10f9a6223ab0c64407ad Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 1 Feb 2015 19:41:21 +0100 Subject: [PATCH 148/174] Update translations. --- locale/cs.po | 471 ++++++++++++++++++++++++------------------- locale/es.po | 474 ++++++++++++++++++++++++------------------- locale/fr.po | 477 +++++++++++++++++++++++++------------------- locale/openscad.pot | 392 ++++++++++++++++++------------------ locale/ru.po | 468 +++++++++++++++++++++++-------------------- 5 files changed, 1240 insertions(+), 1042 deletions(-) diff --git a/locale/cs.po b/locale/cs.po index 6b2aed79..d4ed3268 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.24\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" "PO-Revision-Date: 2015-01-28 10:50+0100\n" "Last-Translator: Miro HronÄok \n" "Language-Team: Czech \n" @@ -104,7 +104,6 @@ msgid "Open Recent" msgstr "Otevřít nedávný soubor" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Příklady" @@ -128,563 +127,610 @@ msgstr "Info o knihovnách a sestavení" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Podrobné informace o tomto sestavení OpenSCADu a použitých knihovnách" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Nový" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Otevřít..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Uložit" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Uložit &jako..." -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Znovu naÄíst" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "U&konÄit" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&ZpÄ›t" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "Zn&ovu" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "&Vyjmout" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Kopírovat" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "V&ložit" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "Odsad&it" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "&Zakomentovat" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "&Odkomentovat" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Vložit posun pohledu" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Vložit rotaci pohledu" -#: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" +#: objects/ui_MainWindow.h:868 +#, fuzzy +msgid "Increase Font &Size" msgstr "ZvÄ›tÅ¡it písmo" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" +#: objects/ui_MainWindow.h:870 +#, fuzzy +msgid "Decrease Font Si&ze" msgstr "ZmenÅ¡it písmo" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Skrýt editor" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "Znovu &naÄíst a zobrazit" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:878 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" msgstr "Vy&renderovat" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:880 -msgid "Check Validity" +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" msgstr "Zkontrolovat správnost" -#: objects/ui_MainWindow.h:881 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Ukázat &ATS..." -#: objects/ui_MainWindow.h:882 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Ukázat CSG s&trom..." -#: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Ukázat CSG &produkty..." -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Exportovat jako &STL..." -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Exportovat jako &OFF..." -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Náhled" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "Povrchy" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "Drátové zobrazení" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "VÅ¡e spoleÄnÄ›" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Zobrazit hrany" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Zobrazit osy" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Zobrazit zaměřovaÄ" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 msgid "Show Scale Markers" msgstr "Zobrazit pravítko" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animovat" -#: objects/ui_MainWindow.h:902 -msgid "Top" -msgstr "Shora" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Zespoda" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:906 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Zleva" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:908 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Zprava" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:910 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "ZepÅ™edu" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:912 -msgid "Back" -msgstr "Zezadu" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "DiagonálnÄ›" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:916 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "Vycentrovat" -#: objects/ui_MainWindow.h:917 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "PerspektivnÄ›" -#: objects/ui_MainWindow.h:918 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "OrtogonálnÄ›" -#: objects/ui_MainWindow.h:919 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Skrýt terminál" -#: objects/ui_MainWindow.h:920 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "O aplikaci" -#: objects/ui_MainWindow.h:921 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "Dokumentace" -#: objects/ui_MainWindow.h:922 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Zapomenout nedávné" -#: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "Exportovat jako &DXF" -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Zavřít" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "PÅ™edvolby" -#: objects/ui_MainWindow.h:927 -msgid "Find..." +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." msgstr "Najít..." -#: objects/ui_MainWindow.h:928 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." msgstr "Najít a nahradit..." -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" msgstr "Najít další" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" msgstr "Najít pÅ™edchozí" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" msgstr "Hledat vybraný Å™etÄ›zec" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:937 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "Vyprázdnit mezipaměť" -#: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "Domovská stránka OpenSCADu" -#: objects/ui_MainWindow.h:939 -msgid "Automatic Reload and Preview" +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" msgstr "Automaticky naÄítat a zobrazovat" -#: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." msgstr "Exportovat jako obrázek..." -#: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "Exportovat jako CSG..." -#: objects/ui_MainWindow.h:942 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Informace o knihovnách" -#: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Adresář s knihovnami..." -#: objects/ui_MainWindow.h:944 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Výchozí pohled" -#: objects/ui_MainWindow.h:945 -msgid "Font List" +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" msgstr "Seznam písem" -#: objects/ui_MainWindow.h:946 -msgid "Export as SVG..." +#: objects/ui_MainWindow.h:945 +#, fuzzy +msgid "Export as S&VG..." msgstr "Exportovat jako SVG..." -#: objects/ui_MainWindow.h:947 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +#, fuzzy +msgid "Export as &AMF..." msgstr "Exportovat jako AMF..." -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:947 msgid "Zoom In" msgstr "PÅ™iblížit" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "Oddálit" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "Zobrazit vÅ¡e" -#: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" msgstr "PÅ™evést tabulátory na mezery" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Skrýt nástrojové liÅ¡ty" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" msgstr "Z&ruÅ¡it odsazení" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" -#: objects/ui_MainWindow.h:957 -msgid "Cheat Sheet" +#: objects/ui_MainWindow.h:956 +#, fuzzy +msgid "&Cheat Sheet" msgstr "Tahák" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:957 msgid "Message" msgstr "Zpráva" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "ÄŒas:" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Kroky:" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Ukládat obrázky" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Soubor" -#: objects/ui_MainWindow.h:966 -msgid "Recent Files" +#: objects/ui_MainWindow.h:965 +#, fuzzy +msgid "Recen&t Files" msgstr "Nedávné soubory" -#: objects/ui_MainWindow.h:968 -msgid "Export" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Příklady" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" msgstr "Exportovat" -#: objects/ui_MainWindow.h:969 +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Upravit" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "&Design" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Zobrazit" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&NápovÄ›da" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Najít" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Nahradit" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Hledaný Å™etÄ›zec" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Hotovo" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Nahradit za" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "VÅ¡e" @@ -714,6 +760,14 @@ msgstr "Povolit OpenCSG" msgid "Show this message again" msgstr "Zobrazit tuto zprávu znovu" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Zavřít" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "PÅ™edvolby" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D zobrazení" @@ -984,15 +1038,7 @@ msgstr "Zobrazovat uvítací obrazovku" msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Povolit lokalizaci rozhraní OpenSCADu (vyžaduje restart aplikace)" -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" @@ -1112,17 +1158,7 @@ msgstr "" "Fontconfig potÅ™ebuje aktualizovat cache.\n" "To může trvat až nÄ›kolik minut." -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" -"\n" -"Používám QGLWidget\n" -"\n" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -1130,7 +1166,7 @@ msgstr "" "Varování: Můžete zaznamenat chyby zobrazení pomocí OpenCSG.\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -1139,7 +1175,7 @@ msgstr "" "Varování: Chybí OpenGL funkce pro OpenCSG - OpenCSG bylo vypnuto.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -1148,7 +1184,7 @@ msgstr "" "Vysoce doporuÄujeme používat OpenSCAD na systému s OpenGL 2.0 nebo novÄ›jší.\n" "Zde je informace o vaÅ¡em vykreslovacím systému:\n" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -1175,6 +1211,21 @@ msgstr "Tvary" msgid "Extrusion" msgstr "Vytažení" +#~ msgid "Top" +#~ msgstr "Shora" + +#~ msgid "Back" +#~ msgstr "Zezadu" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Používám QGLWidget\n" +#~ "\n" + #~ msgid "About OpenSCAD " #~ msgstr "O OpenSCADu " diff --git a/locale/es.po b/locale/es.po index e5184516..cdf29b7b 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2015.01.21\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" "PO-Revision-Date: 2015-01-21 22:36-0300\n" "Last-Translator: Ernesto Bazzano \n" "Language-Team: Español\n" @@ -115,7 +115,6 @@ msgid "Open Recent" msgstr "Abrir recientes" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Ejemplos" @@ -140,564 +139,608 @@ msgstr "Informacion de las librerias y compilación" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Informations detalles de las librerias y compilación" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Nuevos" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Abrir..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Salvar" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "S&alvar como..." -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Recargar" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "Salir" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "An&ular" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Repetir" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Co&rtar" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Copiar" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "&Pegar" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" # no se que es -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "&Indenter" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "C&omentar" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "Desco&mentar" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Pegar posición de la marco" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Pegar rotación de la ventana" -#: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" +#: objects/ui_MainWindow.h:868 +msgid "Increase Font &Size" msgstr "" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" msgstr "" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Ocultar editor" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "&Recargar y previsualizar" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "&Previsualizar" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:878 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" msgstr "&Renderizar" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:880 -msgid "Check Validity" +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" msgstr "Chequear validez" -#: objects/ui_MainWindow.h:881 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Mostrar &AST..." -#: objects/ui_MainWindow.h:882 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Mostrar CSG &Arbre" -#: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Mostar CSG &Produits" -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Exportar como &STL..." -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Exportar como &OFF..." -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Previsualizar" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "Superficie" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "Estructura" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Lanzar Juntos" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Mostrar puntos" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Mostrar ejes" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Mostrar punto de mira" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 msgid "Show Scale Markers" msgstr "" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animar" -#: objects/ui_MainWindow.h:902 -msgid "Top" -msgstr "Arriba" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Abajo" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:906 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Izquierda" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:908 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Derecha" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:910 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "Frente" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:912 -msgid "Back" -msgstr "Atrás" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "Diagonal" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:916 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "Centro" -#: objects/ui_MainWindow.h:917 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "Perspectiva" -#: objects/ui_MainWindow.h:918 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "Orthogonal" -#: objects/ui_MainWindow.h:919 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Ocultar consola" -#: objects/ui_MainWindow.h:920 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "Acerca de" -#: objects/ui_MainWindow.h:921 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "Documentación" -#: objects/ui_MainWindow.h:922 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Borrar recientes" -#: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "Exportar a DXF..." -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Cerrar" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "Preferencias" -#: objects/ui_MainWindow.h:927 -msgid "Find..." +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." msgstr "Buscar..." -#: objects/ui_MainWindow.h:928 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." msgstr "Buscar y reemplazar..." -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" msgstr "Buscar próximo" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" msgstr "Buscar previo" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" msgstr "Buscar selección" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:937 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "Borrar cache" -#: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "Pagina de OpenSCAD" -#: objects/ui_MainWindow.h:939 -msgid "Automatic Reload and Preview" +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" msgstr "Recargar y previsualizar automáticamente" -#: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." msgstr "Exportar imagen..." -#: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "Exportar en CSG..." -#: objects/ui_MainWindow.h:942 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Información de librerías" -#: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Mostrar carpeta de librerías" -#: objects/ui_MainWindow.h:944 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Reiniciar vista" -#: objects/ui_MainWindow.h:945 -msgid "Font List" +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" msgstr "Lista de fuentes" -#: objects/ui_MainWindow.h:946 -msgid "Export as SVG..." +#: objects/ui_MainWindow.h:945 +#, fuzzy +msgid "Export as S&VG..." msgstr "Exportar en SVG..." -#: objects/ui_MainWindow.h:947 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +#, fuzzy +msgid "Export as &AMF..." msgstr "Exportar en AMF..." -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:947 msgid "Zoom In" msgstr "Acercar" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "Alejar" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "Ver todo" -#: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" msgstr "Convertir tabulado en espacios" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Ocultar barra de herramientas" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" msgstr "Dési&ndenter" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" -#: objects/ui_MainWindow.h:957 -msgid "Cheat Sheet" +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" msgstr "" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:957 msgid "Message" msgstr "" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Tiempo:" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Pasos:" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Grabar imágenes" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Archivo" -#: objects/ui_MainWindow.h:966 -msgid "Recent Files" +#: objects/ui_MainWindow.h:965 +#, fuzzy +msgid "Recen&t Files" msgstr "Archivos recientes" -#: objects/ui_MainWindow.h:968 -msgid "Export" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Ejemplos" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" msgstr "Exportar" -#: objects/ui_MainWindow.h:969 +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Editar" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "&Diseñar" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Ver" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Ayuda" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Buscar" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Reemplazar" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Buscar palabra" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Terminar" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Remplazar palabra" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Todo" @@ -737,6 +780,14 @@ msgstr "Activar OpenCSG" msgid "Show this message again" msgstr "Mostrar el mensaje de nuevo" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Cerrar" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Preferencias" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "Vista 3D" @@ -1021,15 +1072,7 @@ msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" "Habilitar interfaz de usuario localización (requiere reiniciar OpenSCAD)" -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "barra de herramientas" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "Formulario" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" @@ -1146,17 +1189,7 @@ msgid "" "This can take up to a couple of minutes." msgstr "" -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" -"\n" -"Utilizar QGLWidget\n" -"\n" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -1164,7 +1197,7 @@ msgstr "" "Advertencia: Usted puede experimentar OpenCSG errores de renderizado.\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -1174,7 +1207,7 @@ msgstr "" "desactivada. .\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -1184,7 +1217,7 @@ msgstr "" "posterior.\n" "Su información renderer es como sigue:\n" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -1211,6 +1244,27 @@ msgstr "Formas" msgid "Extrusion" msgstr "Extrusión" +#~ msgid "Top" +#~ msgstr "Arriba" + +#~ msgid "Back" +#~ msgstr "Atrás" + +#~ msgid "toolBar" +#~ msgstr "barra de herramientas" + +#~ msgid "Form" +#~ msgstr "Formulario" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Utilizar QGLWidget\n" +#~ "\n" + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Coller le sélecteur de polices dans l'éditeur de fenêtres" diff --git a/locale/fr.po b/locale/fr.po index 5964c052..eaa37802 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2013.02.07\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" "PO-Revision-Date: 2015-01-27 18:47-0500\n" "Last-Translator: Keven Villeneuve \n" "Language-Team: French\n" @@ -114,7 +114,6 @@ msgid "Open Recent" msgstr "Ouvrir un fichier récent" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Exemples" @@ -138,563 +137,610 @@ msgstr "Bibliothèques et Infos de la version" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Informations détaillées des bibliothèques et de la version d'OpenSCAD" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Nouveau" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Ouvrir..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "Enregi&strer" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Enregistrer &sous..." -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Recharger" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "&Quitter" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "Ann&uler" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Répéter" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Co&uper" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Copier" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "&Coller" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "&Indenter" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "C&ommenter" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "Déco&mmenter" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Coller la translation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Coller la rotation de la fenêtre de rendu" -#: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" +#: objects/ui_MainWindow.h:868 +#, fuzzy +msgid "Increase Font &Size" msgstr "Agrandir la police" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" +#: objects/ui_MainWindow.h:870 +#, fuzzy +msgid "Decrease Font Si&ze" msgstr "Réduire la police" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Cacher l'éditeur" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "&Recharger et Aperçu" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "&Aperçu" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:878 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +#, fuzzy +msgid "R&ender" msgstr "&Rendu" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:880 -msgid "Check Validity" +#: objects/ui_MainWindow.h:879 +#, fuzzy +msgid "&Check Validity" msgstr "Vérifier la Validité" -#: objects/ui_MainWindow.h:881 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Afficher &AST..." -#: objects/ui_MainWindow.h:882 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Afficher CSG &Arbre" -#: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Afficher CSG &Produits" -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "Exporter comme &STL..." -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "Exporter comme &OFF..." -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Aperçu" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "Surfaces" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "Wireframe" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Jeté ensemble" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Afficher les Arêtes" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Afficher les Axes" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Afficher la Mire" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 msgid "Show Scale Markers" msgstr "Afficher les Marqueurs d'Échelle" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animer" -#: objects/ui_MainWindow.h:902 -msgid "Top" -msgstr "Dessus" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Dessous" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:906 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Gauche" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:908 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Droite" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:910 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "Face" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:912 -msgid "Back" -msgstr "Arrière" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "Diagonale" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:916 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "Centre" -#: objects/ui_MainWindow.h:917 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "Perspective" -#: objects/ui_MainWindow.h:918 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "Orthogonale" -#: objects/ui_MainWindow.h:919 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Cache la console" -#: objects/ui_MainWindow.h:920 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "À propos" -#: objects/ui_MainWindow.h:921 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "Documentation" -#: objects/ui_MainWindow.h:922 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Effacer Récents" -#: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "Exporter comme DXF..." -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Fermer" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "Préférences" -#: objects/ui_MainWindow.h:927 -msgid "Find..." +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." msgstr "Rechercher..." -#: objects/ui_MainWindow.h:928 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." msgstr "Rechercher et remplacer..." -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" msgstr "Rechercher Suivant" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" msgstr "Rechercher Précédent" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" msgstr "Utiliser la sélection pour Rechercher" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:937 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "Vider les caches" -#: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "Page d'accueil OpenSCAD" -#: objects/ui_MainWindow.h:939 -msgid "Automatic Reload and Preview" +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" msgstr "Recharger et Aperçu Automatique" -#: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +#: objects/ui_MainWindow.h:939 +#, fuzzy +msgid "Export as &Image..." msgstr "Exporter comme Image..." -#: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "Exporter comme CSG..." -#: objects/ui_MainWindow.h:942 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Informations Bibliothèques" -#: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Afficher le dossier des bibliothèques" -#: objects/ui_MainWindow.h:944 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Réinitialiser la vue" -#: objects/ui_MainWindow.h:945 -msgid "Font List" +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" msgstr "Liste des polices" -#: objects/ui_MainWindow.h:946 -msgid "Export as SVG..." +#: objects/ui_MainWindow.h:945 +#, fuzzy +msgid "Export as S&VG..." msgstr "Exporter comme SVG..." -#: objects/ui_MainWindow.h:947 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +#, fuzzy +msgid "Export as &AMF..." msgstr "Exporter comme AMF..." -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:947 msgid "Zoom In" msgstr "Zoom Avant" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "Zoom Arrière" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "&Voir Tout" -#: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" msgstr "Convertir les tabulations par des espaces" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "Cacher les boîtes à outils" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" msgstr "Dési&ndenter" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" -#: objects/ui_MainWindow.h:957 -msgid "Cheat Sheet" +#: objects/ui_MainWindow.h:956 +#, fuzzy +msgid "&Cheat Sheet" msgstr "Aide-Mémoire" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:957 msgid "Message" msgstr "Message" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Temps:" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Étapes:" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Vider les photos" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Fichier" -#: objects/ui_MainWindow.h:966 -msgid "Recent Files" +#: objects/ui_MainWindow.h:965 +#, fuzzy +msgid "Recen&t Files" msgstr "Fichiers Récents" -#: objects/ui_MainWindow.h:968 -msgid "Export" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Exemples" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" msgstr "Exporter" -#: objects/ui_MainWindow.h:969 +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Édition" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "Conception" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Vue" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Aide" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Rechercher" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Remplacer" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Rechercher une chaîne de caractères" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Terminer" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Remplacer une chaîne de caractères" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Tout" @@ -734,6 +780,14 @@ msgstr "Activer OpenCSG" msgid "Show this message again" msgstr "Affiche ce message à nouveau" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Fermer" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Préférences" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "&Vue 3D" @@ -1007,15 +1061,7 @@ msgstr "" "Activer la localisation de l'interface utilisateur (Nécessite un redémarrage " "d'OpenSCAD)" -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "boîte à outils" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "Formulaire" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" @@ -1134,17 +1180,7 @@ msgstr "" "Fontconfig a besoin de mettre à jour son cache de polices.\n" "Celà peut prendre quelques minutes." -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" -"\n" -"Utilise QGLWidget\n" -"\n" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -1152,7 +1188,7 @@ msgstr "" "Avertissement: Vous pourriez avoir des erreurs de rendu OpenCSG\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -1162,7 +1198,7 @@ msgstr "" "désactivé.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -1172,7 +1208,7 @@ msgstr "" "OpenGL 2.0 ou ultérieur.\n" "Voici les informations de votre moteur de rendu:\n" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -1199,6 +1235,27 @@ msgstr "Formes" msgid "Extrusion" msgstr "Extrusion" +#~ msgid "Top" +#~ msgstr "Dessus" + +#~ msgid "Back" +#~ msgstr "Arrière" + +#~ msgid "toolBar" +#~ msgstr "boîte à outils" + +#~ msgid "Form" +#~ msgstr "Formulaire" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Utilise QGLWidget\n" +#~ "\n" + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Coller le sélecteur de polices dans l'éditeur de fenêtres" diff --git a/locale/openscad.pot b/locale/openscad.pot index 3d590ff3..fc958879 100644 --- a/locale/openscad.pot +++ b/locale/openscad.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: OpenSCAD 2015.01.24\n" +"Project-Id-Version: OpenSCAD 2015.02.01\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" +"POT-Creation-Date: 2015-02-01 19:40+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -94,7 +94,6 @@ msgid "Open Recent" msgstr "" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "" @@ -118,563 +117,567 @@ msgstr "" msgid "OpenSCAD Detailed Library and Build Information" msgstr "" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "" -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "" -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +msgid "P&aste viewport translation" msgstr "" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "" +#: objects/ui_MainWindow.h:867 +msgid "Past&e viewport rotation" +msgstr "" + #: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" +msgid "Increase Font &Size" msgstr "" #: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" -msgstr "" - -#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" msgstr "" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +msgid "H&ide editor" msgstr "" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" msgstr "" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 msgid "&Preview" msgstr "" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "" -#: objects/ui_MainWindow.h:878 -msgid "&Render" +#: objects/ui_MainWindow.h:877 +msgid "R&ender" msgstr "" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "" +#: objects/ui_MainWindow.h:879 +msgid "&Check Validity" +msgstr "" + #: objects/ui_MainWindow.h:880 -msgid "Check Validity" +msgid "Display A&ST..." msgstr "" #: objects/ui_MainWindow.h:881 -msgid "Display &AST..." -msgstr "" - -#: objects/ui_MainWindow.h:882 msgid "Display CSG &Tree..." msgstr "" -#: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +msgid "Display CSG Pr&oducts..." msgstr "" -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "" -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "" -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" msgstr "" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 msgid "Show Scale Markers" msgstr "" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "" -#: objects/ui_MainWindow.h:902 -msgid "Top" +#: objects/ui_MainWindow.h:901 +msgid "&Top" msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +msgid "&Bottom" msgstr "" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "" -#: objects/ui_MainWindow.h:906 -msgid "Left" +#: objects/ui_MainWindow.h:905 +msgid "&Left" msgstr "" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "" -#: objects/ui_MainWindow.h:908 -msgid "Right" +#: objects/ui_MainWindow.h:907 +msgid "&Right" msgstr "" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "" -#: objects/ui_MainWindow.h:910 -msgid "Front" +#: objects/ui_MainWindow.h:909 +msgid "&Front" msgstr "" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "" -#: objects/ui_MainWindow.h:912 -msgid "Back" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +msgid "&Diagonal" msgstr "" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "" +#: objects/ui_MainWindow.h:915 +msgid "Ce&nter" +msgstr "" + #: objects/ui_MainWindow.h:916 -msgid "Center" +msgid "&Perspective" msgstr "" #: objects/ui_MainWindow.h:917 -msgid "Perspective" +msgid "&Orthogonal" msgstr "" #: objects/ui_MainWindow.h:918 -msgid "Orthogonal" +msgid "H&ide console" msgstr "" #: objects/ui_MainWindow.h:919 -msgid "Hide console" +msgid "&About" msgstr "" #: objects/ui_MainWindow.h:920 -msgid "About" +msgid "&Documentation" msgstr "" #: objects/ui_MainWindow.h:921 -msgid "Documentation" -msgstr "" - -#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "" +#: objects/ui_MainWindow.h:922 +msgid "Export as &DXF..." +msgstr "" + #: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +msgid "&Close" msgstr "" -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" -msgstr "" - -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +msgid "&Preferences" +msgstr "" + +#: objects/ui_MainWindow.h:926 +msgid "&Find..." msgstr "" #: objects/ui_MainWindow.h:927 -msgid "Find..." -msgstr "" - -#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +msgid "Fin&d and Replace..." msgstr "" -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +msgid "Find Ne&xt" msgstr "" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +msgid "Find Pre&vious" msgstr "" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +msgid "Use Se&lection for Find" msgstr "" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "" +#: objects/ui_MainWindow.h:936 +msgid "&Flush Caches" +msgstr "" + #: objects/ui_MainWindow.h:937 -msgid "Flush Caches" +msgid "&OpenSCAD Homepage" msgstr "" #: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" +msgid "&Automatic Reload and Preview" msgstr "" #: objects/ui_MainWindow.h:939 -msgid "Automatic Reload and Preview" +msgid "Export as &Image..." msgstr "" #: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +msgid "Export as &CSG..." msgstr "" #: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +msgid "&Library info" msgstr "" #: objects/ui_MainWindow.h:942 -msgid "Library info" +msgid "Show &Library Folder..." msgstr "" #: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." -msgstr "" - -#: objects/ui_MainWindow.h:944 msgid "Reset View" msgstr "" +#: objects/ui_MainWindow.h:944 +msgid "&Font List" +msgstr "" + #: objects/ui_MainWindow.h:945 -msgid "Font List" +msgid "Export as S&VG..." msgstr "" #: objects/ui_MainWindow.h:946 -msgid "Export as SVG..." +msgid "Export as &AMF..." msgstr "" #: objects/ui_MainWindow.h:947 -msgid "Export as AMF..." -msgstr "" - -#: objects/ui_MainWindow.h:948 msgid "Zoom In" msgstr "" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 msgid "View All" msgstr "" -#: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +msgid "Conv&ert Tabs to Spaces" msgstr "" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:953 msgid "Hide toolbars" msgstr "" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" msgstr "" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "" -#: objects/ui_MainWindow.h:957 -msgid "Cheat Sheet" +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" msgstr "" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:957 msgid "Message" msgstr "" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "" +#: objects/ui_MainWindow.h:965 +msgid "Recen&t Files" +msgstr "" + #: objects/ui_MainWindow.h:966 -msgid "Recent Files" +msgid "&Examples" +msgstr "" + +#: objects/ui_MainWindow.h:967 +msgid "E&xport" msgstr "" #: objects/ui_MainWindow.h:968 -msgid "Export" -msgstr "" - -#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr "" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "" @@ -704,6 +707,14 @@ msgstr "" msgid "Show this message again" msgstr "" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "" @@ -974,15 +985,7 @@ msgstr "" msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "" -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "" @@ -1093,34 +1096,27 @@ msgid "" "This can take up to a couple of minutes." msgstr "" -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" msgstr "" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" diff --git a/locale/ru.po b/locale/ru.po index f08ac497..8e6f6e0e 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" "PO-Revision-Date: 2013-02-24 17:50+0100\n" "Last-Translator: \n" "Language-Team: Russian\n" @@ -100,7 +100,6 @@ msgid "Open Recent" msgstr "Открыть недавние" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Примеры" @@ -125,578 +124,617 @@ msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñборке" msgid "OpenSCAD Detailed Library and Build Information" msgstr "ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ библиотеках и Ñборке OpenSCAD" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Создать" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." msgstr "&Открыть..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Сохранить" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Сохранить &как..." -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "&Обновить" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" msgstr "&Выход" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&Отменить" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Повторить" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Ð’Ñ‹&резать" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "&Копировать" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "&Ð’Ñтавить" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" msgstr "&Добавить отÑтуп" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "Зако&мментировать" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" msgstr "Р&аÑкомментировать" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" +#: objects/ui_MainWindow.h:865 +#, fuzzy +msgid "P&aste viewport translation" msgstr "Ð’Ñтавить Ñмещение точки обзора" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" -#: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" +#: objects/ui_MainWindow.h:867 +#, fuzzy +msgid "Past&e viewport rotation" msgstr "Ð’Ñтавить поворот точки обзора" -#: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" +#: objects/ui_MainWindow.h:868 +#, fuzzy +msgid "Increase Font &Size" msgstr "Увеличить размер шрифта" -#: objects/ui_MainWindow.h:870 +#: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" +#: objects/ui_MainWindow.h:870 +#, fuzzy +msgid "Decrease Font Si&ze" msgstr "Уменьшить размер шрифта" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +#, fuzzy +msgid "H&ide editor" msgstr "Скрыть редактор" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 #, fuzzy msgid "&Reload and Preview" msgstr "&Обновить и компилировать" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 #, fuzzy msgid "&Preview" msgstr "&Превью" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:878 +#: objects/ui_MainWindow.h:877 #, fuzzy -msgid "&Render" +msgid "R&ender" msgstr "&Рендер" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" -#: objects/ui_MainWindow.h:880 +#: objects/ui_MainWindow.h:879 #, fuzzy -msgid "Check Validity" +msgid "&Check Validity" msgstr "Проверить" -#: objects/ui_MainWindow.h:881 -msgid "Display &AST..." +#: objects/ui_MainWindow.h:880 +#, fuzzy +msgid "Display A&ST..." msgstr "Показать &AST..." -#: objects/ui_MainWindow.h:882 +#: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Показать &дерево CSG..." -#: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." +#: objects/ui_MainWindow.h:882 +#, fuzzy +msgid "Display CSG Pr&oducts..." msgstr "Показать &результаты CSG..." -#: objects/ui_MainWindow.h:884 +#: objects/ui_MainWindow.h:883 msgid "Export as &STL..." msgstr "ЭкÑпортировать в &STL..." -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "ЭкÑпортировать в &OFF..." -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" msgstr "Превью" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 #, fuzzy msgid "Surfaces" msgstr "ПоверхноÑти CGAL" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" msgstr "" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" msgstr "Ð’ÑÑ‘ вмеÑте" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" msgstr "Показывать рёбра" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" msgstr "Показывать оÑи" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" msgstr "Показывать перекреÑтиÑ" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 #, fuzzy msgid "Show Scale Markers" msgstr "Показать метки маÑштаба" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "ÐнимациÑ" -#: objects/ui_MainWindow.h:902 -msgid "Top" -msgstr "Сверху" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" +#: objects/ui_MainWindow.h:903 +#, fuzzy +msgid "&Bottom" msgstr "Снизу" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:906 -msgid "Left" +#: objects/ui_MainWindow.h:905 +#, fuzzy +msgid "&Left" msgstr "Слева" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:908 -msgid "Right" +#: objects/ui_MainWindow.h:907 +#, fuzzy +msgid "&Right" msgstr "Справа" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:910 -msgid "Front" +#: objects/ui_MainWindow.h:909 +#, fuzzy +msgid "&Front" msgstr "Спереди" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:912 -msgid "Back" -msgstr "Сзади" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" +#: objects/ui_MainWindow.h:913 +#, fuzzy +msgid "&Diagonal" msgstr "ÐкÑонометричеÑкий" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" -#: objects/ui_MainWindow.h:916 -msgid "Center" +#: objects/ui_MainWindow.h:915 +#, fuzzy +msgid "Ce&nter" msgstr "По центру" -#: objects/ui_MainWindow.h:917 -msgid "Perspective" +#: objects/ui_MainWindow.h:916 +#, fuzzy +msgid "&Perspective" msgstr "ПерÑпектива" -#: objects/ui_MainWindow.h:918 -msgid "Orthogonal" +#: objects/ui_MainWindow.h:917 +#, fuzzy +msgid "&Orthogonal" msgstr "ПрÑÐ¼Ð¾ÑƒÐ³Ð¾Ð»ÑŒÐ½Ð°Ñ Ð¿Ñ€Ð¾ÐµÐºÑ†Ð¸Ñ" -#: objects/ui_MainWindow.h:919 -msgid "Hide console" +#: objects/ui_MainWindow.h:918 +#, fuzzy +msgid "H&ide console" msgstr "Скрыть конÑоль" -#: objects/ui_MainWindow.h:920 -msgid "About" +#: objects/ui_MainWindow.h:919 +#, fuzzy +msgid "&About" msgstr "О программе" -#: objects/ui_MainWindow.h:921 -msgid "Documentation" +#: objects/ui_MainWindow.h:920 +#, fuzzy +msgid "&Documentation" msgstr "ДокументациÑ" -#: objects/ui_MainWindow.h:922 +#: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "ОчиÑтить ÑпиÑок" -#: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +#, fuzzy +msgid "Export as &DXF..." msgstr "ЭкÑпортировать в DXF..." -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +#, fuzzy +msgid "&Close" msgstr "Закрыть" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" +#: objects/ui_MainWindow.h:925 +#, fuzzy +msgid "&Preferences" msgstr "ÐаÑтройки" -#: objects/ui_MainWindow.h:927 -msgid "Find..." +#: objects/ui_MainWindow.h:926 +#, fuzzy +msgid "&Find..." msgstr "Ðайти..." -#: objects/ui_MainWindow.h:928 +#: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." +#: objects/ui_MainWindow.h:928 +#, fuzzy +msgid "Fin&d and Replace..." msgstr "Ðайти и замена..." -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" +#: objects/ui_MainWindow.h:930 +#, fuzzy +msgid "Find Ne&xt" msgstr "ИÑкать дальше" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" +#: objects/ui_MainWindow.h:932 +#, fuzzy +msgid "Find Pre&vious" msgstr "ИÑкать раньше" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" +#: objects/ui_MainWindow.h:934 +#, fuzzy +msgid "Use Se&lection for Find" msgstr "Ðайти выделенный текÑÑ‚" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" -#: objects/ui_MainWindow.h:937 -msgid "Flush Caches" +#: objects/ui_MainWindow.h:936 +#, fuzzy +msgid "&Flush Caches" msgstr "ОчиÑтить кÑш" -#: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" +#: objects/ui_MainWindow.h:937 +#, fuzzy +msgid "&OpenSCAD Homepage" msgstr "ДомашнÑÑ Ñтраница OpenSCAD" +#: objects/ui_MainWindow.h:938 +#, fuzzy +msgid "&Automatic Reload and Preview" +msgstr "ÐвтоматичеÑки обновлÑÑ‚ÑŒ и комилировать" + #: objects/ui_MainWindow.h:939 #, fuzzy -msgid "Automatic Reload and Preview" -msgstr "ÐвтоматичеÑки обновлÑÑ‚ÑŒ и комилировать" - -#: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +msgid "Export as &Image..." msgstr "ЭкÑпортировать в раÑÑ‚Ñ€..." -#: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +#, fuzzy +msgid "Export as &CSG..." msgstr "ЭкÑпортировать в CSG..." -#: objects/ui_MainWindow.h:942 -msgid "Library info" +#: objects/ui_MainWindow.h:941 +#, fuzzy +msgid "&Library info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ библиотеках" -#: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." +#: objects/ui_MainWindow.h:942 +#, fuzzy +msgid "Show &Library Folder..." msgstr "Открыть каталог библиотек..." -#: objects/ui_MainWindow.h:944 +#: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "СброÑить наÑтройки вида" +#: objects/ui_MainWindow.h:944 +#, fuzzy +msgid "&Font List" +msgstr "Шрифт" + #: objects/ui_MainWindow.h:945 #, fuzzy -msgid "Font List" -msgstr "Шрифт" +msgid "Export as S&VG..." +msgstr "ЭкÑпортировать в CSG..." #: objects/ui_MainWindow.h:946 #, fuzzy -msgid "Export as SVG..." -msgstr "ЭкÑпортировать в CSG..." - -#: objects/ui_MainWindow.h:947 -#, fuzzy -msgid "Export as AMF..." +msgid "Export as &AMF..." msgstr "ЭкÑпортировать в DXF..." -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:947 msgid "Zoom In" msgstr "Увеличить маÑштаб" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "Уменьшить маÑштаб" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 #, fuzzy msgid "View All" msgstr "&Вид" -#: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" +#: objects/ui_MainWindow.h:952 +#, fuzzy +msgid "Conv&ert Tabs to Spaces" msgstr "Преобразовать табулÑции в пробелы" -#: objects/ui_MainWindow.h:954 +#: objects/ui_MainWindow.h:953 #, fuzzy msgid "Hide toolbars" msgstr "Скрыть панель" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" msgstr "У&брать отÑтуп" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" -#: objects/ui_MainWindow.h:957 +#: objects/ui_MainWindow.h:956 #, fuzzy -msgid "Cheat Sheet" +msgid "&Cheat Sheet" msgstr "Указатель" -#: objects/ui_MainWindow.h:958 +#: objects/ui_MainWindow.h:957 msgid "Message" msgstr "Сообщение" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "ВремÑ:" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "Кадров в Ñекунду:" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Шагов:" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "СохранÑÑ‚ÑŒ кадры" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Файл" -#: objects/ui_MainWindow.h:966 +#: objects/ui_MainWindow.h:965 #, fuzzy -msgid "Recent Files" +msgid "Recen&t Files" msgstr "Открыть файл" -#: objects/ui_MainWindow.h:968 -msgid "Export" +#: objects/ui_MainWindow.h:966 +#, fuzzy +msgid "&Examples" +msgstr "Примеры" + +#: objects/ui_MainWindow.h:967 +#, fuzzy +msgid "E&xport" msgstr "ЭкÑпорт" -#: objects/ui_MainWindow.h:969 +#: objects/ui_MainWindow.h:968 msgid "&Edit" msgstr "&Правка" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "&Модель" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Вид" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Справка" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Ðайти" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Заменить" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Строка поиÑка" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Готово" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 #, fuzzy msgid "Replacement string" msgstr "Ñлементах" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Ð’Ñе" @@ -727,6 +765,14 @@ msgstr "Включить Ð´Ð»Ñ OpenGL 1.x" msgid "Show this message again" msgstr "" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Закрыть" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "ÐаÑтройки" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Вид" @@ -1010,15 +1056,7 @@ msgstr "Показать Ñкран преветÑтвиÑ" msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Включить локализацию интерфейÑа (необходимо перезапуÑтить OpenSCAD)" -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "Панель инÑтрументов" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "" @@ -1146,14 +1184,7 @@ msgstr "" "Fontconfig требуетÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ñ‚ÑŒ кеш шрифтов.\n" "Это может занÑÑ‚ÑŒ пару минут." -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -1161,27 +1192,27 @@ msgstr "" "Предупреждение: Возможны ошибки рендринга OpenCSG.\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" "\n" msgstr "" -"Предупреждение: Ðе найдены OpenGL раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð´Ð»Ñ OpenCSG - OpenCSG " -"был отключен.\n" +"Предупреждение: Ðе найдены OpenGL раÑÑˆÐ¸Ñ€ÐµÐ½Ð¸Ñ Ð´Ð»Ñ OpenCSG - OpenCSG был " +"отключен.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" "Your renderer information is as follows:\n" msgstr "" -"Крайне рекомендуетÑÑ Ð¸Ñпользовать OpenSCAD на ÑиÑтеме Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ " -" OpenGL 2.0 или новее.\n" +"Крайне рекомендуетÑÑ Ð¸Ñпользовать OpenSCAD на ÑиÑтеме Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¾Ð¹ OpenGL " +"2.0 или новее.\n" "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ рендере:\n" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -1205,6 +1236,15 @@ msgstr "Формы" msgid "Extrusion" msgstr "Выдавливание" +#~ msgid "Top" +#~ msgstr "Сверху" + +#~ msgid "Back" +#~ msgstr "Сзади" + +#~ msgid "toolBar" +#~ msgstr "Панель инÑтрументов" + #~ msgid "Check for Update.." #~ msgstr "Проверить обновлениÑ..." From fa233049c70e57de9934f12e8a0bade7c81612dc Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 1 Feb 2015 19:44:11 +0100 Subject: [PATCH 149/174] Fix translation of combobox values in preferences. --- src/Preferences.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Preferences.cc b/src/Preferences.cc index 93900a0e..0ad84324 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -698,8 +698,9 @@ void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntr Value::VectorType vector = entry.range().toVector(); for (Value::VectorType::iterator it = vector.begin();it != vector.end();it++) { QString val = QString::fromStdString((*it)[0].toString()); - QString text = QString::fromStdString((*it)[1].toString()); - comboBox->addItem(text, val); + std::string text((*it)[1].toString()); + QString qtext = QString::fromStdString(gettext(text.c_str())); + comboBox->addItem(qtext, val); } } From af8c938c8ce81823e2178cede2d95a32e4be80ef Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 1 Feb 2015 19:44:30 +0100 Subject: [PATCH 150/174] Update German translation. --- locale/de.po | 620 ++++++++++++++++++++++++++------------------------- 1 file changed, 312 insertions(+), 308 deletions(-) diff --git a/locale/de.po b/locale/de.po index 552b211c..1f017695 100644 --- a/locale/de.po +++ b/locale/de.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: OpenSCAD 2014.01.05\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-24 20:49+0100\n" -"PO-Revision-Date: 2014-12-22 23:12+0100\n" +"POT-Creation-Date: 2015-02-01 18:03+0100\n" +"PO-Revision-Date: 2015-02-01 19:39+0100\n" "Last-Translator: Torsten Paul \n" "Language-Team: German\n" "Language: de\n" @@ -17,6 +17,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 1.6.10\n" "X-Poedit-SourceCharset: UTF-8\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 msgid "About OpenSCAD" @@ -47,7 +48,6 @@ msgstr "" "\n" #: objects/ui_AboutDialog.h:112 -#, fuzzy msgid "OK" msgstr "OK" @@ -114,7 +114,6 @@ msgid "Open Recent" msgstr "Datei öffnen" #: objects/ui_launchingscreen.h:300 objects/ui_launchingscreen.h:302 -#: objects/ui_MainWindow.h:967 msgid "Examples" msgstr "Beispiele" @@ -127,9 +126,8 @@ msgid "Don't show again" msgstr "Dialog nicht wieder anzeigen" #: objects/ui_launchingscreen.h:313 -#, fuzzy msgid "Version" -msgstr "Extrusion" +msgstr "Version" #: objects/ui_LibraryInfoDialog.h:75 msgid "Lib & Build Info" @@ -139,564 +137,567 @@ msgstr "Versionsinformationen" msgid "OpenSCAD Detailed Library and Build Information" msgstr "Detailierte Informationen über diese OpenSCAD Version" -#: objects/ui_MainWindow.h:838 +#: objects/ui_MainWindow.h:837 msgid "&New" msgstr "&Neu" -#: objects/ui_MainWindow.h:839 +#: objects/ui_MainWindow.h:838 msgid "Ctrl+N" msgstr "Ctrl+N" -#: objects/ui_MainWindow.h:840 +#: objects/ui_MainWindow.h:839 msgid "&Open..." -msgstr "Ö&ffnen" +msgstr "Ö&ffnen..." -#: objects/ui_MainWindow.h:841 +#: objects/ui_MainWindow.h:840 msgid "Ctrl+O" msgstr "Ctrl+O" -#: objects/ui_MainWindow.h:842 +#: objects/ui_MainWindow.h:841 msgid "&Save" msgstr "&Speichern" -#: objects/ui_MainWindow.h:843 +#: objects/ui_MainWindow.h:842 msgid "Ctrl+S" msgstr "Ctrl+S" -#: objects/ui_MainWindow.h:844 +#: objects/ui_MainWindow.h:843 msgid "Save &As..." msgstr "Speichern &Unter..." -#: objects/ui_MainWindow.h:845 +#: objects/ui_MainWindow.h:844 msgid "Ctrl+Shift+S" msgstr "Ctrl+Shift+S" -#: objects/ui_MainWindow.h:846 +#: objects/ui_MainWindow.h:845 msgid "&Reload" msgstr "Neu &laden" -#: objects/ui_MainWindow.h:847 +#: objects/ui_MainWindow.h:846 msgid "Ctrl+R" msgstr "Ctrl+R" -#: objects/ui_MainWindow.h:848 +#: objects/ui_MainWindow.h:847 msgid "&Quit" -msgstr "&Beenden" +msgstr "Beenden" -#: objects/ui_MainWindow.h:849 +#: objects/ui_MainWindow.h:848 msgid "Ctrl+Q" msgstr "Ctrl+Q" -#: objects/ui_MainWindow.h:850 +#: objects/ui_MainWindow.h:849 msgid "&Undo" msgstr "&Rückgängig" -#: objects/ui_MainWindow.h:851 +#: objects/ui_MainWindow.h:850 msgid "Ctrl+Z" msgstr "Ctrl+Z" -#: objects/ui_MainWindow.h:852 +#: objects/ui_MainWindow.h:851 msgid "&Redo" msgstr "&Wiederholen" -#: objects/ui_MainWindow.h:853 +#: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" msgstr "Ctrl+Shift+Z" -#: objects/ui_MainWindow.h:854 +#: objects/ui_MainWindow.h:853 msgid "Cu&t" msgstr "Ausschneiden" -#: objects/ui_MainWindow.h:855 +#: objects/ui_MainWindow.h:854 msgid "Ctrl+X" msgstr "Ctrl+X" -#: objects/ui_MainWindow.h:856 +#: objects/ui_MainWindow.h:855 msgid "&Copy" msgstr "Kopieren" -#: objects/ui_MainWindow.h:857 +#: objects/ui_MainWindow.h:856 msgid "Ctrl+C" msgstr "Ctrl+C" -#: objects/ui_MainWindow.h:858 +#: objects/ui_MainWindow.h:857 msgid "&Paste" msgstr "Einfügen" -#: objects/ui_MainWindow.h:859 +#: objects/ui_MainWindow.h:858 msgid "Ctrl+V" msgstr "Ctrl+V" -#: objects/ui_MainWindow.h:860 +#: objects/ui_MainWindow.h:859 msgid "&Indent" -msgstr "Einzug erhöhen" +msgstr "Einzug er&höhen" -#: objects/ui_MainWindow.h:861 +#: objects/ui_MainWindow.h:860 msgid "Ctrl+I" msgstr "Ctrl+I" -#: objects/ui_MainWindow.h:862 +#: objects/ui_MainWindow.h:861 msgid "C&omment" msgstr "K&ommentieren" -#: objects/ui_MainWindow.h:863 +#: objects/ui_MainWindow.h:862 msgid "Ctrl+D" msgstr "Ctrl+D" -#: objects/ui_MainWindow.h:864 +#: objects/ui_MainWindow.h:863 msgid "Unco&mment" -msgstr "Kommentar entfernen" +msgstr "Kommentar ent&fernen" -#: objects/ui_MainWindow.h:865 +#: objects/ui_MainWindow.h:864 msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" -#: objects/ui_MainWindow.h:866 -msgid "Paste viewport translation" -msgstr "Aktuelle Verschiebung einfügen" +#: objects/ui_MainWindow.h:865 +msgid "P&aste viewport translation" +msgstr "Aktuelle Versch&iebung einfügen" -#: objects/ui_MainWindow.h:867 +#: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" +#: objects/ui_MainWindow.h:867 +msgid "Past&e viewport rotation" +msgstr "Aktuelle Ro&tation einfügen" + #: objects/ui_MainWindow.h:868 -msgid "Paste viewport rotation" -msgstr "Aktuelle Rotation einfügen" +msgid "Increase Font &Size" +msgstr "Font&größe erhöhen" #: objects/ui_MainWindow.h:869 -msgid "Increase Font Size" -msgstr "" - -#: objects/ui_MainWindow.h:870 msgid "Ctrl++" msgstr "Ctrl++" -#: objects/ui_MainWindow.h:871 -msgid "Decrease Font Size" -msgstr "" +#: objects/ui_MainWindow.h:870 +msgid "Decrease Font Si&ze" +msgstr "Fontgröße &verringern" -#: objects/ui_MainWindow.h:872 +#: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" -#: objects/ui_MainWindow.h:873 -msgid "Hide editor" +#: objects/ui_MainWindow.h:872 +msgid "H&ide editor" msgstr "Editor verstecken" -#: objects/ui_MainWindow.h:874 +#: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" -msgstr "Neu laden und Vorschau" +msgstr "Neu &laden und Vorschau" -#: objects/ui_MainWindow.h:875 +#: objects/ui_MainWindow.h:874 msgid "F4" msgstr "F4" -#: objects/ui_MainWindow.h:876 +#: objects/ui_MainWindow.h:875 msgid "&Preview" -msgstr "Vorschau" +msgstr "&Vorschau" -#: objects/ui_MainWindow.h:877 +#: objects/ui_MainWindow.h:876 msgid "F5" msgstr "F5" -#: objects/ui_MainWindow.h:878 -msgid "&Render" -msgstr "Rendern" +#: objects/ui_MainWindow.h:877 +msgid "R&ender" +msgstr "&Rendern" -#: objects/ui_MainWindow.h:879 +#: objects/ui_MainWindow.h:878 msgid "F6" msgstr "F6" +#: objects/ui_MainWindow.h:879 +msgid "&Check Validity" +msgstr "&Design überprüfen" + #: objects/ui_MainWindow.h:880 -msgid "Check Validity" -msgstr "Design überprüfen" +msgid "Display A&ST..." +msgstr "A&ST Baum anzeigen..." #: objects/ui_MainWindow.h:881 -msgid "Display &AST..." -msgstr "&AST Baum anzeigen..." +msgid "Display CSG &Tree..." +msgstr "CSG &Baum anzeigen..." #: objects/ui_MainWindow.h:882 -msgid "Display CSG &Tree..." -msgstr "CSG Baum anzeigen..." +msgid "Display CSG Pr&oducts..." +msgstr "CSG &Gleichungen anzeigen..." #: objects/ui_MainWindow.h:883 -msgid "Display CSG &Products..." -msgstr "CSG Gleichungen anzeigen..." - -#: objects/ui_MainWindow.h:884 msgid "Export as &STL..." msgstr "&STL exportieren..." -#: objects/ui_MainWindow.h:885 +#: objects/ui_MainWindow.h:884 msgid "Export as &OFF..." msgstr "&OFF exportieren..." -#: objects/ui_MainWindow.h:886 +#: objects/ui_MainWindow.h:885 msgid "Preview" -msgstr "Vorschau" +msgstr "&Vorschau" -#: objects/ui_MainWindow.h:887 +#: objects/ui_MainWindow.h:886 msgid "F9" msgstr "F9" -#: objects/ui_MainWindow.h:888 +#: objects/ui_MainWindow.h:887 msgid "Surfaces" -msgstr "Flächen anzeigen" +msgstr "&Flächen anzeigen" -#: objects/ui_MainWindow.h:889 +#: objects/ui_MainWindow.h:888 msgid "F10" msgstr "F10" -#: objects/ui_MainWindow.h:890 +#: objects/ui_MainWindow.h:889 msgid "Wireframe" -msgstr "Gittermodell" +msgstr "&Gittermodell" -#: objects/ui_MainWindow.h:891 +#: objects/ui_MainWindow.h:890 msgid "F11" msgstr "F11" -#: objects/ui_MainWindow.h:892 +#: objects/ui_MainWindow.h:891 msgid "Thrown Together" -msgstr "Kombinierte Anzeige" +msgstr "Kom&binierte Anzeige" -#: objects/ui_MainWindow.h:893 +#: objects/ui_MainWindow.h:892 msgid "F12" msgstr "F12" -#: objects/ui_MainWindow.h:894 +#: objects/ui_MainWindow.h:893 msgid "Show Edges" -msgstr "Kanten anzeigen" +msgstr "&Kanten anzeigen" -#: objects/ui_MainWindow.h:895 +#: objects/ui_MainWindow.h:894 msgid "Ctrl+1" msgstr "Ctrl+1" -#: objects/ui_MainWindow.h:896 +#: objects/ui_MainWindow.h:895 msgid "Show Axes" -msgstr "Koordinatenachsen anzeigen" +msgstr "Koordinaten&achsen anzeigen" -#: objects/ui_MainWindow.h:897 +#: objects/ui_MainWindow.h:896 msgid "Ctrl+2" msgstr "Ctrl+2" -#: objects/ui_MainWindow.h:898 +#: objects/ui_MainWindow.h:897 msgid "Show Crosshairs" -msgstr "Rotationsmittelpunkt anzeigen" +msgstr "Rotations&mittelpunkt anzeigen" -#: objects/ui_MainWindow.h:899 +#: objects/ui_MainWindow.h:898 msgid "Ctrl+3" msgstr "Ctrl+3" -#: objects/ui_MainWindow.h:900 +#: objects/ui_MainWindow.h:899 msgid "Show Scale Markers" -msgstr "" +msgstr "Axen&einteilung anzeigen" -#: objects/ui_MainWindow.h:901 +#: objects/ui_MainWindow.h:900 msgid "Animate" msgstr "Animation" -#: objects/ui_MainWindow.h:902 -msgid "Top" -msgstr "Oben" +#: objects/ui_MainWindow.h:901 +msgid "&Top" +msgstr "&Oben" -#: objects/ui_MainWindow.h:903 +#: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" -#: objects/ui_MainWindow.h:904 -msgid "Bottom" -msgstr "Unten" +#: objects/ui_MainWindow.h:903 +msgid "&Bottom" +msgstr "&Unten" -#: objects/ui_MainWindow.h:905 +#: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" -#: objects/ui_MainWindow.h:906 -msgid "Left" -msgstr "Links" +#: objects/ui_MainWindow.h:905 +msgid "&Left" +msgstr "&Links" -#: objects/ui_MainWindow.h:907 +#: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" -#: objects/ui_MainWindow.h:908 -msgid "Right" -msgstr "Rechts" +#: objects/ui_MainWindow.h:907 +msgid "&Right" +msgstr "&Rechts" -#: objects/ui_MainWindow.h:909 +#: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" -#: objects/ui_MainWindow.h:910 -msgid "Front" -msgstr "Vorn" +#: objects/ui_MainWindow.h:909 +msgid "&Front" +msgstr "Vor&n" -#: objects/ui_MainWindow.h:911 +#: objects/ui_MainWindow.h:910 msgid "Ctrl+8" msgstr "Ctrl+8" -#: objects/ui_MainWindow.h:912 -msgid "Back" -msgstr "Hinten" +#: objects/ui_MainWindow.h:911 +msgid "Bac&k" +msgstr "&Hinten" -#: objects/ui_MainWindow.h:913 +#: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" -#: objects/ui_MainWindow.h:914 -msgid "Diagonal" -msgstr "Diagonal" +#: objects/ui_MainWindow.h:913 +msgid "&Diagonal" +msgstr "&Diagonal" -#: objects/ui_MainWindow.h:915 +#: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" +#: objects/ui_MainWindow.h:915 +msgid "Ce&nter" +msgstr "&Zentriert" + #: objects/ui_MainWindow.h:916 -msgid "Center" -msgstr "Zentriert" +msgid "&Perspective" +msgstr "&Perspektivisch" #: objects/ui_MainWindow.h:917 -msgid "Perspective" -msgstr "Perspektivisch" +msgid "&Orthogonal" +msgstr "Or&thogonal" #: objects/ui_MainWindow.h:918 -msgid "Orthogonal" -msgstr "Orthogonal" - -#: objects/ui_MainWindow.h:919 -msgid "Hide console" +msgid "H&ide console" msgstr "Konsole verstecken" +#: objects/ui_MainWindow.h:919 +msgid "&About" +msgstr "Ãœber &OpenSCAD" + #: objects/ui_MainWindow.h:920 -msgid "About" -msgstr "Ãœber OpenSCAD" +msgid "&Documentation" +msgstr "&Dokumentation" #: objects/ui_MainWindow.h:921 -msgid "Documentation" -msgstr "Dokumentation" - -#: objects/ui_MainWindow.h:922 msgid "Clear Recent" msgstr "Zuletzt benutze Dateien löschen" -#: objects/ui_MainWindow.h:923 -msgid "Export as DXF..." +#: objects/ui_MainWindow.h:922 +msgid "Export as &DXF..." msgstr "DXF exportieren..." -#: objects/ui_MainWindow.h:924 objects/ui_OpenCSGWarningDialog.h:94 -msgid "Close" +#: objects/ui_MainWindow.h:923 +msgid "&Close" msgstr "Schließen" -#: objects/ui_MainWindow.h:925 +#: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" -#: objects/ui_MainWindow.h:926 objects/ui_Preferences.h:1061 -msgid "Preferences" -msgstr "Einstellungen" +#: objects/ui_MainWindow.h:925 +msgid "&Preferences" +msgstr "Ei&nstellungen" + +#: objects/ui_MainWindow.h:926 +msgid "&Find..." +msgstr "&Suchen..." #: objects/ui_MainWindow.h:927 -msgid "Find..." -msgstr "Suchen..." - -#: objects/ui_MainWindow.h:928 msgid "Ctrl+F" msgstr "Ctrl+F" -#: objects/ui_MainWindow.h:929 -msgid "Find and Replace..." -msgstr "Suchen und Ersetzen..." +#: objects/ui_MainWindow.h:928 +msgid "Fin&d and Replace..." +msgstr "Suchen und &Ersetzen..." -#: objects/ui_MainWindow.h:930 +#: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" -#: objects/ui_MainWindow.h:931 -msgid "Find Next" -msgstr "Weiter suchen" +#: objects/ui_MainWindow.h:930 +msgid "Find Ne&xt" +msgstr "&Weiter suchen" -#: objects/ui_MainWindow.h:932 +#: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" -#: objects/ui_MainWindow.h:933 -msgid "Find Previous" -msgstr "Rückwärts suchen" +#: objects/ui_MainWindow.h:932 +msgid "Find Pre&vious" +msgstr "Rüc&kwärts suchen" -#: objects/ui_MainWindow.h:934 +#: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" -#: objects/ui_MainWindow.h:935 -msgid "Use Selection for Find" -msgstr "Auswahl suchen" +#: objects/ui_MainWindow.h:934 +msgid "Use Se&lection for Find" +msgstr "&Auswahl suchen" -#: objects/ui_MainWindow.h:936 +#: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" +#: objects/ui_MainWindow.h:936 +msgid "&Flush Caches" +msgstr "&Cache leeren" + #: objects/ui_MainWindow.h:937 -msgid "Flush Caches" -msgstr "Cache leeren" +msgid "&OpenSCAD Homepage" +msgstr "OpenSCAD &Homepage" #: objects/ui_MainWindow.h:938 -msgid "OpenSCAD Homepage" -msgstr "OpenSCAD Homepage" +msgid "&Automatic Reload and Preview" +msgstr "&Automatisch neu Laden und Vorschau" #: objects/ui_MainWindow.h:939 -msgid "Automatic Reload and Preview" -msgstr "Automatisch neu Laden und Vorschau" - -#: objects/ui_MainWindow.h:940 -msgid "Export as Image..." +msgid "Export as &Image..." msgstr "Image exportieren..." -#: objects/ui_MainWindow.h:941 -msgid "Export as CSG..." +#: objects/ui_MainWindow.h:940 +msgid "Export as &CSG..." msgstr "CSG exportieren..." +#: objects/ui_MainWindow.h:941 +msgid "&Library info" +msgstr "&Versionsinformationen" + #: objects/ui_MainWindow.h:942 -msgid "Library info" -msgstr "Versionsinformationen" +msgid "Show &Library Folder..." +msgstr "Bibli&otheken anzeigen..." #: objects/ui_MainWindow.h:943 -msgid "Show Library Folder..." -msgstr "Bibliotheken anzeigen..." +msgid "Reset View" +msgstr "Ans&icht zurücksetzen" #: objects/ui_MainWindow.h:944 -msgid "Reset View" -msgstr "Ansicht zurücksetzen" +msgid "&Font List" +msgstr "&Fontliste" #: objects/ui_MainWindow.h:945 -msgid "Font List" -msgstr "Fontliste" - -#: objects/ui_MainWindow.h:946 -msgid "Export as SVG..." +msgid "Export as S&VG..." msgstr "SVG exportieren..." -#: objects/ui_MainWindow.h:947 -msgid "Export as AMF..." +#: objects/ui_MainWindow.h:946 +msgid "Export as &AMF..." msgstr "AMF exportieren..." -#: objects/ui_MainWindow.h:948 +#: objects/ui_MainWindow.h:947 msgid "Zoom In" msgstr "Vergrößern" -#: objects/ui_MainWindow.h:949 +#: objects/ui_MainWindow.h:948 msgid "Ctrl+]" msgstr "Ctrl+]" -#: objects/ui_MainWindow.h:950 +#: objects/ui_MainWindow.h:949 msgid "Zoom Out" msgstr "Verkleinern" -#: objects/ui_MainWindow.h:951 +#: objects/ui_MainWindow.h:950 msgid "Ctrl+[" msgstr "Ctrl+[" -#: objects/ui_MainWindow.h:952 +#: objects/ui_MainWindow.h:951 msgid "View All" -msgstr "Alles anzeigen" +msgstr "Alle&s anzeigen" + +#: objects/ui_MainWindow.h:952 +msgid "Conv&ert Tabs to Spaces" +msgstr "Tabs in Leerzeichen &umwandeln" #: objects/ui_MainWindow.h:953 -msgid "Convert Tabs to Spaces" -msgstr "Tabs in Leerzeichen umwandeln" - -#: objects/ui_MainWindow.h:954 msgid "Hide toolbars" msgstr "Symbolleisten verstecken" -#: objects/ui_MainWindow.h:955 +#: objects/ui_MainWindow.h:954 msgid "U&nindent" -msgstr "Einzug vermindern" +msgstr "Einzug ver&mindern" -#: objects/ui_MainWindow.h:956 +#: objects/ui_MainWindow.h:955 msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" +#: objects/ui_MainWindow.h:956 +msgid "&Cheat Sheet" +msgstr "&Befehlsübersicht" + #: objects/ui_MainWindow.h:957 -msgid "Cheat Sheet" -msgstr "" - -#: objects/ui_MainWindow.h:958 -#, fuzzy msgid "Message" -msgstr "help message" +msgstr "Message" -#: objects/ui_MainWindow.h:961 +#: objects/ui_MainWindow.h:960 msgid "Time:" msgstr "Zeit:" -#: objects/ui_MainWindow.h:962 +#: objects/ui_MainWindow.h:961 msgid "FPS:" msgstr "FPS:" -#: objects/ui_MainWindow.h:963 +#: objects/ui_MainWindow.h:962 msgid "Steps:" msgstr "Schritte:" -#: objects/ui_MainWindow.h:964 +#: objects/ui_MainWindow.h:963 msgid "Dump Pictures" msgstr "Bilder ausgeben" -#: objects/ui_MainWindow.h:965 +#: objects/ui_MainWindow.h:964 msgid "&File" msgstr "&Datei" +#: objects/ui_MainWindow.h:965 +msgid "Recen&t Files" +msgstr "Zuletzt benutze &Dateien" + #: objects/ui_MainWindow.h:966 -msgid "Recent Files" -msgstr "Zuletzt benutze Dateien" +msgid "&Examples" +msgstr "&Beispiele" + +#: objects/ui_MainWindow.h:967 +msgid "E&xport" +msgstr "&Exportieren" #: objects/ui_MainWindow.h:968 -msgid "Export" -msgstr "Exportieren" - -#: objects/ui_MainWindow.h:969 msgid "&Edit" msgstr "&Bearbeiten" -#: objects/ui_MainWindow.h:970 +#: objects/ui_MainWindow.h:969 msgid "&Design" msgstr "D&esign" -#: objects/ui_MainWindow.h:971 +#: objects/ui_MainWindow.h:970 msgid "&View" msgstr "&Ansicht" -#: objects/ui_MainWindow.h:972 +#: objects/ui_MainWindow.h:971 msgid "&Help" msgstr "&Hilfe" -#: objects/ui_MainWindow.h:975 +#: objects/ui_MainWindow.h:974 msgid "Find" msgstr "Suchen" -#: objects/ui_MainWindow.h:976 objects/ui_MainWindow.h:983 +#: objects/ui_MainWindow.h:975 objects/ui_MainWindow.h:982 msgid "Replace" msgstr "Ersetzen" -#: objects/ui_MainWindow.h:978 +#: objects/ui_MainWindow.h:977 msgid "Search string" msgstr "Suchtext" -#: objects/ui_MainWindow.h:979 +#: objects/ui_MainWindow.h:978 msgid "<" msgstr "<" -#: objects/ui_MainWindow.h:980 +#: objects/ui_MainWindow.h:979 msgid ">" msgstr ">" -#: objects/ui_MainWindow.h:981 +#: objects/ui_MainWindow.h:980 msgid "Done" msgstr "Fertig" -#: objects/ui_MainWindow.h:982 +#: objects/ui_MainWindow.h:981 msgid "Replacement string" msgstr "Ersetzen mit" -#: objects/ui_MainWindow.h:984 +#: objects/ui_MainWindow.h:983 msgid "All" msgstr "Alles" @@ -736,6 +737,14 @@ msgstr "OpenCSG benutzen" msgid "Show this message again" msgstr "Diesen Dialog wieder anzeigen" +#: objects/ui_OpenCSGWarningDialog.h:94 +msgid "Close" +msgstr "Schließen" + +#: objects/ui_Preferences.h:1061 +msgid "Preferences" +msgstr "Einstellungen" + #: objects/ui_Preferences.h:1062 msgid "3D View" msgstr "3D Ansicht" @@ -766,7 +775,7 @@ msgstr "Farbschema:" #: objects/ui_Preferences.h:1071 msgid "Show Warnings and Errors in 3D View" -msgstr "" +msgstr "Fehler und Warnungen in der 3D Ansicht anzeigen" #: objects/ui_Preferences.h:1072 msgid "Editor Type" @@ -793,155 +802,146 @@ msgid "Color syntax highlighting" msgstr "Syntaxhervorhebung" #: objects/ui_Preferences.h:1081 -#, fuzzy msgid "Ctrl/Cmd-Mouse-wheel zooms text" msgstr "Ctrl/Cmd+Mausrad zum Vergrößern des Textes benutzen" #: objects/ui_Preferences.h:1082 -#, fuzzy msgid "Indentation" -msgstr "Dokumentation" +msgstr "Einrückung" #: objects/ui_Preferences.h:1083 -#, fuzzy msgid "Auto Indent" -msgstr "Einzug erhöhen" +msgstr "Automatisch einrücken" #: objects/ui_Preferences.h:1084 -#, fuzzy msgid "Indent using" -msgstr "Einzug erhöhen" +msgstr "Einrücken mit" #: objects/ui_Preferences.h:1087 src/settings.cc:135 -#, fuzzy msgid "Spaces" -msgstr "Flächen anzeigen" +msgstr "Leerzeichen" #: objects/ui_Preferences.h:1088 src/settings.cc:135 msgid "Tabs" -msgstr "" +msgstr "Tabs" #: objects/ui_Preferences.h:1090 msgid "Indentation width" -msgstr "" +msgstr "Einrückungstiefe" #: objects/ui_Preferences.h:1091 msgid "Tab width" -msgstr "" +msgstr "Tabulatorschrittweite" #: objects/ui_Preferences.h:1092 msgid "Tab key function" -msgstr "" +msgstr "Funktion der Tab-Taste" #: objects/ui_Preferences.h:1095 objects/ui_Preferences.h:1125 #: src/settings.cc:136 -#, fuzzy msgid "Indent" -msgstr "Einzug erhöhen" +msgstr "Einrücken" #: objects/ui_Preferences.h:1096 src/settings.cc:136 msgid "Insert Tab" -msgstr "" +msgstr "Tab einfügen" #: objects/ui_Preferences.h:1098 msgid "Show whitespace" -msgstr "" +msgstr "Formatierungsymbole anzeigen" #: objects/ui_Preferences.h:1101 src/settings.cc:132 msgid "Never" -msgstr "" +msgstr "nie" #: objects/ui_Preferences.h:1102 src/settings.cc:132 msgid "Always" -msgstr "" +msgstr "immer" #: objects/ui_Preferences.h:1103 msgid "Only after indentation" -msgstr "" +msgstr "nur nach Einrückung" #: objects/ui_Preferences.h:1105 msgid "Size" -msgstr "" +msgstr "Größe" #: objects/ui_Preferences.h:1106 -#, fuzzy msgid "Display" -msgstr "&AST Baum anzeigen..." +msgstr "Anzeige" #: objects/ui_Preferences.h:1107 msgid "Enable brace matching" -msgstr "" +msgstr "zusammengehörige Klammern hervorheben" #: objects/ui_Preferences.h:1108 msgid "Highlight current line" -msgstr "" +msgstr "Aktuelle Zeile hervorheben" #: objects/ui_Preferences.h:1109 objects/ui_Preferences.h:1142 msgid "Line wrap" -msgstr "" +msgstr "Zeilenumbruch" #: objects/ui_Preferences.h:1112 objects/ui_Preferences.h:1129 #: objects/ui_Preferences.h:1137 src/settings.cc:127 src/settings.cc:130 #: src/settings.cc:131 msgid "None" -msgstr "" +msgstr "nie" #: objects/ui_Preferences.h:1113 src/settings.cc:127 msgid "Wrap at character boundaries" -msgstr "" +msgstr "an jedem Zeichen" #: objects/ui_Preferences.h:1114 src/settings.cc:127 msgid "Wrap at word boundaries" -msgstr "" +msgstr "an Wörtern" #: objects/ui_Preferences.h:1116 msgid "Line wrap indentation" -msgstr "" +msgstr "Einrückung nach Zeilenumbruch" #: objects/ui_Preferences.h:1117 msgid "Line wrap visualization" -msgstr "" +msgstr "Zeilenumbruch anzeigen" #: objects/ui_Preferences.h:1118 msgid "Style" -msgstr "" +msgstr "Stil" #: objects/ui_Preferences.h:1121 src/settings.cc:128 msgid "Fixed" -msgstr "" +msgstr "Fest" #: objects/ui_Preferences.h:1122 src/settings.cc:128 msgid "Same" -msgstr "" +msgstr "Wie vorherige Zeile" #: objects/ui_Preferences.h:1123 src/settings.cc:128 -#, fuzzy msgid "Indented" -msgstr "Einzug erhöhen" +msgstr "Eingerückt" #: objects/ui_Preferences.h:1126 -#, fuzzy msgid "Start" -msgstr "Starnight" +msgstr "Anfang" #: objects/ui_Preferences.h:1130 objects/ui_Preferences.h:1138 #: src/settings.cc:130 src/settings.cc:131 msgid "Text" -msgstr "" +msgstr "Text" #: objects/ui_Preferences.h:1131 objects/ui_Preferences.h:1139 #: src/settings.cc:130 src/settings.cc:131 msgid "Border" -msgstr "" +msgstr "Rand" #: objects/ui_Preferences.h:1132 objects/ui_Preferences.h:1140 #: src/settings.cc:130 src/settings.cc:131 msgid "Margin" -msgstr "" +msgstr "Seitenrand" #: objects/ui_Preferences.h:1134 msgid "End" -msgstr "" +msgstr "Ende" #: objects/ui_Preferences.h:1143 msgid "Automatically check for updates" @@ -1015,16 +1015,7 @@ msgstr "Startbildschirm anzeigen" msgid "Enable user interface localization (requires restart of OpenSCAD)" msgstr "Lokalisierung der GUI einschalten (benötigt Neustart von OpenSCAD)" -# This should not be visible (window title of the ToolBar). -#: objects/ui_Preferences.h:1163 -msgid "toolBar" -msgstr "toolBar" - #: objects/ui_ProgressWidget.h:72 -msgid "Form" -msgstr "Form" - -#: objects/ui_ProgressWidget.h:73 msgid "%v / %m" msgstr "%v / %m" @@ -1042,23 +1033,22 @@ msgid "Untitled.scad" msgstr "Unbenannt.scad" #: src/mainwin.cc:971 -#, fuzzy msgid "Compile error." -msgstr "Ãœbersetzen" +msgstr "Fehler" #: src/mainwin.cc:974 msgid "Error while compiling '%1'." -msgstr "" +msgstr "Fehler beim Kompilieren von '%1'." #: src/mainwin.cc:978 msgid "Compilation generated %1 warning." msgid_plural "Compilation generated %1 warnings." -msgstr[0] "" -msgstr[1] "" +msgstr[0] "%1 Warnung beim kompilieren." +msgstr[1] "%1 Warnungen beim kompilieren." #: src/mainwin.cc:988 msgid " For details see console window." -msgstr "" +msgstr " Für Details das Konsole Fenster öffnen." #: src/mainwin.cc:1353 msgid "Save File" @@ -1141,18 +1131,10 @@ msgid "" "Fontconfig needs to update its font cache.\n" "This can take up to a couple of minutes." msgstr "" +"Fontconfig muss den Font-Cache aktualisieren.\n" +"Dies kann einige Minuten dauern." -#: src/QGLView.cc:111 -msgid "" -"\n" -"Using QGLWidget\n" -"\n" -msgstr "" -"\n" -"Benutze QGLWidget\n" -"\n" - -#: src/QGLView.cc:128 +#: src/QGLView.cc:129 msgid "" "Warning: You may experience OpenCSG rendering errors.\n" "\n" @@ -1160,7 +1142,7 @@ msgstr "" "Achtung: Es können Darstellungsfehler beim Anzeigen der Vorschau auftreten.\n" "\n" -#: src/QGLView.cc:131 +#: src/QGLView.cc:132 msgid "" "Warning: Missing OpenGL capabilities for OpenCSG - OpenCSG has been " "disabled.\n" @@ -1170,7 +1152,7 @@ msgstr "" "nicht aus - OpenCSG wurde deaktiviert.\n" "\n" -#: src/QGLView.cc:134 +#: src/QGLView.cc:135 msgid "" "It is highly recommended to use OpenSCAD on a system with OpenGL 2.0 or " "later.\n" @@ -1180,7 +1162,7 @@ msgstr "" "2.0.\n" "Informationen zum OpenGL Treiber:\n" -#: src/QGLView.cc:138 +#: src/QGLView.cc:139 #, c-format msgid "" "GLEW version %s\n" @@ -1193,7 +1175,7 @@ msgstr "" #: src/settings.cc:132 msgid "After indentation" -msgstr "" +msgstr "nach Einrückung" #: src/UIUtils.cc:86 msgid "Basics" @@ -1207,6 +1189,28 @@ msgstr "Formen" msgid "Extrusion" msgstr "Extrusion" +#~ msgid "Top" +#~ msgstr "Oben" + +#~ msgid "Back" +#~ msgstr "Hinten" + +# This should not be visible (window title of the ToolBar). +#~ msgid "toolBar" +#~ msgstr "toolBar" + +#~ msgid "Form" +#~ msgstr "Form" + +#~ msgid "" +#~ "\n" +#~ "Using QGLWidget\n" +#~ "\n" +#~ msgstr "" +#~ "\n" +#~ "Benutze QGLWidget\n" +#~ "\n" + #~ msgid "Paste font selector to Editor Window" #~ msgstr "Font Selektor in Editor kopieren" From c5ec54362e03546a88f0c452b2226936b2879ea5 Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Sun, 1 Feb 2015 20:11:29 +0100 Subject: [PATCH 151/174] Run translation-make.sh from test suite to validate *.po file syntax (fixes #1180). --- tests/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3eefcf0..9ab9c56d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -783,6 +783,9 @@ add_executable(openscad_nogui ../src/openscad.cc) set_target_properties(openscad_nogui PROPERTIES COMPILE_FLAGS "-fno-strict-aliasing -DEIGEN_DONT_ALIGN ${ENABLE_OPENCSG_FLAG} -DENABLE_CGAL ${CGAL_CXX_FLAGS_INIT}") target_link_libraries(openscad_nogui tests-offscreen tests-cgal ${GLEW_LIBRARY} ${OPENCSG_LIBRARY} ${APP_SERVICES_LIBRARY}) +# also run translation compilation to verify the files are without syntax errors +add_custom_target(locale_files ALL COMMAND ${CMAKE_SOURCE_DIR}/../scripts/translation-make.sh) + # # GUI binary tests # From c5f7f66809c39fe1eada0a67453b9140345572c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Sun, 1 Feb 2015 20:55:47 +0100 Subject: [PATCH 152/174] Updated the Czech translation after #1200 changes --- locale/cs.po | 143 ++++++++++++++++++--------------------------------- 1 file changed, 50 insertions(+), 93 deletions(-) diff --git a/locale/cs.po b/locale/cs.po index d4ed3268..f7fc056c 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: OpenSCAD 2013.02.24\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-02-01 18:03+0100\n" -"PO-Revision-Date: 2015-01-28 10:50+0100\n" +"PO-Revision-Date: 2015-02-01 20:54+0100\n" "Last-Translator: Miro HronÄok \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 1.5.4\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n>=2 && n<=4 ? 1 : 2;\n" +"X-Generator: Poedit 1.7.3\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Poedit-SourceCharset: UTF-8\n" #: objects/ui_AboutDialog.h:103 src/AboutDialog.h:13 @@ -161,7 +161,7 @@ msgstr "Ctrl+Shift+S" #: objects/ui_MainWindow.h:845 msgid "&Reload" -msgstr "&Znovu naÄíst" +msgstr "Zno&vu naÄíst" #: objects/ui_MainWindow.h:846 msgid "Ctrl+R" @@ -185,7 +185,7 @@ msgstr "Ctrl+Z" #: objects/ui_MainWindow.h:851 msgid "&Redo" -msgstr "Zn&ovu" +msgstr "Znov&u" #: objects/ui_MainWindow.h:852 msgid "Ctrl+Shift+Z" @@ -193,7 +193,7 @@ msgstr "Ctrl+Shift+Z" #: objects/ui_MainWindow.h:853 msgid "Cu&t" -msgstr "&Vyjmout" +msgstr "Vy&jmout" #: objects/ui_MainWindow.h:854 msgid "Ctrl+X" @@ -225,7 +225,7 @@ msgstr "Ctrl+I" #: objects/ui_MainWindow.h:861 msgid "C&omment" -msgstr "&Zakomentovat" +msgstr "Zakomen&tovat" #: objects/ui_MainWindow.h:862 msgid "Ctrl+D" @@ -240,41 +240,36 @@ msgid "Ctrl+Shift+D" msgstr "Ctrl+Shift+D" #: objects/ui_MainWindow.h:865 -#, fuzzy msgid "P&aste viewport translation" -msgstr "Vložit posun pohledu" +msgstr "Vložit posun pohl&edu" #: objects/ui_MainWindow.h:866 msgid "Ctrl+T" msgstr "Ctrl+T" #: objects/ui_MainWindow.h:867 -#, fuzzy msgid "Past&e viewport rotation" -msgstr "Vložit rotaci pohledu" +msgstr "Vlo&žit rotaci pohledu" #: objects/ui_MainWindow.h:868 -#, fuzzy msgid "Increase Font &Size" -msgstr "ZvÄ›tÅ¡it písmo" +msgstr "Zv&Ä›tÅ¡it písmo" #: objects/ui_MainWindow.h:869 msgid "Ctrl++" msgstr "Ctrl++" #: objects/ui_MainWindow.h:870 -#, fuzzy msgid "Decrease Font Si&ze" -msgstr "ZmenÅ¡it písmo" +msgstr "Z&menÅ¡it písmo" #: objects/ui_MainWindow.h:871 msgid "Ctrl+-" msgstr "Ctrl+-" #: objects/ui_MainWindow.h:872 -#, fuzzy msgid "H&ide editor" -msgstr "Skrýt editor" +msgstr "Skrýt &editor" #: objects/ui_MainWindow.h:873 msgid "&Reload and Preview" @@ -293,7 +288,6 @@ msgid "F5" msgstr "F5" #: objects/ui_MainWindow.h:877 -#, fuzzy msgid "R&ender" msgstr "Vy&renderovat" @@ -302,21 +296,18 @@ msgid "F6" msgstr "F6" #: objects/ui_MainWindow.h:879 -#, fuzzy msgid "&Check Validity" -msgstr "Zkontrolovat správnost" +msgstr "Zkontrolovat &správnost" #: objects/ui_MainWindow.h:880 -#, fuzzy msgid "Display A&ST..." -msgstr "Ukázat &ATS..." +msgstr "&Ukázat ATS..." #: objects/ui_MainWindow.h:881 msgid "Display CSG &Tree..." msgstr "Ukázat CSG s&trom..." #: objects/ui_MainWindow.h:882 -#, fuzzy msgid "Display CSG Pr&oducts..." msgstr "Ukázat CSG &produkty..." @@ -394,43 +385,39 @@ msgstr "Animovat" #: objects/ui_MainWindow.h:901 msgid "&Top" -msgstr "" +msgstr "Ses&hora" #: objects/ui_MainWindow.h:902 msgid "Ctrl+4" msgstr "Ctrl+4" #: objects/ui_MainWindow.h:903 -#, fuzzy msgid "&Bottom" -msgstr "Zespoda" +msgstr "Ze&spoda" #: objects/ui_MainWindow.h:904 msgid "Ctrl+5" msgstr "Ctrl+5" #: objects/ui_MainWindow.h:905 -#, fuzzy msgid "&Left" -msgstr "Zleva" +msgstr "Z&leva" #: objects/ui_MainWindow.h:906 msgid "Ctrl+6" msgstr "Ctrl+6" #: objects/ui_MainWindow.h:907 -#, fuzzy msgid "&Right" -msgstr "Zprava" +msgstr "Z&prava" #: objects/ui_MainWindow.h:908 msgid "Ctrl+7" msgstr "Ctrl+7" #: objects/ui_MainWindow.h:909 -#, fuzzy msgid "&Front" -msgstr "ZepÅ™edu" +msgstr "ZepÅ™e&du" #: objects/ui_MainWindow.h:910 msgid "Ctrl+8" @@ -438,172 +425,147 @@ msgstr "Ctrl+8" #: objects/ui_MainWindow.h:911 msgid "Bac&k" -msgstr "" +msgstr "Ze&zadu" #: objects/ui_MainWindow.h:912 msgid "Ctrl+9" msgstr "Ctrl+9" #: objects/ui_MainWindow.h:913 -#, fuzzy msgid "&Diagonal" -msgstr "DiagonálnÄ›" +msgstr "Dia&gonálnÄ›" #: objects/ui_MainWindow.h:914 msgid "Ctrl+0" msgstr "Ctrl+0" #: objects/ui_MainWindow.h:915 -#, fuzzy msgid "Ce&nter" -msgstr "Vycentrovat" +msgstr "Vy¢rovat" #: objects/ui_MainWindow.h:916 -#, fuzzy msgid "&Perspective" -msgstr "PerspektivnÄ›" +msgstr "Pe&rspektivnÄ›" #: objects/ui_MainWindow.h:917 -#, fuzzy msgid "&Orthogonal" -msgstr "OrtogonálnÄ›" +msgstr "&OrtogonálnÄ›" #: objects/ui_MainWindow.h:918 -#, fuzzy msgid "H&ide console" -msgstr "Skrýt terminál" +msgstr "Skrýt &terminál" #: objects/ui_MainWindow.h:919 -#, fuzzy msgid "&About" -msgstr "O aplikaci" +msgstr "&O aplikaci" #: objects/ui_MainWindow.h:920 -#, fuzzy msgid "&Documentation" -msgstr "Dokumentace" +msgstr "&Dokumentace" #: objects/ui_MainWindow.h:921 msgid "Clear Recent" msgstr "Zapomenout nedávné" #: objects/ui_MainWindow.h:922 -#, fuzzy msgid "Export as &DXF..." -msgstr "Exportovat jako &DXF" +msgstr "Exportovat jako &DXF..." #: objects/ui_MainWindow.h:923 -#, fuzzy msgid "&Close" -msgstr "Zavřít" +msgstr "&Zavřít" #: objects/ui_MainWindow.h:924 msgid "Ctrl+W" msgstr "Ctrl+W" #: objects/ui_MainWindow.h:925 -#, fuzzy msgid "&Preferences" -msgstr "PÅ™edvolby" +msgstr "PÅ™edvolb&y" #: objects/ui_MainWindow.h:926 -#, fuzzy msgid "&Find..." -msgstr "Najít..." +msgstr "&Najít..." #: objects/ui_MainWindow.h:927 msgid "Ctrl+F" msgstr "Ctrl+F" #: objects/ui_MainWindow.h:928 -#, fuzzy msgid "Fin&d and Replace..." -msgstr "Najít a nahradit..." +msgstr "Najít a na&hradit..." #: objects/ui_MainWindow.h:929 msgid "Ctrl+Alt+F" msgstr "Ctrl+Alt+F" #: objects/ui_MainWindow.h:930 -#, fuzzy msgid "Find Ne&xt" -msgstr "Najít další" +msgstr "Najít &další" #: objects/ui_MainWindow.h:931 msgid "Ctrl+G" msgstr "Ctrl+G" #: objects/ui_MainWindow.h:932 -#, fuzzy msgid "Find Pre&vious" -msgstr "Najít pÅ™edchozí" +msgstr "Najít &pÅ™edchozí" #: objects/ui_MainWindow.h:933 msgid "Ctrl+Shift+G" msgstr "Ctrl+Shift+G" #: objects/ui_MainWindow.h:934 -#, fuzzy msgid "Use Se&lection for Find" -msgstr "Hledat vybraný Å™etÄ›zec" +msgstr "Hledat vybraný Å™etÄ›ze&c" #: objects/ui_MainWindow.h:935 msgid "Ctrl+E" msgstr "Ctrl+E" #: objects/ui_MainWindow.h:936 -#, fuzzy msgid "&Flush Caches" -msgstr "Vyprázdnit mezipaměť" +msgstr "&Vyprázdnit mezipaměť" #: objects/ui_MainWindow.h:937 -#, fuzzy msgid "&OpenSCAD Homepage" -msgstr "Domovská stránka OpenSCADu" +msgstr "Domovská &stránka OpenSCADu" #: objects/ui_MainWindow.h:938 -#, fuzzy msgid "&Automatic Reload and Preview" -msgstr "Automaticky naÄítat a zobrazovat" +msgstr "&Automaticky naÄítat a zobrazovat" #: objects/ui_MainWindow.h:939 -#, fuzzy msgid "Export as &Image..." -msgstr "Exportovat jako obrázek..." +msgstr "Exportovat jako &obrázek..." #: objects/ui_MainWindow.h:940 -#, fuzzy msgid "Export as &CSG..." -msgstr "Exportovat jako CSG..." +msgstr "Exportovat jako &CSG..." #: objects/ui_MainWindow.h:941 -#, fuzzy msgid "&Library info" -msgstr "Informace o knihovnách" +msgstr "&Informace o knihovnách" #: objects/ui_MainWindow.h:942 -#, fuzzy msgid "Show &Library Folder..." -msgstr "Adresář s knihovnami..." +msgstr "&Adresář s knihovnami..." #: objects/ui_MainWindow.h:943 msgid "Reset View" msgstr "Výchozí pohled" #: objects/ui_MainWindow.h:944 -#, fuzzy msgid "&Font List" -msgstr "Seznam písem" +msgstr "Seznam &písem" #: objects/ui_MainWindow.h:945 -#, fuzzy msgid "Export as S&VG..." -msgstr "Exportovat jako SVG..." +msgstr "Exportovat jako S&VG..." #: objects/ui_MainWindow.h:946 -#, fuzzy msgid "Export as &AMF..." -msgstr "Exportovat jako AMF..." +msgstr "Exportovat jako &AMF..." #: objects/ui_MainWindow.h:947 msgid "Zoom In" @@ -626,9 +588,8 @@ msgid "View All" msgstr "Zobrazit vÅ¡e" #: objects/ui_MainWindow.h:952 -#, fuzzy msgid "Conv&ert Tabs to Spaces" -msgstr "PÅ™evést tabulátory na mezery" +msgstr "PÅ™e&vést tabulátory na mezery" #: objects/ui_MainWindow.h:953 msgid "Hide toolbars" @@ -643,9 +604,8 @@ msgid "Ctrl+Shift+I" msgstr "Ctrl+Shift+I" #: objects/ui_MainWindow.h:956 -#, fuzzy msgid "&Cheat Sheet" -msgstr "Tahák" +msgstr "&Tahák" #: objects/ui_MainWindow.h:957 msgid "Message" @@ -672,19 +632,16 @@ msgid "&File" msgstr "&Soubor" #: objects/ui_MainWindow.h:965 -#, fuzzy msgid "Recen&t Files" -msgstr "Nedávné soubory" +msgstr "Nedávné &soubory" #: objects/ui_MainWindow.h:966 -#, fuzzy msgid "&Examples" -msgstr "Příklady" +msgstr "&Příklady" #: objects/ui_MainWindow.h:967 -#, fuzzy msgid "E&xport" -msgstr "Exportovat" +msgstr "&Exportovat" #: objects/ui_MainWindow.h:968 msgid "&Edit" From 111197f694f7be0b663b94a6f55ea53ca6f2d519 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 1 Feb 2015 18:43:18 -0500 Subject: [PATCH 153/174] #793 Added testcase --- .../3D/features/polyhedron-concave-test.scad | 2 ++ .../scad/3D/features/polyhedron-tests.scad | 24 ------------------ .../polyhedron-concave-test-expected.png | Bin 0 -> 7271 bytes .../cgalpngtest/polyhedron-tests-expected.png | Bin 9882 -> 9700 bytes .../polyhedron-concave-test-expected.csg | 3 +++ .../dumptest/polyhedron-tests-expected.csg | 6 ----- .../polyhedron-tests-expected.png | Bin 9835 -> 9699 bytes .../polyhedron-concave-test-expected.png | Bin 0 -> 7271 bytes .../opencsgtest/polyhedron-tests-expected.png | Bin 6380 -> 9634 bytes .../polyhedron-concave-test-expected.png | Bin 0 -> 7271 bytes .../polyhedron-tests-expected.png | Bin 7061 -> 10481 bytes 11 files changed, 5 insertions(+), 30 deletions(-) create mode 100644 testdata/scad/3D/features/polyhedron-concave-test.scad create mode 100644 tests/regression/cgalpngtest/polyhedron-concave-test-expected.png create mode 100644 tests/regression/dumptest/polyhedron-concave-test-expected.csg create mode 100644 tests/regression/opencsgtest/polyhedron-concave-test-expected.png create mode 100644 tests/regression/throwntogethertest/polyhedron-concave-test-expected.png diff --git a/testdata/scad/3D/features/polyhedron-concave-test.scad b/testdata/scad/3D/features/polyhedron-concave-test.scad new file mode 100644 index 00000000..11943f79 --- /dev/null +++ b/testdata/scad/3D/features/polyhedron-concave-test.scad @@ -0,0 +1,2 @@ +polyhedron(points = [[0, 0, 0], [2, 4, 0], [8, 4, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 5], [2, 4, 5], [8, 4, 5], [10, 0, 5], [10, 10, 5], [0, 10, 5]], faces = [[0, 1, 2, 3, 4, 5], [0, 6, 7], [0, 7, 1], [1, 7, 8], [1, 8, 2], [2, 8, 9], [2, 9, 3], [3, 9, 10], [3, 10, 4], [4, 10, 11], [4, 11, 5], [5, 11, 6], [5, 6, 0], [11, 10, 9, 8, 7, 6]], convexity = 2); + \ No newline at end of file diff --git a/testdata/scad/3D/features/polyhedron-tests.scad b/testdata/scad/3D/features/polyhedron-tests.scad index 443619d0..d519c7d8 100644 --- a/testdata/scad/3D/features/polyhedron-tests.scad +++ b/testdata/scad/3D/features/polyhedron-tests.scad @@ -11,30 +11,6 @@ module polyhedrons() { translate([4,0,0]) polyhedron(points = [[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]], triangles = [[0,2,4],[0,5,2],[0,4,3],[0,3,5],[1,4,2],[1,2,5],[1,3,4], [1,5,3]]); - -// Containing concave polygons -translate([6,0,0]) -polyhedron(points=[ - [-0.8,-0.8,-0.8], - [0,0,-0.8], - [0.8,-0.8,-0.8], - [0.8,0.8,-0.8], - [-0.8,0.8,-0.8], - [-0.8,-0.8,0.8], - [0,0,0.8], - [0.8,-0.8,0.8], - [0.8,0.8,0.8], - [-0.8,0.8,0.8], - ], - triangles=[ - [0,1,2,3,4], - [5,6,1,0], - [6,7,2,1], - [7,8,3,2], - [8,9,4,3], - [9,5,0,4], - [9,8,7,6,5], - ], convexity=2); } polyhedrons(); diff --git a/tests/regression/cgalpngtest/polyhedron-concave-test-expected.png b/tests/regression/cgalpngtest/polyhedron-concave-test-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c45cc11cb7c72da78addcc2558521b66cb42f99a GIT binary patch literal 7271 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 LK3jI${lWhL-piZP literal 9882 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 diff --git a/tests/regression/dumptest/polyhedron-concave-test-expected.csg b/tests/regression/dumptest/polyhedron-concave-test-expected.csg new file mode 100644 index 00000000..864c01ee --- /dev/null +++ b/tests/regression/dumptest/polyhedron-concave-test-expected.csg @@ -0,0 +1,3 @@ +group() { + polyhedron(points = [[0, 0, 0], [2, 4, 0], [8, 4, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0], [0, 0, 5], [2, 4, 5], [8, 4, 5], [10, 0, 5], [10, 10, 5], [0, 10, 5]], faces = [[0, 1, 2, 3, 4, 5], [0, 6, 7], [0, 7, 1], [1, 7, 8], [1, 8, 2], [2, 8, 9], [2, 9, 3], [3, 9, 10], [3, 10, 4], [4, 10, 11], [4, 11, 5], [5, 11, 6], [5, 6, 0], [11, 10, 9, 8, 7, 6]], convexity = 2); +} diff --git a/tests/regression/dumptest/polyhedron-tests-expected.csg b/tests/regression/dumptest/polyhedron-tests-expected.csg index 82313982..93933444 100644 --- a/tests/regression/dumptest/polyhedron-tests-expected.csg +++ b/tests/regression/dumptest/polyhedron-tests-expected.csg @@ -7,9 +7,6 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } - multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); - } } multmatrix([[1, 0, 0, 0], [0, 1, 0, 2], [0, 0, 1, 0], [0, 0, 0, 1]]) { difference() { @@ -21,9 +18,6 @@ group() { multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1); } - multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { - polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2); - } } multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) { cube(size = [8, 3, 3], center = true); diff --git a/tests/regression/monotonepngtest/polyhedron-tests-expected.png b/tests/regression/monotonepngtest/polyhedron-tests-expected.png index 78f524c0f27c93513ea737482f6e795f97e6e72a..aedcb8f2472924956a265bc499e439185ad8284b 100644 GIT binary patch literal 9699 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 S8v64VaQULeh0=3w5B>+c)UX-= literal 9835 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 LO)i${;bQ(DR^QDN diff --git a/tests/regression/opencsgtest/polyhedron-concave-test-expected.png b/tests/regression/opencsgtest/polyhedron-concave-test-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c45cc11cb7c72da78addcc2558521b66cb42f99a GIT binary patch literal 7271 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 literal 7061 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 Date: Mon, 2 Feb 2015 14:05:49 -0500 Subject: [PATCH 154/174] Added NBSP tests --- testdata/scad/misc/nbsp-latin1-test.scad | 2 ++ testdata/scad/misc/nbsp-utf8-test.scad | 2 ++ tests/CMakeLists.txt | 2 ++ tests/regression/echotest/nbsp-latin1-test-expected.echo | 1 + tests/regression/echotest/nbsp-utf8-test-expected.echo | 1 + 5 files changed, 8 insertions(+) create mode 100644 testdata/scad/misc/nbsp-latin1-test.scad create mode 100644 testdata/scad/misc/nbsp-utf8-test.scad create mode 100644 tests/regression/echotest/nbsp-latin1-test-expected.echo create mode 100644 tests/regression/echotest/nbsp-utf8-test-expected.echo diff --git a/testdata/scad/misc/nbsp-latin1-test.scad b/testdata/scad/misc/nbsp-latin1-test.scad new file mode 100644 index 00000000..3d8bbfe9 --- /dev/null +++ b/testdata/scad/misc/nbsp-latin1-test.scad @@ -0,0 +1,2 @@ +a = 1;   // Latin-1 NBSP (no-break space) +echo(a); diff --git a/testdata/scad/misc/nbsp-utf8-test.scad b/testdata/scad/misc/nbsp-utf8-test.scad new file mode 100644 index 00000000..fd929422 --- /dev/null +++ b/testdata/scad/misc/nbsp-utf8-test.scad @@ -0,0 +1,2 @@ +a = 1;   // UTF-8 NBSP (no-break space) +echo(a); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9ab9c56d..f8546e4f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1074,6 +1074,8 @@ list(APPEND ECHO_FILES ${FUNCTION_FILES} ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/no-break-space-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/unicode-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/utf8-tests.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/nbsp-utf8-test.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/nbsp-latin1-test.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/concat-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-recursive-test.scad diff --git a/tests/regression/echotest/nbsp-latin1-test-expected.echo b/tests/regression/echotest/nbsp-latin1-test-expected.echo new file mode 100644 index 00000000..ee62791e --- /dev/null +++ b/tests/regression/echotest/nbsp-latin1-test-expected.echo @@ -0,0 +1 @@ +ECHO: 1 diff --git a/tests/regression/echotest/nbsp-utf8-test-expected.echo b/tests/regression/echotest/nbsp-utf8-test-expected.echo new file mode 100644 index 00000000..ee62791e --- /dev/null +++ b/tests/regression/echotest/nbsp-utf8-test-expected.echo @@ -0,0 +1 @@ +ECHO: 1 From c0bcb368435db8ff0e87f0694e22752ddd29265d Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 2 Feb 2015 14:08:53 -0500 Subject: [PATCH 155/174] #842 bugfix: handle multiple consecutive NBSP characters --- src/lexer.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lexer.l b/src/lexer.l index c873be8e..c968edd6 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -164,7 +164,7 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); } files on the cmd-line as in the editor. */%} -\xc2\xa0 +[\xc2\xa0]+ {UNICODE}+ { parser_error_pos -= strlen(yytext); return TOK_ERROR; } From 32024588b56a774fea0ce67ca8e99ac5725ad268 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 2 Feb 2015 15:56:35 -0500 Subject: [PATCH 156/174] bugfix: Specifying multiple --debug args didn't work --- src/printutils.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/printutils.cc b/src/printutils.cc index 7098fd1a..ef1ace95 100644 --- a/src/printutils.cc +++ b/src/printutils.cc @@ -83,7 +83,7 @@ void PRINTDEBUG(const std::string &filename, const std::string &msg) boost::algorithm::to_lower( lowdebug ); if (OpenSCAD::debug=="all") { PRINT_NOCACHE( shortfname+": "+ msg ); - } else if (lowshortfname.find(lowdebug) != std::string::npos) { + } else if (lowdebug.find(lowshortfname) != std::string::npos) { PRINT_NOCACHE( shortfname+": "+ msg ); } } From 384c6af273b29796e19aa52f297a7738e6757f63 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 2 Feb 2015 16:31:17 -0500 Subject: [PATCH 157/174] Output timing for convex decomposition when doing minkowski --- src/cgalutils.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index c934ad4f..a9466b54 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -254,6 +254,7 @@ namespace CGALUtils { decomposed_nef = *nef->p3; } + t.start(); CGAL::convex_decomposition_3(decomposed_nef); // the first volume is the outer volume, which ignored in the decomposition @@ -268,6 +269,8 @@ namespace CGALUtils { PRINTDB("Minkowski: decomposed into %d convex parts", P[i].size()); + t.stop(); + PRINTDB("Minkowski: decomposition took %f s", t.time()); } } From 707103b6064612a68a0b9782c80413b0dee29589 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 2 Feb 2015 18:57:21 -0500 Subject: [PATCH 158/174] #793 Tessellate PolySets before rendering to properly support concave polygons --- src/CGALRenderer.cc | 9 ++++++++- src/CSGTermEvaluator.cc | 16 +++++++++++++++- .../cgalpngtest/issue1061-expected.png | Bin 10709 -> 10301 bytes .../opencsgtest/issue1061-expected.png | Bin 11401 -> 10864 bytes .../polyhedron-concave-test-expected.png | Bin 7271 -> 7514 bytes .../throwntogethertest/issue1061-expected.png | Bin 11401 -> 10864 bytes .../polyhedron-concave-test-expected.png | Bin 7271 -> 7514 bytes 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/CGALRenderer.cc b/src/CGALRenderer.cc index c9b816c5..a3505856 100644 --- a/src/CGALRenderer.cc +++ b/src/CGALRenderer.cc @@ -32,6 +32,7 @@ // dxfdata.h must come first for Eigen SIMD alignment issues #include "dxfdata.h" #include "polyset.h" +#include "polyset-utils.h" #include "printutils.h" #include "CGALRenderer.h" @@ -44,7 +45,13 @@ CGALRenderer::CGALRenderer(shared_ptr geom) { if (shared_ptr ps = dynamic_pointer_cast(geom)) { - this->polyset = ps; + assert(ps->getDimension() == 3); + // We need to tessellate here, in case the generated PolySet contains concave polygons + // See testdata/scad/3D/features/polyhedron-concave-test.scad + PolySet *ps_tri = new PolySet(3, ps->convexValue()); + ps_tri->setConvexity(ps->getConvexity()); + PolysetUtils::tessellate_faces(*ps, *ps_tri); + this->polyset.reset(ps_tri); } else if (shared_ptr poly = dynamic_pointer_cast(geom)) { this->polyset.reset(poly->tessellate()); diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index 4adfa62d..bae72d4a 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -11,6 +11,7 @@ #include "printutils.h" #include "GeometryEvaluator.h" #include "polyset.h" +#include "polyset-utils.h" #include #include @@ -99,7 +100,20 @@ static shared_ptr evaluate_csg_term_from_geometry(const State &state, // We cannot render Polygon2d directly, so we preprocess (tessellate) it here shared_ptr g = geom; shared_ptr p2d = dynamic_pointer_cast(geom); - if (p2d) g.reset(p2d->tessellate()); + if (p2d) { + g.reset(p2d->tessellate()); + } + else { + // We cannot render concave polygons, so tessellate any 3D PolySets + shared_ptr ps = dynamic_pointer_cast(geom); + if (ps) { + assert(ps->getDimension() == 3); + PolySet *ps_tri = new PolySet(3, ps->convexValue()); + ps_tri->setConvexity(ps->getConvexity()); + PolysetUtils::tessellate_faces(*ps, *ps_tri); + g.reset(ps_tri); + } + } shared_ptr t(new CSGTerm(g, state.matrix(), state.color(), stream.str())); if (modinst->isHighlight()) { diff --git a/tests/regression/cgalpngtest/issue1061-expected.png b/tests/regression/cgalpngtest/issue1061-expected.png index 78bd8525d0e2ef89c7874f2d97f9afbf5f0c0804..ef40d78385aa08fd75f2cff6f3f060de2db8418f 100644 GIT binary patch literal 10301 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 J_jk~v{tqGIDNO(X diff --git a/tests/regression/opencsgtest/polyhedron-concave-test-expected.png b/tests/regression/opencsgtest/polyhedron-concave-test-expected.png index c45cc11cb7c72da78addcc2558521b66cb42f99a..8e3dd762bb895573ac69dca2e661540997cf514d 100644 GIT binary patch literal 7514 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 J_jk~v{tqGIDNO(X diff --git a/tests/regression/throwntogethertest/polyhedron-concave-test-expected.png b/tests/regression/throwntogethertest/polyhedron-concave-test-expected.png index c45cc11cb7c72da78addcc2558521b66cb42f99a..8e3dd762bb895573ac69dca2e661540997cf514d 100644 GIT binary patch literal 7514 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 Date: Mon, 2 Feb 2015 19:21:49 -0500 Subject: [PATCH 159/174] #793 Don't try to tessellate empty geometry --- src/CSGTermEvaluator.cc | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index bae72d4a..e2207f76 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -99,19 +99,21 @@ static shared_ptr evaluate_csg_term_from_geometry(const State &state, // We cannot render Polygon2d directly, so we preprocess (tessellate) it here shared_ptr g = geom; - shared_ptr p2d = dynamic_pointer_cast(geom); - if (p2d) { - g.reset(p2d->tessellate()); - } - else { - // We cannot render concave polygons, so tessellate any 3D PolySets - shared_ptr ps = dynamic_pointer_cast(geom); - if (ps) { - assert(ps->getDimension() == 3); - PolySet *ps_tri = new PolySet(3, ps->convexValue()); - ps_tri->setConvexity(ps->getConvexity()); - PolysetUtils::tessellate_faces(*ps, *ps_tri); - g.reset(ps_tri); + if (!g->isEmpty()) { + shared_ptr p2d = dynamic_pointer_cast(geom); + if (p2d) { + g.reset(p2d->tessellate()); + } + else { + // We cannot render concave polygons, so tessellate any 3D PolySets + shared_ptr ps = dynamic_pointer_cast(geom); + if (ps) { + assert(ps->getDimension() == 3); + PolySet *ps_tri = new PolySet(3, ps->convexValue()); + ps_tri->setConvexity(ps->getConvexity()); + PolysetUtils::tessellate_faces(*ps, *ps_tri); + g.reset(ps_tri); + } } } From 8cb5adf0caf444f11f30669c35008d45474b5cfd Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 3 Feb 2015 00:48:26 -0500 Subject: [PATCH 160/174] Make sure GUI event processing happens in the GUI thread. Fixes #1194 --- src/openscad.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openscad.cc b/src/openscad.cc index c0a6a15d..2bf104fa 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -605,6 +605,7 @@ void dialogInitHandler(FontCacheInitializer *initializer, void *) dialog.setMinimum(0); dialog.setMaximum(0); dialog.setCancelButton(0); + dialog.moveToThread(QApplication::instance()->thread()); QFutureWatcher futureWatcher; QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); From 0fcc1fbf835b26f6b109d663e378bcf04c137699 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 3 Feb 2015 14:35:54 -0500 Subject: [PATCH 161/174] Force execution of the progress dialog to the GUI thread. Fixes #1194 --- src/MainWindow.h | 3 +++ src/mainwin.cc | 20 ++++++++++++++++++++ src/openscad.cc | 20 +++++++++----------- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/MainWindow.h b/src/MainWindow.h index 1577a64e..67d4fd48 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -249,6 +249,8 @@ public slots: void waitAfterReload(); void autoReloadSet(bool); void setContentsChanged(); + void showFontCacheDialog(); + void hideFontCacheDialog(); private: static void report_func(const class AbstractNode*, void *vp, int mark); @@ -256,6 +258,7 @@ private: static bool undockMode; static bool reorderMode; static QSet *windows; + static class QProgressDialog *fontCacheDialog; char const * afterCompileSlot; bool procevents; diff --git a/src/mainwin.cc b/src/mainwin.cc index 1287fad7..3efe812c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -170,6 +170,8 @@ bool MainWindow::mdiMode = false; bool MainWindow::undockMode = false; bool MainWindow::reorderMode = false; +QProgressDialog *MainWindow::fontCacheDialog = NULL; + MainWindow::MainWindow(const QString &filename) : root_inst("group"), library_info_dialog(NULL), font_list_dialog(NULL), tempFile(NULL), progresswidget(NULL), contentschanged(false) { @@ -2673,3 +2675,21 @@ void MainWindow::setContentsChanged() { this->contentschanged = true; } + +void MainWindow::showFontCacheDialog() +{ + if (!MainWindow::fontCacheDialog) MainWindow::fontCacheDialog = new QProgressDialog; + QProgressDialog *dialog = MainWindow::fontCacheDialog; + + dialog->setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.")); + dialog->setMinimum(0); + dialog->setMaximum(0); + dialog->setCancelButton(0); + dialog->exec(); +} + +void MainWindow::hideFontCacheDialog() +{ + assert(MainWindow::fontCacheDialog); + MainWindow::fontCacheDialog->reset(); +} diff --git a/src/openscad.cc b/src/openscad.cc index 2bf104fa..4e689c95 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -600,25 +600,23 @@ void dialogThreadFunc(FontCacheInitializer *initializer) void dialogInitHandler(FontCacheInitializer *initializer, void *) { - QProgressDialog dialog; - dialog.setLabelText(_("Fontconfig needs to update its font cache.\nThis can take up to a couple of minutes.")); - dialog.setMinimum(0); - dialog.setMaximum(0); - dialog.setCancelButton(0); - dialog.moveToThread(QApplication::instance()->thread()); + MainWindow *mainw = *MainWindow::getWindows()->begin(); QFutureWatcher futureWatcher; - QObject::connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset())); - QObject::connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel())); - QObject::connect(&futureWatcher, SIGNAL(progressRangeChanged(int,int)), &dialog, SLOT(setRange(int,int))); - QObject::connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int))); + QObject::connect(&futureWatcher, SIGNAL(finished()), mainw, SLOT(hideFontCacheDialog())); QFuture future = QtConcurrent::run(boost::bind(dialogThreadFunc, initializer)); futureWatcher.setFuture(future); - dialog.exec(); + // We don't always get the started() signal, so we start manually + QMetaObject::invokeMethod(mainw, "showFontCacheDialog"); + // Block, in case we're in a separate thread, or the dialog was closed by the user futureWatcher.waitForFinished(); + + // We don't always receive the finished signal. We still need the signal to break + // out of the exec() though. + QMetaObject::invokeMethod(mainw, "hideFontCacheDialog"); } int gui(vector &inputFiles, const fs::path &original_path, int argc, char ** argv) From 4ce1a8d92fd83d70c5a1f8729bd83a96a7c93d49 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 4 Feb 2015 01:20:53 -0500 Subject: [PATCH 162/174] Move cursor to end of console to avoid inheriting selected paragraph style. Fixes #1186 --- src/MainWindow.h | 2 ++ src/mainwin.cc | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/MainWindow.h b/src/MainWindow.h index 67d4fd48..adce1412 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -98,6 +98,8 @@ private slots: void setColorScheme(const QString &cs); void showProgress(); void openCSGSettingsChanged(); + void consoleOutput(const std::string &msg); + private: void initActionIcon(QAction *action, const char *darkResource, const char *lightResource); void openFile(const QString &filename); diff --git a/src/mainwin.cc b/src/mainwin.cc index 3efe812c..12f7ef56 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -2638,19 +2638,27 @@ void MainWindow::quit() void MainWindow::consoleOutput(const std::string &msg, void *userdata) { - // Invoke the append function in the main thread in case the output + // Invoke the method in the main thread in case the output // originates in a worker thread. MainWindow *thisp = static_cast(userdata); + QMetaObject::invokeMethod(thisp, "consoleOutput", Q_ARG(std::string, msg)); +} + +void MainWindow::consoleOutput(const std::string &msg) +{ QString qmsg = QString::fromUtf8(msg.c_str()); if (qmsg.startsWith("WARNING:") || qmsg.startsWith("DEPRECATED:")) { - thisp->compileWarnings++; - qmsg = "" + qmsg + ""; + this->compileWarnings++; + qmsg = "" + qmsg + "\n"; } else if (qmsg.startsWith("ERROR:")) { - thisp->compileErrors++; - qmsg = "" + qmsg + ""; + this->compileErrors++; + qmsg = "" + qmsg + "\n"; } - QMetaObject::invokeMethod(thisp->console, "append", Qt::QueuedConnection, Q_ARG(QString, qmsg)); - if (thisp->procevents) QApplication::processEvents(); + QTextCursor c = this->console->textCursor(); + c.movePosition(QTextCursor::End); + this->console->setTextCursor(c); + this->console->append(qmsg); + if (this->procevents) QApplication::processEvents(); } void MainWindow::setCurrentOutput() From a203b552055d15d538c2bf2c49f87c9359fea65a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 5 Feb 2015 12:08:08 -0500 Subject: [PATCH 163/174] Reduce excessive degenerate polygon warnings --- src/polyset-utils.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/polyset-utils.cc b/src/polyset-utils.cc index 03350d92..af31188e 100644 --- a/src/polyset-utils.cc +++ b/src/polyset-utils.cc @@ -57,10 +57,10 @@ namespace PolysetUtils { else { Polygons triangles; bool err = GeometryUtils::tessellatePolygon(pgon, triangles); - if (triangles.empty()) { - degeneratePolygons++; - } - else { + // Empty triangles tend to happen quite often, + // probably due to previous floating point conversion, so + // we don't issue any warnings. + if (!triangles.empty()) { // ..and pass to the output polyhedron BOOST_FOREACH(const Polygon &t, triangles) { outps.append_poly(); From 37421bbbfa3e525945235df307817759fe827cab Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 5 Feb 2015 12:08:38 -0500 Subject: [PATCH 164/174] #1186 bugfix: Use QString in slots --- src/MainWindow.h | 2 +- src/mainwin.cc | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/MainWindow.h b/src/MainWindow.h index adce1412..41870d46 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -98,7 +98,7 @@ private slots: void setColorScheme(const QString &cs); void showProgress(); void openCSGSettingsChanged(); - void consoleOutput(const std::string &msg); + void consoleOutput(const QString &msg); private: void initActionIcon(QAction *action, const char *darkResource, const char *lightResource); diff --git a/src/mainwin.cc b/src/mainwin.cc index 12f7ef56..f175613c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -2641,18 +2641,21 @@ void MainWindow::consoleOutput(const std::string &msg, void *userdata) // Invoke the method in the main thread in case the output // originates in a worker thread. MainWindow *thisp = static_cast(userdata); - QMetaObject::invokeMethod(thisp, "consoleOutput", Q_ARG(std::string, msg)); + QMetaObject::invokeMethod(thisp, "consoleOutput", Q_ARG(QString, QString::fromStdString(msg))); } -void MainWindow::consoleOutput(const std::string &msg) +void MainWindow::consoleOutput(const QString &msg) { - QString qmsg = QString::fromUtf8(msg.c_str()); - if (qmsg.startsWith("WARNING:") || qmsg.startsWith("DEPRECATED:")) { + QString qmsg; + if (msg.startsWith("WARNING:") || msg.startsWith("DEPRECATED:")) { this->compileWarnings++; - qmsg = "" + qmsg + "\n"; - } else if (qmsg.startsWith("ERROR:")) { + qmsg = "" + msg + "\n"; + } else if (msg.startsWith("ERROR:")) { this->compileErrors++; - qmsg = "" + qmsg + "\n"; + qmsg = "" + msg + "\n"; + } + else { + qmsg = msg; } QTextCursor c = this->console->textCursor(); c.movePosition(QTextCursor::End); From a4508e3fb517acced9969eee02e81d4132f790bf Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 5 Feb 2015 17:03:19 -0500 Subject: [PATCH 165/174] Removed obsolete files --- qxs/openscad.qnfa | 71 ----------------------- qxs/openscad.qxf | 142 ---------------------------------------------- 2 files changed, 213 deletions(-) delete mode 100644 qxs/openscad.qnfa delete mode 100644 qxs/openscad.qxf diff --git a/qxs/openscad.qnfa b/qxs/openscad.qnfa deleted file mode 100644 index bdd64f2e..00000000 --- a/qxs/openscad.qnfa +++ /dev/null @@ -1,71 +0,0 @@ - - - - - /\* - \*/ - - - - // - \n - - - \\\n - \n - \\ - - - - - " - " - \n - \\[nrtvf\\"'\n] - - - - use - \n - - < - > - - - - - include - \n - - < - > - - - - ( - ) - { - } - \[ - \] - - - module - function - - - - for - if - else - - - - false - true - undef - - - -?[0-9]*.[0-9]+f? - -?[0-9]+[ulUL]* - diff --git a/qxs/openscad.qxf b/qxs/openscad.qxf deleted file mode 100644 index f0df3d54..00000000 --- a/qxs/openscad.qxf +++ /dev/null @@ -1,142 +0,0 @@ - - - - false - false - false - false - false - false - - - false - false - false - false - false - false - #008000 - - - true - false - false - false - false - false - #ff00ff - - - false - true - false - false - false - false - #a0a0a4 - - - false - true - false - false - false - false - #000080 - - - true - false - false - false - false - false - #000000 - - - true - false - false - false - false - false - #0095ff - - - true - false - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - false - #ffff00 - #ff0000 - - - true - true - false - false - false - false - #ff0000 - #ffff00 - - - true - false - false - false - false - true - #d060d0 - #ff0000 - - - false - false - false - false - false - false - #800080 - - - false - false - false - false - false - false - #ff0000 - - - false - false - false - false - false - false - #ff1493 - - From 6cecbc2a525483fff95aedd5188b361e7ed34ea3 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 5 Feb 2015 17:07:46 -0500 Subject: [PATCH 166/174] Removed unused images --- Arrowhead-Right-32.png | Bin 4196 -> 0 bytes Document-New-128.png | Bin 65838 -> 0 bytes Open-128.png | Bin 65838 -> 0 bytes Save-128.png | Bin 65838 -> 0 bytes axes.png | Bin 463 -> 0 bytes back.png | Bin 955 -> 0 bytes down.png | Bin 1029 -> 0 bytes front.png | Bin 1029 -> 0 bytes grid.png | Bin 641 -> 0 bytes openscad.png | Bin 884 -> 0 bytes right.png | Bin 882 -> 0 bytes up.png | Bin 884 -> 0 bytes 12 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Arrowhead-Right-32.png delete mode 100644 Document-New-128.png delete mode 100644 Open-128.png delete mode 100644 Save-128.png delete mode 100644 axes.png delete mode 100644 back.png delete mode 100644 down.png delete mode 100644 front.png delete mode 100644 grid.png delete mode 100644 openscad.png delete mode 100644 right.png delete mode 100644 up.png diff --git a/Arrowhead-Right-32.png b/Arrowhead-Right-32.png deleted file mode 100644 index 42dd282b0f9b21968a3c2635067f15217bf5e039..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0KA zI0SzG{+;*b%NHHODruzR-@kv|K>Yga*RNJIvI4)cAP4*h0wDeQ`}gl2_*K(D7Ulq` zBYyt)@gs@`*5Ec0*#S^T{Qdd!XC7`HRF*+^0MrrxfBpK^Ol7OE8;8vSNRF6!_wHR5 z>^i9=ipv2YM}Pn@o34KP^eG3Gtiv>hkOM%D`19w_-ZyXF@L}qvf(S7V06F6C-@m8d zzke@A1uIdFAl3m;N8J4U`LhD52^8{3aRAg2Pl2T-^@?s%9RO7S{@b^2b`<&>p`8>5 z0Mo&9pzjS3x~ae-)&W4vZv*3Bg$h=p8bOQ$fR>;C`0=9zs!l5L2sr>)1{?%tKLILP zhiMEx2LMaKjc?z+rCliqatvtV)dshUQJK*YAU_0nCf>fy SS6IImWP+!wpUXO@geCx7iR=yl diff --git a/Document-New-128.png b/Document-New-128.png deleted file mode 100644 index 7225b928d260bbc131f52ba2e4282375ed739533..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65838 zcmeHQeP~tZ8NUr7IA`4`qZE-6ij=PFir7;8V{@s?oEGQGaF9t?+$a*pkRme57*$t_ zNEuy`BKu&@KIgsXoO^Qa$D%w3 zPTue5dC%|py`SejH)~#B@YBa9PMMg=WFDV4xA7NnSIRx14u9Kb{bqM2Q=ggF`0B!U z9?LYWY*~R=y9@zCzz{G53;{#H5HJJ`0YktLFa!(%L%hC)rQput)&0{{rk6W+_N+9*Mx^ z%a>QXt=4VHI$aZme!6MON!e@HuC0o!U?mccZ<_gII}4CUwzajj21fV;4M{gm>rY#j z<%V%xym)bTzINuTI06`tm%so+X$&4!h6asFkBXOagM)*u6@O?`Fp2=i;J47|h6H%t zVw|C&p^>|H?^g8I`sf!IbA!8>Al93WDvSUoe{V{c8`c`JDp-8}{P~G;_x1I8F2hOP zV&yJexG)n$8xZ|sc{wMcW1!pS0A;jwfvE28 z?rC@K+{uO+nXN4>?ZANpGYf=OAVLVhdT0V#4^RfMySloj!uXvU;H3V&d-pzHhAI>l zK>`Q~NdR$;07apT&w!1TC$W>apP+`da>j+Z2M-?nPP~Tlq(ZmX1GsfC0+fI+woxa; z`0W~0A%a{wj(*0|&Ba&c6)kl6a{%fW*9ef305JYUbo;H^xB@7zsCY@2G`VDV7?Z}T z5kPcOH(et@3Id!wd2$l=@HcBf#V;3ub^TtV^9Retk?Ys5SCs%x6)M*Qe6Q=*|9sTX z0_@naV*+;aHi^;WZj!;xLt{uhj&EH*e*Ab<$N;_md_dRDdV?|a2D^6cs>A#J4Prck zs9i4-f0!PY#ysNU-TY@`P+wA3s51hTg5Z%OM`~`}y7jR(U@3kf2~G;VQA(Z0QWp9G zdjhPx^#BP`ymIBryKLFwx_-vd6@ckyULA*(L?`wGCMHy0ayIDp383p`1V{jFe}DgS zeYnFls2El*0y`QChIJV^D*%~|2~?LY3-tR0U|q#E0u+H5FM7OVT{LPjSCc>+UCK!q ztAM)zy{U-WvL{1*0Rf~wMt~TovGkjYHTz&OqbEs6s~^Io?+Y9lnGvJ1Vo5M|fB>ws z5g-QgQ>RYVg8;*BOU7_;8SesK$Hve?yxVWWWUdKIxjiU2UyLq?yl5Uux3H$5s$0!TT1Sq~6}7~)9)F$nJ*c&T~-Q6(>cLq)gm-{The^>lyWxRZ#|}aiUzT9lhhmVd;=LjJHv1+uPeGNxtvl}m@?;;?4C3}Q85gTZh4d`^_}djKuZ zdH^C6;)W3*XOLI|h$x)@s>4ElDU5R6vtrJW+D~KVWHKo*<|j=*b3Z$?w{Bfb!i;em4b|;5Rr=^W*vr|K$lPbbWtua z1W=9ze1(t!-Zv=3WQejO1 zr}d4Q03sGM_Q{x_y^pzp_d|kW1bs0~CzLhl>+WeWc!3d#luAo=7r0w{yK zUJ^incdnuYz%N79qRU?u*X7f2j_jgA7Z3H%8nblDK#8n{@P1Ym1XZY%+C7;qAneg8oIo!A224g-CKAz&R0^B!8U_L-uMt~RuD@g#f;Egmeje#+IGYnhs zbENXR7x}+rKDroY{uERFKoZK>d?0{Gf&dAi4JCfuCG`OKPg9dHsq+nuN!&1&avvQ! zbZ7!dAoGa8TmZwxbd-@pgKuNv=l_EMY%_Ny{f|+Q>GuFyzV!exLFRs(5`lEzDxlShvp^?zjoZ~tDDw}82Nj3EC4mW^{EGtdK2hY=tKwI~7r z{E~VAbmwcufH3Y=bnlJ23OG7ehnC$-10(O}I$iwuoTv`(7uE=Qu;SR{riX=%0AZ*U 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 diff --git a/Save-128.png b/Save-128.png deleted file mode 100644 index f56c70b1fa669dca313b4bbf9b1535c41621c300..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65838 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 WFCKpD_#wUa!50o4`0n|4KKTdmM+Hv+ diff --git a/axes.png b/axes.png deleted file mode 100644 index e7cb8e1f8d39d9a0ea64fd2daf86c3ce81a4ef2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQO_WE6)kp2|cA$`CiEBiObAE1aYF-J0b5UwyNotBh zd1gt5g1e`0KzJjcI0FNtxu=U`NW|f{)Ao8X2MV;Nzq{IUL?J`4hDY$Ni$KoSiy~sv z?3(iv^f~Mr_V#87>$21`uN892ie%Y%;my6B^S8Fzr%aD+`TJm6@v}RUY<(WSzP@}7 zrVH4AWSYkK@vk;K7Av^&j6+@)^Z(loGixoLPqL9RuIx(g>A&||K}lAyQnR#V^2rp{ zmV)fG&Y5!=iXA>rzpjzPv})J7RkK&EGCa0c;Lz0KbNtCjDMD+%qZNtyLb>5}ngR^w{%iD^9>?`Lg2w)BnN=}oy0 z*eqC1*(N72?_ld|NV|D<`q?*37Jidb_Pu%LeZaDStEBtNzt^HJf;+`0?ptLSE^3$d znjbP0l+XkK DA(po& diff --git a/back.png b/back.png deleted file mode 100644 index 35d2646445c76660dba1d4062cdf7ab425e4e9ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 955 zcmV;s14R6ZP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00SdQL_t(o!|hg0Xk1kk{?5Jk zz1JDXFwkaEhT^6LK~cnoKPzKeD~)5ojV=`m;z|%ikh*o<3fbt!tsB8f6{4i6MH4}= zqCu)CX#|OMGc+^v-rRf7J;y~;s3PrT5|P4u>wCZRo&N(&Fu??OGgQ^6s@n?(jq_<^ zW8*-p)q2cYI|rZ;ktOHcB_itorvg;9>Ajz|*3KJaP5_9i8UZwk=pr+BVvI|TM&r+Y z6;PJtkvz{&0hlMECsg&Ss-9QXj;dDH+UJOwR@e2{@*!kJs-aZsU zc$=BOVdm@1yv)q6S5$;@lae2tlZODVk6&PKgM{*IR|6R^8n_IF)xY8viE)wfHHHNh>ojj zPgOr<=8lN;i=z1WPULRH>Mye_TT|7GA%qXDwQT@x=iK|M3IJC`WI3TU8Yj(W-1;brVpCOnHyU8Dd4~ud z*mnV=!Wwf7B4@n!kNhtJlE?-C%JV$zr3QAraEQnOfHB61h%q8ZHO6C5{e$xS+mRw* zt@Qw=vMhVKs;ZM)TU+;x&@uHG<11D>7po3F!MYSJxxSi5m|^aewkVOun=9b)?Nqm<1ogI zyo^-Uh7caO+51Fvzp8#GB3~F|<^VVm=@?^XiRe*P{aHj7Rdq4X^K}4+g!wJw+&d|y zHbf5FEIWI1N$qMKmt}dxId^JjB0fn(_wI0P16WhlP6*+%dcFSpEe^DV`3*yK6@Z7e zOGLD}r-P*1?KT^Y#*8uMSpXy=OM}7SLbKWI{_8C7_YWImT&-5SMnrx;PqJ)%eLbHX drxV=O_zPa5)p#H_la&Af002ovPDHLkV1g7?uyOzZ diff --git a/down.png b/down.png deleted file mode 100644 index 149ccb5e16f65bf434e738197a84f9de23eeb321..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1029 zcmV+g1p51lP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00V7FL_t(o!|hg0XkA4V{?6RF z?`ce9f@TpzD}sxPB87q?DjE_IjA@Z9DvF{|sIFYOk*>OMr3;lTtVrDy>_QhWtr8`q zl$g2@TQrJFODrN3BfQt-<=%JioHL(`7>Tyc&ui-{-}cOz^Ua*^n>oN1wy=dZLDG@* z*Se2vHeqgV?xz0!{s)sJ83s^|F-~~zPl-tLh7uszT@=M&k|cYbb58&WBm;nM5jm-< zwGhHYXJ_Zd>q;QYvh9^hU5sxPfkru`88UUgqIg+VGgUpUs(+~Jc{6)A zgfK+1V^!gsLkNRr_KumI`+MyvRn1zh*6ZulSNuE&ET8yz-tyVwX$U*%E)SsnkdYa_PvMfJJl4JzHi1+?5NdWjM#yCcD zd}e0myMciLU0hte|4J?bunoZPA`&-D;2*n)7=SYX&a_&sV`-Xx0KjKiw!f>Z>&JBt zF@P9f0J#(7+WktmOQ_7%xI()R7;;`_FrN zdWsEgo+L>Dpes$&m-0OCXfztreSLjP>-4)rRUZK`Dk8T5$dV+f08n`Ur-&4n_vk7p z%knD`855C5(=dxdAawl8>?3?86qeum=7D5SBK?{Jo#f00000NkvXXu0mjfJ0j7l diff --git a/front.png b/front.png deleted file mode 100644 index 5e791c04035af2e5d8be66c07f76c7d04e07e61d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1029 zcmV+g1p51lP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00V7FL_t(o!|hg0XkA4V{?6RF z?`ce9f@TpzD}sxPB87q?DjE_IjA@Z9DvF{|sIFYOk*>OMr3;lTtVrDy>_QhWtr8`q zl$g2@TQrJFODrN3BfQt-<=%JioHL(`7>Tyc&ui-{-}cOz^Ua*^n>oN1wy=dZLDG@* z*Se2vHeqgV?xz0!{s)sJ83s^|F-~~zPl-tLh7uszT@=M&k|cYbb58&WBm;nM5jm-< zwGhHYXJ_Zd>q;QYvh9^hU5sxPfkru`88UUgqIg+VGgUpUs(+~Jc{6)A zgfK+1V^!gsLkNRr_KumI`+MyvRn1zh*6ZulSNuE&ET8yz-tyVwX$U*%E)SsnkdYa_PvMfJJl4JzHi1+?5NdWjM#yCcD zd}e0myMciLU0hte|4J?bunoZPA`&-D;2*n)7=SYX&a_&sV`-Xx0KjKiw!f>Z>&JBt zF@P9f0J#(7+WktmOQ_7%xI()R7;;`_FrN zdWsEgo+L>Dpes$&m-0OCXfztreSLjP>-4)rRUZK`Dk8T5$dV+f08n`Ur-&4n_vk7p z%knD`855C5(=dxdAawl8>?3?86qeum=7D5SBK?{Jo#f00000NkvXXu0mjfG8NMV diff --git a/grid.png b/grid.png deleted file mode 100644 index 1b3006275ce7c667ce30e1b8c511becd65804c28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 641 zcmV-{0)G98P)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00HSqL_t(o!|hf*ixfc+t*V|c zrrDF#VeS>00sbW(Z>KxS6%C1=iDt3c?e+PoO?MMjgGs> zFf#z0i!mMn*!SMQv)0bm)h8`CNLBTSnWq3W&-0(&`xy~EP}MVUCL#*pgZKVgk|a+> zBrS?!AHWx8cD)F!S1L> zWVR4bL?quyfn5+|+>GVFHoE_xfT}h`qdKH22(`Fvi65Dtmxy!ZYG5q;ez3zDX3rXunLK(y9I0H0!v_gYp5 zRsAR;H<(Vj8p(mG#IRitUU7h}wcC|k*2wxw=c z7I^RdD*z1<{c4)#ZI)%<0nA#Qhloh)x}KC}`7FjbA)?pDn4Pj9-Q;6&MxOx4hA-WK b0bTe52c8AtpJx@)00000NkvXXu0mjfe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00P`eL_t(o!|j*Ni(Ew%#m~J} z@72t6Xd89J0VAlOi9!&}Mp0ypfqXETMV2mfA?lytLhv65xN#75(P$?p*XR-S72#)wk|-F^PZYAb1<{(L?m-PeO=cFMWiPpH=3q7JZT@E`0Bhr4&ZSjdc-+*Vy>qz%ksgL z(nVD@RW%X$W;7Z-`oC{%X6?GJ&%_u%Nh!%50UBfcylI+OhQr|lx6_mUOHox-2l6~W z31A(-GXU#=hNyeFRMlY!;j@_}p_x@#mR&Kk%Q41}opWmd*1Y#0ni&B6tg0Jk*6DV;Kd!E>%3v@! zJo6|fq6FX?fNOPKf0||4M*w_PRj;*Lt)J$agdv12GaKyYQn@wvD4rE}jDXu7+eGB2 zZtR?E0JO3!dv!D#72Dg}->s~yl>g$GLPVYeaE6HPW#(#P0Wrq!LkJrH*0L;HUtV6m zBqCop=f1j``+H-1IfQUbMAnJuMI!2}>PAZG!c@b^%v_A|$y?qhqJw63RaGxC^Cbiv#P3xWe zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00P=cL_t(o!|hf*h+I_|{l5GD zX5Z>E777b$3JX&#DO7}@U=e>%S%XN>%0|#4AcB<`6v5aFVqqmhuo2X3cH<(OCd;C( zMG#kw5G?GHU1zeHeQ)O8^W9@Jg_xPyAv++#9Js}MoOe0zp7WjeM5dTxivJio4ymfD zLwTM*VrIoCUXmnLRaI+qb939{3P|@OkW6BXuai8PB+2dw>TRl;G#ZWfMC5~soj|YG zJCY>H7bGu+5Iz+V+_Z^mnPu7gs`@a=P4E4QvMm3ch(`e42C!Y%^;5$*A%tT9t^!yG za2>#FYF@%|nWSrm~A?RI;8m_^RH=S1WNfYT!Kqlg?Q**vg-G)iRAZYwgVt~ z@6YV*?cIIL0zwGS188~g-y+!uB9~S5Jb*JrQC!+L z16x~L+83w&uE+;1k|{|M5e}VmRTYsu##jJI$10+Qg#{l%Sar^wh%uhs+1dGU5N~#N z_E1@tpE>6iMP&V7Z_fU`WivaU=lL&LmSOA+wA<}F%xnd~+V1Y|&=7j>-|ct6i)Qu% zfWP`7{Hm_&`)+v*o6Tm62$V9-V~%5V@E`OQ`N^v{tDpS#02Dd{xg7c&bgC~Mq_aVwMkM* zE)_-b`@{sOs?~Me zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00P`eL_t(o!|j*Ni(Ew%#m~J} z@72t6Xd89J0VAlOi9!&}Mp0ypfqXETMV2mfA?lytLhv65xN#75(P$?p*XR-S72#)wk|-F^PoYONPf|*zqeS!$0B>ejMC7dZ{(feDSXKY_ zfQiVM`Erc$*DTBKBBB=nJmJ0n4Z!;o2}mgw&bb8ODuBnl_wSk6w<)D}V~pL!#l`ZL z)|Aq-W_BXa^S8{bWoBIfM^trb+8`Q^$K$uX_h9DJM05(k$q>TVF~$x6W9Bs?dWnbz zs(MaDHdS>PLilVZNoZzOmStDW>~f6pW9Qr&fHm*^hh_!)R_mv^CSeF+%ghG5xm0e=J&I?=9V6hj$2Jl9 zsT(`z8UU><%U&IgM#c8__IE2QE9Jj9rVx?m0GuJBdzrbKSU`;N`w+qgfVC{k)|Z!; zFNw$(&bhB{=KkK;UJfA~6OnZydXb3ws=ARiz9Ay#M5LcmlC(=drF33I-mI$Xp_z~4 zf70*w+e=GJtIT{H0IBMQvMevP+wJ~bEo5d{uh+}>{|Ecr(fkR*@`?I8Jhb)z0000< KMNUMnLSTZlf}v9Y From e6557822f605833cd011e5ae8dc9bc8a6ffb66e3 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 5 Feb 2015 17:08:24 -0500 Subject: [PATCH 167/174] Removed obsolete file --- mjau.gdb | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 mjau.gdb diff --git a/mjau.gdb b/mjau.gdb deleted file mode 100644 index 6d394114..00000000 --- a/mjau.gdb +++ /dev/null @@ -1,2 +0,0 @@ -set environment DYLD_LIBRARY_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib -set environment DYLD_FRAMEWORK_PATH=/Users/kintel/code/OpenSCAD/libraries/install/lib From 47f5815b49bd77e1f9d3d153fb149f44a62e81bd Mon Sep 17 00:00:00 2001 From: Lenbok Date: Fri, 6 Feb 2015 12:03:07 +1300 Subject: [PATCH 168/174] Fix problem with check-dependencies.sh during detection of qt under some circumstances. - If qtchooser is installed but qmake could not be found (either qt4 or qt5), the check would hang due to grep expecting input from stdin. - If qtchooser is installed but qmake for qt5 is not installed, the code would not actually check for the existence of qt4 qmake, since the test for ! -e $qtpath doesn't do what you want when $qtpath is empty. --- scripts/check-dependencies.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/check-dependencies.sh b/scripts/check-dependencies.sh index 242b969e..d2e7b08e 100755 --- a/scripts/check-dependencies.sh +++ b/scripts/check-dependencies.sh @@ -167,7 +167,7 @@ qt_sysver() export QT_SELECT=5 qtpath="`qtchooser -run-tool=qmake -qt=5 -query QT_INSTALL_HEADERS`"/QtCore/qglobal.h fi - if [ ! -e $qtpath ]; then + if [ ! -e "$qtpath" ]; then if qtchooser -run-tool=qmake -qt=4 -v >/dev/null 2>&1 ; then export QT_SELECT=4 qtpath="`qtchooser -run-tool=qmake -qt=4 -query QT_INSTALL_HEADERS`"/QtCore/qglobal.h @@ -193,10 +193,10 @@ qt_sysver() # netbsd qtpath=$1/qt4/include/QtCore/qglobal.h fi - if [ ! -e $qtpath ]; then - unset QT_SELECT - return - fi + fi + if [ ! -e "$qtpath" ]; then + unset QT_SELECT + return fi qtver=`grep 'define *QT_VERSION_STR *' $qtpath | awk '{print $3}'` qtver=`echo $qtver | sed s/'"'//g` From b2f2323f6b7bc9b5bc207eb0a0cd3c925613b15a Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 9 Feb 2015 01:29:32 -0500 Subject: [PATCH 169/174] #1210 Added test --- cgal/data/issue1210.polygon | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cgal/data/issue1210.polygon diff --git a/cgal/data/issue1210.polygon b/cgal/data/issue1210.polygon new file mode 100644 index 00000000..0092be09 --- /dev/null +++ b/cgal/data/issue1210.polygon @@ -0,0 +1,4 @@ +9.5,7.5,-0.5 +9.5,2,-0.5 +9.5,2,-0.4999999701976776123 +9.5,7.5,-0.4999999701976776123 From c50d927216f56a227cfccb1b1bd6d5f44041a005 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 9 Feb 2015 18:42:17 -0500 Subject: [PATCH 170/174] Fixed bug in libtess. Fixes #1210 --- src/libtess2/Source/sweep.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libtess2/Source/sweep.c b/src/libtess2/Source/sweep.c index 112f1ef5..6a927745 100755 --- a/src/libtess2/Source/sweep.c +++ b/src/libtess2/Source/sweep.c @@ -1122,11 +1122,12 @@ static void InitEdgeDict( TESStesselator *tess ) h = (tess->bmax[1] - tess->bmin[1]); /* If the bbox is empty, ensure that sentinels are not coincident by - slightly enlarging it. */ - smin = tess->bmin[0] - (w > 0 ? w : 0.01); - smax = tess->bmax[0] + (w > 0 ? w : 0.01); - tmin = tess->bmin[1] - (h > 0 ? h : 0.01); - tmax = tess->bmax[1] + (h > 0 ? h : 0.01); + slightly enlarging it. To avoid floating point precision issues, + make sure to enlarge by a minimal amount. */ + smin = tess->bmin[0] - (w > 0.01 ? w : 0.01); + smax = tess->bmax[0] + (w > 0.01 ? w : 0.01); + tmin = tess->bmin[1] - (h > 0.01 ? h : 0.01); + tmax = tess->bmax[1] + (h > 0.01 ? h : 0.01); AddSentinel( tess, smin, smax, tmin ); AddSentinel( tess, smin, smax, tmax ); From c2bd5c35373eff9310cb7bb2aa54579012706601 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 9 Feb 2015 18:46:12 -0500 Subject: [PATCH 171/174] Set the following enabled as default: show axes, show scalemarkers, automatic reload. Fixes #1205 --- src/MainWindow.ui | 2 +- src/mainwin.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/MainWindow.ui b/src/MainWindow.ui index a92889b0..422b3b2c 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -348,8 +348,8 @@ - + diff --git a/src/mainwin.cc b/src/mainwin.cc index f175613c..5bea5e12 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -604,7 +604,7 @@ void MainWindow::loadViewSettings(){ viewActionShowEdges->setChecked(true); viewModeShowEdges(); } - if (settings.value("view/showAxes").toBool()) { + if (settings.value("view/showAxes", true).toBool()) { viewActionShowAxes->setChecked(true); viewModeShowAxes(); } @@ -612,7 +612,7 @@ void MainWindow::loadViewSettings(){ viewActionShowCrosshairs->setChecked(true); viewModeShowCrosshairs(); } - if (settings.value("view/showScaleProportional").toBool()) { + if (settings.value("view/showScaleProportional", true).toBool()) { viewActionShowScaleProportional->setChecked(true); viewModeShowScaleProportional(); } @@ -635,7 +635,7 @@ void MainWindow::loadViewSettings(){ void MainWindow::loadDesignSettings() { QSettings settings; - if (settings.value("design/autoReload").toBool()) { + if (settings.value("design/autoReload", true).toBool()) { designActionAutoReload->setChecked(true); } uint polySetCacheSize = Preferences::inst()->getValue("advanced/polysetCacheSize").toUInt(); From 571d2140c1c8ebf53cfeab48b780cfcf8ae829c9 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Mon, 9 Feb 2015 19:19:00 -0500 Subject: [PATCH 172/174] Updated Mac dependency build: Allow package selection on the cmd-line, allow forcing reinstall of already installed package --- scripts/macosx-build-dependencies.sh | 369 ++++++++++++++++++--------- 1 file changed, 252 insertions(+), 117 deletions(-) diff --git a/scripts/macosx-build-dependencies.sh b/scripts/macosx-build-dependencies.sh index d4f7e99e..244c2800 100755 --- a/scripts/macosx-build-dependencies.sh +++ b/scripts/macosx-build-dependencies.sh @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash # # This script builds all library dependencies of OpenSCAD for Mac OS X. # The libraries will be build in 64-bit (and optionally 32-bit mode) mode @@ -6,18 +6,18 @@ # # This script must be run from the OpenSCAD source root directory # -# Usage: macosx-build-dependencies.sh [-6lcd] +# Usage: macosx-build-dependencies.sh [-6lcd] [] # -6 Build only 64-bit binaries # -l Force use of LLVM compiler # -c Force use of clang compiler # -d Build for deployment (if not specified, e.g. Sparkle won't be built) +# -f Force build even if package is installed # # Prerequisites: # - MacPorts: curl, cmake # # FIXME: # o Verbose option -# o Force rebuild vs. only rebuild changes # BASEDIR=$PWD/../libraries @@ -30,17 +30,116 @@ OPTION_LLVM=false OPTION_CLANG=false OPTION_GCC=false OPTION_DEPLOY=false +OPTION_FORCE=0 + +PACKAGES=( + "eigen 3.2.4" + "gmp 5.1.3" + "mpfr 3.1.2" + "boost 1.57.0" + "qt5 5.4.0" + "qscintilla 2.8.4" + # NB! For eigen, also update the path in the function + # NB! For CGAL, also update the actual download URL in the function + "cgal 4.5.1" + "glew 1.12.0" + "gettext 0.19.4" + "libffi 3.2.1" + "glib2 2.42.1" + "opencsg 1.4.0" + "freetype 2.5.5" + "ragel 6.9" + "harfbuzz 0.9.37" + "libxml2 2.9.2" + "fontconfig 2.11.1" +) +DEPLOY_PACKAGES=( + "sparkle Cocoanetics:1e7dcb1a48b96d1a8c62100b5864bd50211cbae1" +) printUsage() { - echo "Usage: $0 [-6lcd]" + echo "Usage: $0 [-6lcd] []" echo echo " -6 Build only 64-bit binaries" echo " -l Force use of LLVM compiler" echo " -c Force use of clang compiler" echo " -d Build for deployment" + echo " -f Force build even if package is installed" + echo + echo " If is not specified, builds all packages" } +# Outputs all package names +all_packages() +{ + for i in $(seq 0 $(( ${#PACKAGES[@]} - 1 )) ); do + local p=${PACKAGES[$i]} + echo -n "${p%%\ *} " # Cut at first space + done +} + +# Usage: package_version +# Outputs the package version for the given package +package_version() +{ + for i in $(seq 0 $(( ${#PACKAGES[@]} - 1 )) ); do + local p=${PACKAGES[$i]} + if [ "$1" = "${p%%\ *}" ]; then + echo "${p#*\ }" # cut until first space + return 0 + fi + done + return 1 +} + +# Usage: build +build() +{ + local package=$1 + local version=$2 + + local should_install=$(( $OPTION_FORCE == 1 )) + if [[ $should_install == 0 ]]; then + is_installed $package $version + should_install=$? + fi + if [[ $should_install == 1 ]]; then + set -e + build_$package $version + set +e + fi + +} + +# Usage: is_installed [] +# Returns success (0) if the/a version of the package is already installed +is_installed() +{ + if check_$1 $2; then + echo "$1 already installed - not building" + return 0 + fi + return 1 +} + +# Usage: check_dir +# Checks if $DEPLOYDIR/ exists and is a folder +# Returns success (0) if the folder exists +check_dir() +{ + test -d "$DEPLOYDIR/$1" +} + +# Usage: check_file +# Checks if $DEPLOYDIR/ exists and is a file +# Returns success (0) if the file exists +check_file() +{ + test -f "$DEPLOYDIR/$1" +} + + patch_qt_disable_core_wlan() { version="$1" @@ -104,15 +203,15 @@ build_qt() make -j"$NUMCPU" install } +check_qt5() +{ + check_dir lib/QtCore.framework +} + build_qt5() { version=$1 - if [ -d $DEPLOYDIR/lib/QtCore.framework ]; then - echo "Qt5 already installed. not building" - return - fi - echo "Building Qt" $version "..." cd $BASEDIR/src v=(${version//./ }) # Split into array @@ -133,6 +232,11 @@ build_qt5() make -j"$NUMCPU" install } +check_qscintilla() +{ + check_file include/Qsci/qsciscintilla.h +} + build_qscintilla() { version=$1 @@ -149,6 +253,11 @@ build_qscintilla() install_name_tool -id $DEPLOYDIR/lib/libqscintilla2.dylib $DEPLOYDIR/lib/libqscintilla2.dylib } +check_gmp() +{ + check_file lib/libgmp.dylib +} + # Hack warning: gmplib is built separately in 32-bit and 64-bit mode # and then merged afterwards. gmplib's header files are dependent on # the CPU architecture on which configure was run and will be patched accordingly. @@ -156,11 +265,6 @@ build_gmp() { version=$1 - if [ -f $DEPLOYDIR/lib/libgmp.dylib ]; then - echo "gmp already installed. not building" - return - fi - echo "Building gmp" $version "..." cd $BASEDIR/src rm -rf gmp-$version @@ -252,17 +356,17 @@ EOF cp x86_64/include/gmpxx.h include/ } +check_mpfr() +{ + check_file include/mpfr.h +} + # As with gmplib, mpfr is built separately in 32-bit and 64-bit mode and then merged # afterwards. build_mpfr() { version=$1 - if [ -f $DEPLOYDIR/include/mpfr.h ]; then - echo "mpfr already installed. not building" - return - fi - echo "Building mpfr" $version "..." cd $BASEDIR/src rm -rf mpfr-$version @@ -300,15 +404,15 @@ build_mpfr() cp x86_64/include/mpf2mpfr.h include/ } +check_boost() +{ + check_file lib/libboost_system.dylib +} + build_boost() { version=$1 - if [ -f $DEPLOYDIR/lib/libboost_system.dylib ]; then - echo "boost already installed. not building" - return - fi - bversion=`echo $version | tr "." "_"` echo "Building boost" $version "..." cd $BASEDIR/src @@ -343,15 +447,15 @@ build_boost() } +check_cgal() +{ + check_file lib/libCGAL.dylib +} + build_cgal() { version=$1 - if [ -f $DEPLOYDIR/lib/libCGAL.dylib ]; then - echo "cgal already installed. not building" - return - fi - echo "Building CGAL" $version "..." cd $BASEDIR/src rm -rf CGAL-$version @@ -383,15 +487,15 @@ build_cgal() install_name_tool -change $PWD/lib/libCGAL.9.dylib $DEPLOYDIR/lib/libCGAL.dylib $DEPLOYDIR/lib/libCGAL_Core.dylib } +check_glew() +{ + check_file lib/libGLEW.dylib +} + build_glew() { version=$1 - if [ -f $DEPLOYDIR/lib/libGLEW.dylib ]; then - echo "glew already installed. not building" - return - fi - echo "Building GLEW" $version "..." cd $BASEDIR/src rm -rf glew-$version @@ -407,15 +511,15 @@ build_glew() make GLEW_DEST=$DEPLOYDIR CC=$CC CFLAGS.EXTRA="-no-cpp-precomp -dynamic -fno-common -mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" LDFLAGS.EXTRA="-mmacosx-version-min=$MAC_OSX_VERSION_MIN $GLEW_EXTRA_FLAGS -arch x86_64" STRIP= install } +check_opencsg() +{ + check_file lib/libopencsg.dylib +} + build_opencsg() { version=$1 - if [ -f $DEPLOYDIR/lib/libopencsg.dylib ]; then - echo "opencsg already installed. not building" - return - fi - echo "Building OpenCSG" $version "..." cd $BASEDIR/src rm -rf OpenCSG-$version @@ -432,15 +536,23 @@ build_opencsg() make install } +# Usage: func [] +check_eigen() +{ + # To check version: + # include/eigen3/Eigen/src/Core/util/Macros.h: + # #define EIGEN_WORLD_VERSION 3 + # #define EIGEN_MAJOR_VERSION 2 + # #define EIGEN_MINOR_VERSION 3 + + check_dir include/eigen3 +} + +# Usage: func build_eigen() { version=$1 - if [ -d $DEPLOYDIR/include/eigen3 ]; then - echo "eigen3 already installed. not building" - return - fi - echo "Building eigen" $version "..." cd $BASEDIR/src rm -rf eigen-$version @@ -453,6 +565,7 @@ build_eigen() elif [ $version = "3.2.1" ]; then EIGENDIR=eigen-eigen-6b38706d90a9; elif [ $version = "3.2.2" ]; then EIGENDIR=eigen-eigen-1306d75b4a21; elif [ $version = "3.2.3" ]; then EIGENDIR=eigen-eigen-36fd1ba04c12; + elif [ $version = "3.2.4" ]; then EIGENDIR=eigen-eigen-10219c95fe65; fi if [ $EIGENDIR = "none" ]; then @@ -473,19 +586,28 @@ build_eigen() if $OPTION_32BIT; then EIGEN_EXTRA_FLAGS=";i386" fi - cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_BUILD_LIB=ON -DBUILD_SHARED_LIBS=FALSE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$EIGEN_EXTRA_FLAGS" .. + cmake -DCMAKE_INSTALL_PREFIX=$DEPLOYDIR -DEIGEN_TEST_NOQT=TRUE -DCMAKE_OSX_DEPLOYMENT_TARGET="$MAC_OSX_VERSION_MIN" -DCMAKE_OSX_ARCHITECTURES="x86_64$EIGEN_EXTRA_FLAGS" .. make -j"$NUMCPU" install - make install } +check_sparkle() +{ + check_file lib/Sparkle.framework/Sparkle +} + +# Usage: build_sparkle : build_sparkle() { + v=$1 + github=${1%%:*} # Cut at first colon + version=${1#*:} # cut until first colon + + echo "Building Sparkle" $version "..." + # Let Sparkle use the default compiler unset CC unset CXX - github=$1 - version=$2 - echo "Building Sparkle" $version "..." + cd $BASEDIR/src rm -rf Sparkle-$version if [ ! -f Sparkle-$version.zip ]; then @@ -504,15 +626,15 @@ build_sparkle() install_name_tool -id $DEPLOYDIR/lib/Sparkle.framework/Versions/A/Sparkle $DEPLOYDIR/lib/Sparkle.framework/Sparkle } +check_freetype() +{ + check_file lib/libfreetype.dylib +} + build_freetype() { version="$1" - extra_config_flags="$2" - - if [ -f $DEPLOYDIR/lib/libfreetype.dylib ]; then - echo "freetype already installed. not building" - return - fi + extra_config_flags="--without-png" echo "Building freetype $version..." cd "$BASEDIR"/src @@ -522,20 +644,23 @@ build_freetype() fi tar xzf "freetype-$version.tar.gz" cd "freetype-$version" + + export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" + export FREETYPE_LIBS="-L$DEPLOYDIR/lib -lfreetype" PKG_CONFIG_LIBDIR="$DEPLOYDOR/lib/pkgconfig" ./configure --prefix="$DEPLOYDIR" CFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN LDFLAGS=-mmacosx-version-min=$MAC_OSX_VERSION_MIN $extra_config_flags make -j"$NUMCPU" make install } +check_libxml2() +{ + check_file lib/libxml2.dylib +} + build_libxml2() { version="$1" - if [ -f $DEPLOYDIR/lib/libxml2.dylib ]; then - echo "libxml2 already installed. not building" - return - fi - echo "Building libxml2 $version..." cd "$BASEDIR"/src rm -rf "libxml2-$version" @@ -549,15 +674,15 @@ build_libxml2() make install } +check_fontconfig() +{ + check_file lib/libfontconfig.dylib +} + build_fontconfig() { version=$1 - if [ -f $DEPLOYDIR/lib/libfontconfig.dylib ]; then - echo "fontconfig already installed. not building" - return - fi - echo "Building fontconfig $version..." cd "$BASEDIR"/src rm -rf "fontconfig-$version" @@ -573,15 +698,15 @@ build_fontconfig() make install } +check_libffi() +{ + check_file lib/libffi.dylib +} + build_libffi() { version="$1" - if [ -f $DEPLOYDIR/lib/libffi.dylib ]; then - echo "libffi already installed. not building" - return - fi - echo "Building libffi $version..." cd "$BASEDIR"/src rm -rf "libffi-$version" @@ -595,15 +720,15 @@ build_libffi() make install } +check_gettext() +{ + check_file lib/libgettextlib.dylib +} + build_gettext() { version="$1" - if [ -f $DEPLOYDIR/lib/libgettextlib.dylib ]; then - echo "gettext already installed. not building" - return - fi - echo "Building gettext $version..." cd "$BASEDIR"/src rm -rf "gettext-$version" @@ -618,15 +743,15 @@ build_gettext() make install } +check_glib2() +{ + check_file lib/libglib-2.0.dylib +} + build_glib2() { version="$1" - if [ -f $DEPLOYDIR/lib/libglib-2.0.dylib ]; then - echo "glib2 already installed. not building" - return - fi - echo "Building glib2 $version..." cd "$BASEDIR"/src @@ -645,15 +770,15 @@ build_glib2() make install } +check_ragel() +{ + check_file bin/ragel +} + build_ragel() { version=$1 - if [ -f $DEPLOYDIR/bin/ragel ]; then - echo "ragel already installed. not building" - return - fi - echo "Building ragel $version..." cd "$BASEDIR"/src rm -rf "ragel-$version" @@ -668,15 +793,15 @@ build_ragel() make install } +check_harfbuzz() +{ + check_file lib/libharfbuzz.dylib +} + build_harfbuzz() { version=$1 - extra_config_flags="$2" - - if [ -f $DEPLOYDIR/lib/libharfbuzz.dylib ]; then - echo "harfbuzz already installed. not building" - return - fi + extra_config_flags="--with-coretext=auto --with-glib=no" echo "Building harfbuzz $version..." cd "$BASEDIR"/src @@ -700,19 +825,27 @@ if [ ! -f $OPENSCADDIR/openscad.pro ]; then fi OPENSCAD_SCRIPTDIR=$PWD/scripts -while getopts '6lcd' c +while getopts '6lcdf' c do case $c in 6) OPTION_32BIT=false;; l) OPTION_LLVM=true;; c) OPTION_CLANG=true;; d) OPTION_DEPLOY=true;; + f) OPTION_FORCE=1;; + *) printUsage;exit 1;; esac done +OPTION_PACKAGES="${@:$OPTIND}" + OSX_VERSION=`sw_vers -productVersion | cut -d. -f2` -if (( $OSX_VERSION >= 8 )); then - echo "Detected Mountain Lion (10.8) or later" +if (( $OSX_VERSION >= 10 )); then + echo "Detected Yosemite (10.10) or later" +elif (( $OSX_VERSION >= 9 )); then + echo "Detected Mavericks (10.9)" +elif (( $OSX_VERSION >= 8 )); then + echo "Detected Mountain Lion (10.8)" elif (( $OSX_VERSION >= 7 )); then echo "Detected Lion (10.7)" else @@ -771,30 +904,32 @@ else echo "Building 64-bit binaries" fi +if (( $OPTION_FORCE )); then + echo "Forcing rebuild" +fi + echo "Using basedir:" $BASEDIR mkdir -p $SRCDIR $DEPLOYDIR -build_qt5 5.4.0 -build_qscintilla 2.8.4 -# NB! For eigen, also update the path in the function -build_eigen 3.2.3 -build_gmp 5.1.3 -build_mpfr 3.1.2 -build_boost 1.57.0 -# NB! For CGAL, also update the actual download URL in the function -build_cgal 4.5.1 -build_glew 1.11.0 -build_gettext 0.19.4 -build_libffi 3.2.1 -build_glib2 2.42.1 -build_opencsg 1.4.0 -build_freetype 2.5.5 --without-png -build_ragel 6.9 -build_harfbuzz 0.9.37 "--with-coretext=auto --with-glib=no" -export FREETYPE_CFLAGS="-I$DEPLOYDIR/include -I$DEPLOYDIR/include/freetype2" -export FREETYPE_LIBS="-L$DEPLOYDIR/lib -lfreetype" -build_libxml2 2.9.2 -build_fontconfig 2.11.1 + +# Only build deploy packages in deploy mode if $OPTION_DEPLOY; then -# build_sparkle andymatuschak 0ed83cf9f2eeb425d4fdd141c01a29d843970c20 - build_sparkle Cocoanetics 1e7dcb1a48b96d1a8c62100b5864bd50211cbae1 + # Array concatenation + PACKAGES=("${PACKAGES[@]}" "${DEPLOY_PACKAGES[@]}") fi + +# Build specified (or all) packages +ALL_PACKAGES=$(all_packages) +if [ -z "$OPTION_PACKAGES" ]; then + OPTION_PACKAGES=$ALL_PACKAGES +fi + +echo "Building packages: $OPTION_PACKAGES" +echo + +for package in $OPTION_PACKAGES; do + if [[ $ALL_PACKAGES =~ $package ]]; then + build $package $(package_version $package) + else + echo "Skipping unknown package $package" + fi +done From 0fefd42250977869bf6c1436d17c409503257cf0 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 10 Feb 2015 12:21:53 -0500 Subject: [PATCH 173/174] The margin checkerboard was a bit visually disturbing --- src/scintillaeditor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scintillaeditor.cpp b/src/scintillaeditor.cpp index fdebead8..bf6bb9e0 100644 --- a/src/scintillaeditor.cpp +++ b/src/scintillaeditor.cpp @@ -307,14 +307,14 @@ void ScintillaEditor::setColormap(const EditorColorScheme *colorScheme) qsci->setWhitespaceForegroundColor(readColor(colors, "whitespace-foreground", textColor)); qsci->setMarginsBackgroundColor(readColor(colors, "margin-background", paperColor)); qsci->setMarginsForegroundColor(readColor(colors, "margin-foreground", textColor)); + qsci->setFoldMarginColors(readColor(colors, "margin-background", paperColor), + readColor(colors, "margin-background", paperColor)); qsci->setMatchedBraceBackgroundColor(readColor(colors, "matched-brace-background", paperColor)); qsci->setMatchedBraceForegroundColor(readColor(colors, "matched-brace-foreground", textColor)); qsci->setUnmatchedBraceBackgroundColor(readColor(colors, "unmatched-brace-background", paperColor)); qsci->setUnmatchedBraceForegroundColor(readColor(colors, "unmatched-brace-foreground", textColor)); qsci->setSelectionForegroundColor(readColor(colors, "selection-foreground", paperColor)); qsci->setSelectionBackgroundColor(readColor(colors, "selection-background", textColor)); - qsci->setFoldMarginColors(readColor(colors, "margin-foreground", textColor), - readColor(colors, "margin-background", paperColor)); qsci->setEdgeColor(readColor(colors, "edge", textColor)); } catch (std::exception e) { noColor(); From 2cbbf66586dc28cc3baab98b917697f5b993a21f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 10 Feb 2015 14:10:25 -0500 Subject: [PATCH 174/174] Support high-resolution icons if present --- src/openscad.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openscad.cc b/src/openscad.cc index 4e689c95..0953ffdb 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -642,6 +642,7 @@ int gui(vector &inputFiles, const fs::path &original_path, int argc, cha QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION)); #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) QGuiApplication::setApplicationDisplayName("OpenSCAD"); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #else QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #endif

    BgF$BC+&S3t70Q>3Tp(wmrbG6`yB# zpg0Qs(UK0&RP)s6j~h3qc476X`Ri7@`V>{m=CL-T%2~>{4hMZ96w=w;oI!e9N?94j zoN2N*4zHLdcULq!SG7IA^ud8r#X(tmDbhQ|m6`|PLIo(aUBHTn>eg|+SpVe<<~?9bOA_r*FO?_0E zP2@Y4MoEllm~0tiP5S1CS)Fnb+&8VPHTF!@)nthFW@5&A|J$t1@;{mhI>B&6eh0)4 zsK#epM3(e~Ay=H=J)r}k{ij>&8`6z)KM)43l@dK~fALn@&^xYOy+lXb@t-2~^y;!0XSAs(-7tXOJfIx3<_@J+dZ=xk#nLQ|B-o zjM1Bd&`QgwJ_L5PEv8~TfYs|J>Fl;wiU;hm>rS7`C|+w98J54I>*U&>eq;c)ld#(D6#7GS zvhbZ%d^g!RozVRdbTSXUG&r9t0>bnc8O)_m@Y3cEuWT8Lgou&z)?K$Jfy1lJj?^g1htRD$AXftr?01D&=s$q9I_jd2%N# z{^DZxO=vIhtZVTA<5%kZY!rcQ_~xH2KTFiTWqIRDS`xZoe1_V%Z2Oa;)$ms|mJ5yO zrpu^&0^FQzT;Yi9-Sp~vT#%(gm?C$l!o5^WmVYYKoPBwyb(Nc_Kxn0qGPHW1{e^-v zoI#iVW-Wjh<{kR0t2fRguq*GCi+p5lQ|2(aZa^n-D!^nx28t3Xi)7q5=h+#BYh{g1 zn{W1o#_WEYK=`)15)F@{y6)D7BGIE;LKDE&VVfwfG2cU`=qYREx2+lVV>|hZ76);r zljZH(cJf!GVu1iKr1ok<5bhcFKEWA>YmQ=K1-#u5z77=4X_}J6Pygfz`)vbESwA-K zA}LBA8JM4N(bXUyU!;_Y7fZarj$)JE`J~*Q*`1d5U^TCVt$)y?5{E1)pxsm5p@{%7CT(TiWN zp0sXEw6vn8b`O?+3>@|+pFCYJK)Xvd{FpzE0HWwtOd|IXgrQPJJ)xXFJ%V|z&3S=K zVd!`;ZwE^}_3U3z=|~Ot zS`w+I^w=mbPV9>Gt9c0Rh}fT-U9M8vJi|ew5PlnprY&i36P|+f|Lx6gq2u2sjBWTX zN-=#KyDIZ`actd!!Of};;<8+yskWn2Isedt%;@p7dpQ9KrKjvhvOv1~?txC{iHT7_ z>mFh3+xDMybxpcg?g&UFmBXvE%gcAF0ifaYT32ztQBK=(A{Lavkxhttm%?|~u_ zjj_Lk>QOGT)bBIF98l(dkDPEB26LyEJt!j)NHrz;sTN=w)~W$}{oN*rm2f;zO<<@v zUb#)8rl_BYv?`T#rfGw4plut}r#}MV-Esde=T7UxO*UanH5C1qA15WCmBH(Ah_YG; zK>)or1CQGWO}H9EBcluGM?qaRc5}Dd@tKVq7VXdDjF(nQ{8|{BFfmd#)(HZMLdu3*ltV!~J{lzN3Oa4B*-8-EeeL*x zFH}0tz~x!Cl)I)lbILYNUnL`q!k5I_j{=0W+lHulxt#ur+n%|Zseco-pn;l_N047= zvD;sOAV0r3e#pypeTsVh9JnnEv;!~%IV*d#1kB3l1Yc{?dz8KEh&HpJN@r<^D76k+ ze0l747R^(>Yg(;5pYLC+h{y^o3uzVoT1O~pD1GRYoX?x#WEs#44DG}{QC)eA@^=^F zvL`tzr^iH|%pCP^JNG0P3SfbJyNtmd3$FUC)@#pROP8W)HfuZ!-yPz-ryXbU%Cs-m z1%MZXKhgnTW0+QF&c}VfrV8H)9qm z0Y$&^i|Q>MFvQk|Ui^G>#6MdE5>H;u;E&Mk-D=&+=asQfO$QSkso|yXzsaxSEa+&B zL*l3Wi=+3nbj5uC4t4NY*bO-zsk02S>zrEaWw+4+>KlzxGIA!6A5d3wK-BF~9N`iO$LJ#%B&gch#fqWu_SO>s4YJbAC1+V^s7%psJXcZ!FdwsUi^>F&OoP>$vPEV+5$dHM8L)KjDKJWF_BqZA9^G`g#v?SB& zw-Z{Kk*TytQhqtVXU1-Kt@w{kjfDag|xX$Fn>o(Z|aY-+Up=v67n)Lwu# zCTa*Mgob|!+tB7iAH;{ql(WE5mj(b=LvQPxP0kGL1NE;k8$IL#@ud=f4XXql5Uty$RWMXNUdeMiqQXxCG(UL{)Nyq|4HHG_|;Tg zUOa4gfQR1EoVtt)Bl4d2qII-+0_hzu)cQP6?&4*hAmG|!C6>*F5lwLZKy z-}n*)?BXAMdGPoyN@D-Uk3f|+E^M{f(E`amc&UN?t-}#MWK|*qNszclBWBa=?ir|v zyU&yqsq$T&+lKzCKRU%5c_c{k_POp9ADps z5Hmqv3j{iSvY8q zpSe0e8tn_(GRBU6XiJ}eFS2ALQMIwff=VK_dUdr39n_Dg@c}y5tew%5>UI-G6ZsnU z$1j7|($;yWE+b&z4H5_BSx?`mYILIf@rxf5TkvC*D|y4$nJj(pt*g-7ik%AI{Y6WI z>d?yUeR;p!|OYJw_s!E$w9>=TTY8%rcId1 zjpfmCsc<(+{wVhE=#gM3p>D&%#?pVB!ZF5^*k+o@iA1-3zmo)zk{*Z|Nh2CR^5dum zu&X??)(2*nw)U2ypPqN+hMX0snf^B?h&~K2Ciu(bELy-L#_@9$3G6tyx#LDsF5New zdm}fg&KNJ`K8BY!KXgnb-Cd)n)P&obYMq|42C;Yps28!N80*g*#fvO607H>|*S}Ql z81dJvw|3aC(-^0&ho-~tsU7(g$P<>XeAk;~*FpU7<8nJO)henqFORk>R$LI#B5eBg7|_@6QT|{JHbyw%KA3 zDPYM*(r}MR{Q9Q##Nxeqk}8&CuIq`V8`b9F(T&UPJkTt791ksTfKCgYrBD!F&1%g& zk`nl@=Ud5#q@FzMbdk@*JP}BY87{&rm6<+G?s+HufmSuft~b9S1{h{D#)oH9%^>X} zv$L#F`i2J6_{u-6WIG;m4N0Z#V-Y_*yU3$nIZqBXFPJ?!p+i*oQx_0CF5@0*-YL0w zSItjdpJ-1JJ-d7M0TYNdC6>negCsw-Syi_CD(4;f28n0P|19!UV_u_lUBkH0a>;4* zS41Fmrnoy}hi)RIa#;t5LAHn|JTK`4m@iM;G?P8|Q<|wOD~W^=9tYr(Ce>?k2BqCk z-p3;&fCFN!gD}0i_+~?BrdKQY$GH@e`u=!RpDtqwST?xBQm7$vhU7VF)-vCP3i8>+XK^NIQ%-i@^Mz3bNMlSC5i^W6^c@Uc8V zu7+74O-xq}j@6L;bnQ7YD(C3cI2%_pmDH3i^peLngDUIm;*QHG=RXB@b<>Z}cw5~y zdI{WN7WCl+ODG+8Q9i9Vie>I3Yx}jbM{@3KJ)-E0JvDBC^T+3Z^S%=}kc>#>m1i0h z*F0|hbCsI;ET6RMiCM9YBPN0(aN?pG2MlvxxzXChogHm9K!#ML*7=U9ddtg>U3yv5 zB`kkP_gO7tc*ZT{3tqa2>VBVken<#QtGK^dHU%2nx-V>oJK2^qsi~W_gGa1Otsra> zsEg?t2JWntOPT&?rxmlnM{{lG#BtNdhCahHrG^KakYbVm)F=Q>P2zPSTzpGQWYu!r+mb7wZ+ozDA16cF&|VC3|%?w|L4eZO1Kp4a{n zs(0Ek)fDEKVOb=0xO?KngnKKNtJhtjM~-k-L4Q!jnYNDcC-wAamfiM{W_6iU+l)0} z_-GC-;nQa!`X2pojPrgIntOKB1qh86z3z66k>{6XebW-II8w1As*PjOn&{oh?l(M-pVp^p>q{QaC-kz z>C0w;1taY}Wco&$h493P&6TWjgOzKKPBu2-ucA%`hdYkz^aA!>K0{5~JsP75Qd8qs z?J~6GC_%p;*`1h=+mIG})G6IOqft+*slYNUopIKlu@v>cs~pO%d`{JUbm4Zgu!hf- z62EOwAD5l#w{NW4z)dD}kk}7Vm$r4C3FG)f$%au%dX*k_B;@W{|B~!a^e0Cb*G635 z{u*zs)l*r&mb~6-do=U+1v%i5{-o(9j?>wfy;*fYGu0$W`yc#CYRT%pXPy?{OQL z0v1y2R-Up)R5BjYTFUomlvMb;XRGj;H#6V)DrQ6lNng*MaQn2G(;`WYASV^2U(yEB z8C%=`Z9GdTQBH<*?XSdCOpITBK=ju*e!W{aD|@17$n}b}OI_4?#sXR*_%y@!wZeEHZlVHH=3V5 zI|>69vL#C5=AI=yGjzpn|Inp>XaLRMgq6-wv{%i#y$_a*c|8xG&KiQH14o^{U3giK zhAM-S&Ee->tTXPxe9#sc4|J2KKNKl}<#_3HT%7AHgND@JW?_4!gL|(D%t-?uY<=%8 zI)aJGI|uj!>o^kEk)c4YS2{@D7iq!?DW#8f#>zN!%#M3j;G4p_UNNM%gs!X`u5Rwm z@A88=a{kBnh6M(ba8--h(|1?%^hx@#5A=Kbq`Mlw6bN1it&5`-dq&$V&>rOaEx4fWO*ucqqlIR^8FBeIT+w5J$ED z4vc}p)(Zwyb}}j)K_8HRhc64b>4-`C71?q&%L1%1kK>2cJ9^SQK$}w1lDNsb^#(%m zBV@NF>E^YtELY(>{)yWeSF8JBm|bpl2!f44`7hoZLk(LTKNMLRVG-IaSi-vD^yW1C z`F8>YVGrex<{QlQ^FIQ3H!w?oxHlRZ(>x>n7bBZzmOd|az*8ZDh}eHL&{5~Mi6rb6 z7va|&#r6-5^_0(!2y>{2U6UBFGZ)N)5z}y1?(}m^t_o!ocer zT>Kg*tC4U*3VjmP>`9cR5c zG|WbH@Q~MHD~PwI4`1?e?4IUFs|pLk;TxEDrclp+VS;6%fXmTL-%(@TLJ*rgBQ3aE z_OtAba{9AJ_czaq%a$g$2t*x1&-2tyt4t`g12^fm(}&4)1L zu{vt0?80Y0&FLrFpS(D0d`AgPA8!HQTm0aSCDLYyt2LChX>x;KP_6=8AG~WNb8{W1 zBogAuOLdWdYJr5ANP8uL6tMq6zWV4t{SO*g^^Up!p+1lQUzyE>fGnt-*d0u^Zk6jpSdT&)L4&^j++hu07e6SZ8HFX zf<-6*KfQ!-YrO^l6kwpOVet^MmSb1#W^La|k#W0H(!e#QdCl|MTMlo!Ho#*p%aodp zRe)iX!{Bf%CfSEqQigU5`{e#t*7shVNImh>N zelJwNBOlidjjntcp7-B2X{LnOWAi3+Cxh(wCMc@e*~FTIC;)~6BKF{`UPKr1*#Eh? z421*3kkiMy2o&&Cng5+20D+@`TU1CK0OLN717w#UcAwhf0AEHl07be#2cW&>vr;@z z&;m-31I^L-H=uBIQBvnUIA{Sj_&-hm*WiC^_@CSS|M;aGbJz2{%NE`o3kvi7zK$n# ztC}0UibKDK?cMWM!&G^V45A=L@%sf4DhItq_ddXoxO?_mogxVB$J=RZnXDn5JV2HV~Wp*eWk)?T3oLUNd|4BQ3=Og(3$56XBImnHr zu(?lcs4q`pNZ_21^dcNNAMn7bRFGL}>4TX9wD)mY&YJM&t3`H|sL|Rphclx(z+->g z117ea4w;`Hb>{?~7mC-pp($AhW@{|-8A2GV<}NK;^7iUw=oCV-XeRm~@zo7y>)zO- zmdC*JIdjcWg9(r7nl7ybCOu$#n_Ey#0^6I7hNZ-zQB>Aow50Jc=escx%le305GOCb z=ng~Cg=&VLskRv9hs+695?O$t7VSqtfzP9H3K4N_$7vg(yO0f!tTzC}H;9sv6kcb2 z;G_0)enhL?8Xhf(Y7eUsD#S9!cUXrbzd}Y`Qm;}L*IH$T3uvQjkhOx64EypWT{0N} zR5D|vemKz!!!uYBw4T)5cF%)7@G0PY8^pZ1Ydo!-3oC!laXKDX6 zCN(-S=iOL+V7saWbac0=lSKw#et4Pv&Wn_ShB3rGS9?v-H8`3t{1$;uSWxOgdzjPI zW!X63{nWg+ybuDS!M0A-UR-$*3MZW5>Y+v9gh$ZALt~~wCJZ3TaT5n# zVPR1mAgpH`wE|my0c$5UH5|U+03i>iK|-wl{2G#fl0qel0*;PwEsH=~+-manNKSTF5~4 z6kX}g;ea!LC7b9$1VxZU@UTN{Q>5 zAPmF78NhX(1*5>r8C`HT-M1fbfRK#704~RcX9HBHuq+9dZ!;A&pZ2E7f(Akj!gr2{ zM^+k-PMf}lL<2AKjk8Z{r9pgmnSwQet=X_m8Tk&CcXP1-GUxn2J7oDY0BTxdCq)Og zkIMw0j;`8Frwv%LqJhc>mvl8i8%Z`a(4E)?IqlXE>^9x|%Y{=LS125p$)a>RObY`5 zQvT~TCpBn8xDG%hWrS!?rzHl41_bMnYQHVQ&Ol&u zbog>-JZR-bJh^Zx0e{?d;B!uTibjlRCbSd8$EFp)ReHJELkVH(dHh-L!`@SlR7gD! z?=jMmW=hNF^=hOHuHvJ*=fR{7MJ}!KMMRb>AiYzyo?Qhgte#hKwDITWay+OxQs|PB z!J#-aDqO_YgIY7$No5R+u2e$lh)-t0t-koiQg(N9nU8uo=da!Q3$us0Cw6ALjMr*>2E3Gq1Wggg6~Y;NgtDKXBb##{grz z(Z{MurJX9N(Y7joIY&-XCTyhNK~fZ2i#p*l3hKi!PzI&781NrzMZZo(q{Ufv(Qm;&3PdE4A% z1%x8`JN1^*cGp3hR2p!N_VP$`t{4Ofcuz}VVh~UaEjbl6&ITn032dyRjC}fBPY!h_m}K^TD4V+)b|p| zSy{GBzX+MxbLx8;mz#{BF83ex#)KbQ@?STC@`r|o`l0CkYQ@2@#Ystap!{|WShEl= zq6}|yXJiP zAzh#7XTwtZuqw7nA@g@Uvpa-zYGA3c6vJdIcbuW~(3bn+K8D&a7d9S5F~}a||0xVG zz6^jAcXwBz%zg#l`{8$>elw)u%7eL7^P&nS(Wl@_xRpWT!pjmeu3f8AW!5diyXAO) z!Kl0#_Q7w8C@QEgUz4Kh{bwsa=yssK`d(R3U-HEID!~F>QlLJhM}egQEIadhlY@O0 zB9I~*KeYs4Zjn#!=os|G4~X**$JWO3ZdYz4k~T4~>A*$4&bLxTv8ZTVh@;n#p7D%5 zfw-mkU%gH)2Y0mmp}m-O5&rFo?=A-8LLtA-3tb`?vp%4`T2^!-z}V|-#6}ua>-t!e zyQA*PIz^Pc!w5$kj{f}++^4>}iJ5Gvq%BhV6HBQRD}Z$2iVOHh^ssrB`JUmfnEfS9 z{3s-Q7L^7BMtPZ*b$5vP8jePcZF7-VnuR{2e{PcEBG&}z86E9x?sy822F>I3ov*lS#=wUd_x>w>hYz>`u9(7we_tQFOCZCdOY1M@jZ{^xwjC!;TK zT=-NQH;EnDduvhv8Kz7e$H~bCd=)&pre6F~**6gRKCDMAWw}C5YT^@-A}E;+awHzxL}(^6CG7fo zMf<2s38r~}do@Cf4o@r@l=2X=RlGS6rg?7Qf> zFE+WXex?uq;M`h6q#O|jhhz7)>aYGZ>@;(yu;5mCGsZU6Ih>}(0q74)}29)o-;L)3SQ#2&A|A*PbHc3!Y zhwzBqy;8G>LmPl}b=m4N>W>dUUs3<{K1&3$6-!|quA^m21C&lM9~RzEfOO?-GwU1; zZt+vV@V!ZdatVZ~gHk<&b-nS%fXbE2AwQHR@cY;0VMtZCa)Iv`EBF~R*E6QL zvM)|-x@;Yh#HYSt zs-)utk{Bm8`C*A+>_D|9Rj_n^sfeP33l+M)>H(vv*WE*#=QxqIreAIafHQ9b&X~;Xc|IIJ1 zc9Og!i)(66yBwVqAxwVtCBY@?6|e)6D_Y0_3vSx7p}3K zgGgjRRnQB00V88m@|SCC)HRF?AS(R4FaFgJSAU6Ea8Ts<5bp8g1t5dFZa-TKksM}K zx|~u;I3nJP1)ZBSD6(hmLzhHk+sV#jO8b-=$$^GaV?G9u<;*+8p`PE>tAsN>g?jH2 ze*d#$j#Tq#z3nKB^rf}&dSZYxEV?T1O|=ty*ukyXj{^CtMj6lbHl5$9>vc5GVOnED z-`pr$Jjd97szbkvTpn8&Gam#Lzuu;WVglh z<`0>A$zjX6(`3JA?j&Hj1RXRtzO;N43s@|eSw}T70>i(mc!fVT{`03V5aKd;VV2j;5b<=NZxSp&{9lz`XGV+C|vcZcsM!pj4}eL09D-^cr#r9CE59? zKAcOHOas6fP?AW&857yXXZ1i=S*R-``-k*PAJCwcdH%k4NhBB6*?EtK-Fj5%ZIb%3 za_F#Sev?wV5>T3>Hhb_lY{6Uf(&9Tt-&L5zS);$@uVaz8;*aO#&IZsbn&quk@v$fT zkofZ`dVXwQmDCe7HvBiwT;Mlp#iuN`&kGmWP5ksL2dksB6Qg!ZIEBLG`y=TnEqUqd z?&Y+thMZ}xIuLmxN$SBngZJ&S-chz*`OI?4uZ=?>H9>J zySNS-^q;GQ`+rRB*Jg}+S-qSN@Xv>lxRS1#Qd!5hOzGpkk(Q`fO6nD4Ay&9neozRI zf9^D|LFJTMGNB1S*_kIlrQ{uTG_e2L=Wa>>#8<1UXvYW&0p_WVPN+0a>k6R-NHKLGLalT zDK0+J8BGp-6$i}C&=)}BYG%3K-Wq3V7HIf$Yi>=MY!go=Gf)kIX=pT8zL+e5)~VPs zzitS--N^QSUy<{Nn%Zz+aUC2jT)RF<$B3pG-?|}v4a#ux?!gZ_NLRnaB_6IRmfGt% z);AhLyCyclk#(zs>uZ0i_N!~h( zC2oZ$&u#ejaW_qcubDxu1t#=I`JXC*@bjwn@{J3X4AFAsS!D!HGO<-M{@6d^a(3SN z{5yw4??0|Sj)5fs?C>@^3yxfyq4?g7vn0v_ZJE<4s;CU7NHR zzDQE@<=FqDi47?KE(3>LAiC9cW;it9kGo`eVZx^CM&n7%+M!C>NvpyKidEa~|-VUevtETnJ(4*yll2Fq;lLqmu zDp-KoW^Lv8t^jjU=aaTQvCcn#ww4vM*&r`)e%rdyZL-bE&naT2JsVMMAny^nm2Qzq z4{-&4Kb(2|k-0}wwChWM=3Fs!k0^DW*7*#6z)JQeQw`D^c# z*~I++YN$WY9QfbLn2pxqN-tF-&pnIC?^fZ43`YzUwoVQhN@_DQ`;t9#>GS-^kJvT2 zbCi@k?AtDkF?k$Ashz?Kmjr~(HC_A}{p{${UIbBfC*oPK%Aes}{`kbZACM5zt!9@m2e+WH9|7YlALD)hPyOONTvt{Aw@3Wo?;VPtis+X2@p|@o$cvm_i z3+3HFi9<$tKa$;(fc(xl?2XTHdMVt4V&*&Rq}oC0!=m1r2mx;q=J+I>1HbmSLiU;6 z8o86>;6rV$29>ti%NgTDyW;>3zlyuD^zSX+)olcsrvU;!4D3$M&dFLadac%liGAY* z)@PRBUDN7U2?-L2)7cI#k7Dgqj|Kb0xKmh3yQAsleYvkxo0Wod(~#w{Kux60uXIhS z7x&025O0H%_m|=EZ}GfjDq)cEp;Z6XpXC_B)wgX@Lk$qfqqG@*PX-8Q(X%~X?vxh_ zukUD}bt#z8ALnf!lz%fu0k$9c7`xgT9|*BSxJZLEzadt4i1_IRVySOIROS)p1 zv0VimNit8(?PG#UQdx~xOI)hy)u5TFE8QD_#gi)%#_HpMk^47=Im{z;YWv;Yp;?O( zJ`g8bMcII=BP4L?`jb0OVzr#X+)U`H$_}2aMS*-sC0rdJ%(%`+DSss6Z$Q7y=bY?dnUcYh3OdXoSK%wdR_@KY|d zV3Ks;yKH3qy;UTqZR)2e;Ql0)L!b_rQQVpt6MRm{K+Sg|wCPAHQ2C^*-)vzhgzK?x zq5|}{_25Ma8#Kgeju-iHc{4EHH=cZChnr*C%r`PF2G^n3neXHItta)zm&5sU5E_o_ zMi!#8;rBeb$ekk9H3E>{e+jRe{!wkEW;fcX8m2`0eex2fKcbeYe6s>a2V9Zk7EYgv z*<@b2$G@-yE27%|?#Q;kLHSfArTlYKoo3KBKnQr}tJ4+wEqAcuCw%v&#UuSK^4m=( z$3Ch$aV>(#qC~&UO`~gQ1mrGHX}uRTZr$Pax=lY0cTCuO&O#Mp_2qB3*t*OKaavgu z@Y~dM4Kw|Me(?00hATO9FsCF^tpWJy*Kd}|0z%oPH6~GrVc~l3wl2z^{p{UJeiY4F z!dc?4KXr{3iw#ngLk{AY%Q=&KAhzCXAKEROWI*=hHE-8Ej;Li&tqt^PNn{FI>|9B_ z^AmHj-SI-{+u3wbxn!>in0I3JT}`qKW~^PGdZ@eO`085qyYpX<1fPIZMqTAwrVhwV zo;c=tzgJ{5HBx%-L)683;J+1hi4`h!W=0>^?&ET=HhkN}_E;hnB%sKQjl|Jr1GKec zDo=##PJr^tJWmyyCwHx$TA<{GX!&w|X~e!qMmztLUV#sq9{)hO`ap)kUaKz+rzCl^ zKei949_+{Th4&wm59C=N1&{w%#2Yg1k%z>It4he`ui-Cxb$R_Vy>q}6zVvNTpv6^e z2TWBTLK$w}vZq%57!)u%Q%`pnq}m=OCU-PB-x$|F^F8?-YhrzIjK#D_y@N9ThAx~% zTp@XNXW`&5y%*R@IO+sYVh-l>%xdAI&r4Px$Q@;P8I-gp^J2tG&h}Nmj%y#HIC&C+ zJwvOa2>bju9c~8qQ5Y3?%cH!EtWW?~i1~GB6CP$Bkto$$PmNFI*@0?TQxW6=zx%>axBp;CX9Hy*#?=3gj@z z7QqVc4<9B+38sTb4+m=VW%K(8k@j@jH=LVk#AyG8QeFf>alGxbg!i8(LxJK zHcb^3``d_t2>mF;dtDe^AB%`EjB*x*9^JsV8Cp?xL;du1z>g>L1G5=b;#G+G-~&U+ z^zV=0i7bi_4jqmoD2qo#o7b;?JOQ978R}m{&dE8d{9YGlgI+bZeT0|fy#4s& zWElTL-?^mlkgJale&h~DD*dLiL544uezDqgc!GJxwT|=^b$7QO8ORuH&e!Q}So-Il z+c&MwjD1@7eXY28*#BMeHu*ssuwa=l$R`5R5_y`F8WoneILY~Lv|9)GzE%EHGo^#= z_A2tZKLWN?k$9Xnx;l*2jicP7c#OEFM*}YNOy+LUG_Y5&^4EOh@16_YVJ>HT17aucTl+nia-?2n1 zLrrmM-S!OS5Qud|H>u}*r|Au$FQi)xfy;66WaIe@&m|%V=PE)OU$?nwQqASPqPC3EL9X;tXGhuq(O+ij*owRUQjppG=A zX$sa=6T*&Tiua>ZR?f8rOn=I{0d3tC2pE|BVY0IUxk$PMHEp7$B?)*C8m}CkqoT5+ z&w+>2r|{+;^9=AD1hLapPvYYSkf6ejM7qjb8hPLrZ;MiuA|h<4>9#q1cu@NL<=TRh za+?`_dDD2!s%KiTd{(`^pS^d{85szTJlpKaFGoa+MGka4IRL|c4?4VtDGK;wf$DuY zIl|55C*-^2`Qa)@l$DhBiTFVf zhO!%mEsxw|M6T(kM4*ROt;|>7IezkijNXwBlubN#ZaiAxJl;>RILcAQ8S?QEs(+@B za4TZp3VlUD9_m&&d64uzhlPb?O{@1|lHZhC!16_Wj7NSMK|d4YzNv4y5ZaV@@Z0v8 zvE@QMQ;t&5ue}n%r3qwvyzM@w8+(`MufT(w6Z9X3?C3|smAeNDCXNMSSi6!dE-YO{ ze7wBN5ON`wqD>Keag&Gw>VpHjuM|LPx;~wF%$GvyoGM_3>C*StaA8w&yn=Ye&tX3| z^A-huDV!hp!fJ|epd0Db3i7cmy+TV}acdBuVb@4Wvh;JLjJE&LN?!4v;jKb99BAzb zoVVIHfaQBrjBP|qp*b`*-Zb$s`Q8c-3)|}Z<3DjH)l2yMK$dk*>YF0N5C7p6S>LOP zU5WyV>ZMQ4v}O1yb@>bGPs%i2fB#$6ubODIY^WW&TO`QpdjOI@-#1qixX^#dgEu+u zD!IS^`9t2SCecVJ3p+95l_(%~^aRs((oYQa8E}4eF9JMv6`4^lANWH*sj{N!uM!252p6vyByLn?*(tdf_ZrXK{JdU5Mh?OG`nCmUa3zYL zCVYC_eW}FQd)0odm@n|0{!S1lxk_~@d?Pmk|GoIP^B#~DK`PjiwWx4Sd z_g0*Rh_GA?6OtdQxd{uJEyK8yj-5?%Y}Hd2vz1Rok3=IK^kupMy89Mc-VWrND(9eT z`Mqk{p!H*M*v~9jvDBmLbhlh3Pu?HN>DTUiuWw>>v6@)A{pUk8P}8hVr~QU8F10OB zyES(gRG>n+I&Z|4ohL^&dkEV4XIVDT%Fn40Kau8;Em5oJCX<@II~sF3cX9Fw=|VaYzXA__jy#`u(uC72dO9lW3QvLz(u{cKhyj(S*5XcoA<=@@sNwm(0(jF>c;QZcc(&pj3J2Ns%y=7-S8ToS)GjT_I$7Ca))y@S`u3b~I z=HI|8JofyFW)HoF6Kn4XCS_NEQHEu|Il1ecCg|TCkA>3#86cgelMOa7pMT|=0uQpY zRDeITJhlHHJdueq{}3~zvzT!~u~rZVjF<`$JqGQVp6NTZ);9TWsj9#Gy1NR~$DO5Z zT~tpzw&&Bv(!X%A1u1;>^wg6G+)KI#LGhJ`pJ!_{sRpb`-KzK#{{Q?8UzXYh=bHPsOJ#II|9nwtG22B zafC%bQxmGd?e!jpmuK}whG+7fho$?U&n+@kBKfB0W z=6oS`l1MyCjwc7Nd>P4$!1J?I1cMoHE^~zlv`AXA1X3q`kw#RaEqvX~TknPY2j-o= zyxz%$FF~T96`MTWE_}zu(L<@++Ax&80OO7prE0YZu`KuIK?{&JT2`*AT7<^ncp^@Z zEHz>WN$~{)Q)~ksjYt5OpF4q>tHo0NC~$S@RwXNLxsjQf&0AV{E8W>K!@jR@psnA(4n?Gy2yes5;17Vyq`uJr={6b4LMMVy^ zx`}^sU_Y5~JftS0q7ID*+l9NvDpe}V=+79pj)rP*;cT1ZdhWvAKTplGB@ts< zH-9BY+K-FQc!p}5{ROAh&8NNpm&Mfb_8SHpT}s3F7UtiPwl{nZ)bYCpWp*x!L@c!J zPTbzj0g#h%E{f)tK)KqA=md&50E7w>9^V1PyPTfms0R<2cOmr(9HYTMEC2>N#@cT*9V7o2)Ptx* From a038d693c788c7aac7261caabf4c03500cb03671 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 22:51:38 -0500 Subject: [PATCH 094/174] debug output tweak --- src/cgalutils.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cgalutils.cc b/src/cgalutils.cc index eee21c89..f8010f6a 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -1051,14 +1051,15 @@ namespace CGALUtils { uniqueVertices.copy(std::back_inserter(polyhole.vertices)); #if 0 // For debugging - std::cout << "---\n"; + std::cerr << "---\n"; + std::cerr.precision(20); BOOST_FOREACH(const IndexedFace &poly, polyhole.faces) { BOOST_FOREACH(int i, poly) { - std::cout << polyhole.vertices[i][0] << "," << polyhole.vertices[i][1] << "," << polyhole.vertices[i][2] << "\n"; + std::cerr << polyhole.vertices[i][0] << "," << polyhole.vertices[i][1] << "," << polyhole.vertices[i][2] << "\n"; } - std::cout << "\n"; + std::cerr << "\n"; } - std::cout << "-\n"; + std::cerr << "-\n"; #endif /* at this stage, we have a sequence of polygons. the first From 7283d06294df46e0b2038c4da62dbbb3a676a181 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 22:51:50 -0500 Subject: [PATCH 095/174] cosmetics --- src/value.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value.cc b/src/value.cc index f519948c..cd467863 100644 --- a/src/value.cc +++ b/src/value.cc @@ -46,7 +46,7 @@ ValuePtr ValuePtr::undefined; std::ostream &operator<<(std::ostream &stream, const Filename &filename) { - fs::path fnpath = fs::path( (std::string)filename ); + fs::path fnpath = fs::path(filename); fs::path fpath = boostfs_uncomplete(fnpath, fs::current_path()); stream << QuotedString(boosty::stringy( fpath )); return stream; From 29d9d4e6147461d7516215fe292d0975fb48ea1d Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Thu, 15 Jan 2015 23:16:11 -0500 Subject: [PATCH 096/174] Revert "cosmetics" - this is apparently needed when using boost-1.46 This reverts commit 7283d06294df46e0b2038c4da62dbbb3a676a181. --- src/value.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/value.cc b/src/value.cc index cd467863..f519948c 100644 --- a/src/value.cc +++ b/src/value.cc @@ -46,7 +46,7 @@ ValuePtr ValuePtr::undefined; std::ostream &operator<<(std::ostream &stream, const Filename &filename) { - fs::path fnpath = fs::path(filename); + fs::path fnpath = fs::path( (std::string)filename ); fs::path fpath = boostfs_uncomplete(fnpath, fs::current_path()); stream << QuotedString(boosty::stringy( fpath )); return stream; From f8a9af0e545c7b2d851348a704c8db50f4434c0d Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 16 Jan 2015 12:03:30 -0500 Subject: [PATCH 097/174] Removed unnecessary console output --- src/mainwin.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mainwin.cc b/src/mainwin.cc index 6c7b0039..fb2e4d15 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -2030,7 +2030,6 @@ void MainWindow::actionExport(export_type_e, QString, QString) QString filename = this->fileName.isEmpty() ? QString(_("Untitled")) + suffix : QFileInfo(this->fileName).baseName() + suffix; QString export_filename = QFileDialog::getSaveFileName(this, title, filename, filter); if (export_filename.isEmpty()) { - PRINTB("No filename specified. %s export aborted.", type_name); clearCurrentOutput(); return; } From e479ffba90263d453f4a8977ce7ad2b3481a9903 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 16 Jan 2015 12:45:35 -0500 Subject: [PATCH 098/174] Use new tessellator for PolySet tessellation --- src/GeometryUtils.cc | 34 ++++++++++++++++++++++++++++++++++ src/GeometryUtils.h | 2 ++ src/polyset-utils.cc | 40 +++++++++++++++------------------------- 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index 4bcdedd7..ba312de3 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -1,6 +1,8 @@ #include "GeometryUtils.h" #include "tesselator.h" #include "printutils.h" +#include "Reindexer.h" +#include "grid.h" #include static void *stdAlloc(void* userData, unsigned int size) { @@ -171,3 +173,35 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, return false; } + +/*! + Tessellates a single contour. Non-indexed version. +*/ +bool GeometryUtils::tessellatePolygon(const Polygon &polygon, Polygons &triangles, + const Vector3f *normal) +{ + bool err = false; + Reindexer uniqueVertices; + IndexedPolygons indexedpolygons; + indexedpolygons.faces.push_back(IndexedFace()); + IndexedFace &currface = indexedpolygons.faces.back(); + BOOST_FOREACH (const Vector3d &v, polygon) { + int idx = uniqueVertices.lookup(v.cast()); + if (currface.empty() || idx != currface.back()) currface.push_back(idx); + } + if (currface.front() == currface.back()) currface.pop_back(); + if (currface.size() >= 3) { // Cull empty triangles + uniqueVertices.copy(std::back_inserter(indexedpolygons.vertices)); + std::vector indexedtriangles; + err = tessellatePolygonWithHoles(indexedpolygons, indexedtriangles, normal); + Vector3f *verts = &indexedpolygons.vertices.front(); + BOOST_FOREACH(const IndexedTriangle &t, indexedtriangles) { + triangles.push_back(Polygon()); + Polygon &p = triangles.back(); + p.push_back(verts[t[0]].cast()); + p.push_back(verts[t[1]].cast()); + p.push_back(verts[t[2]].cast()); + } + } + return err; +} diff --git a/src/GeometryUtils.h b/src/GeometryUtils.h index 0d213c3e..4d3b3f19 100644 --- a/src/GeometryUtils.h +++ b/src/GeometryUtils.h @@ -20,6 +20,8 @@ struct IndexedTriangleMesh { }; namespace GeometryUtils { + bool tessellatePolygon(const Polygon &polygon, Polygons &triangles, + const Vector3f *normal = NULL); bool tessellatePolygonWithHoles(const IndexedPolygons &polygons, std::vector &triangles, const Vector3f *normal = NULL); } diff --git a/src/polyset-utils.cc b/src/polyset-utils.cc index b3bba6d7..03350d92 100644 --- a/src/polyset-utils.cc +++ b/src/polyset-utils.cc @@ -2,6 +2,7 @@ #include "polyset.h" #include "Polygon2d.h" #include "printutils.h" +#include "GeometryUtils.h" #ifdef ENABLE_CGAL #include "cgalutils.h" #endif @@ -47,41 +48,30 @@ namespace PolysetUtils { The tessellation will be robust wrt. degenerate and self-intersecting */ void tessellate_faces(const PolySet &inps, PolySet &outps) { -#ifdef ENABLE_CGAL int degeneratePolygons = 0; for (size_t i = 0; i < inps.polygons.size(); i++) { - const Polygon pgon = inps.polygons[i]; + const Polygon &pgon = inps.polygons[i]; if (pgon.size() < 3) { degeneratePolygons++; - continue; - } - std::vector triangles; - if (pgon.size() == 3) { - triangles.push_back(pgon); } else { - // Build a data structure that CGAL accepts - PolygonK cgalpoints; - BOOST_FOREACH(const Vector3d &v, pgon) { - cgalpoints.push_back(Vertex3K(v[0], v[1], v[2])); + Polygons triangles; + bool err = GeometryUtils::tessellatePolygon(pgon, triangles); + if (triangles.empty()) { + degeneratePolygons++; + } + else { + // ..and pass to the output polyhedron + BOOST_FOREACH(const Polygon &t, triangles) { + outps.append_poly(); + outps.append_vertex(t[0]); + outps.append_vertex(t[1]); + outps.append_vertex(t[2]); + } } - - bool err = CGALUtils::tessellatePolygon(cgalpoints, triangles); - } - - // ..and pass to the output polyhedron - for (size_t j=0;j 0) PRINT("WARNING: PolySet has degenerate polygons"); -#else - assert(false); -#endif } bool is_approximately_convex(const PolySet &ps) { From 65e50b2be63587fcd1d38ca9e7e6db313c6bb1e8 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 16 Jan 2015 13:35:01 -0500 Subject: [PATCH 099/174] #13 Added testcases --- testdata/scad/bugs/issue13.scad | 2 ++ testdata/scad/bugs/issue13b.scad | 2 ++ tests/CMakeLists.txt | 4 +++- .../regression/cgalpngtest/issue13-expected.png | Bin 0 -> 7847 bytes .../regression/cgalpngtest/issue13b-expected.png | Bin 0 -> 7165 bytes .../monotonepngtest/issue13-expected.png | Bin 0 -> 7847 bytes .../monotonepngtest/issue13b-expected.png | Bin 0 -> 7165 bytes .../regression/opencsgtest/issue13-expected.png | Bin 0 -> 8213 bytes .../regression/opencsgtest/issue13b-expected.png | Bin 0 -> 7268 bytes 9 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 testdata/scad/bugs/issue13.scad create mode 100644 testdata/scad/bugs/issue13b.scad create mode 100644 tests/regression/cgalpngtest/issue13-expected.png create mode 100644 tests/regression/cgalpngtest/issue13b-expected.png create mode 100644 tests/regression/monotonepngtest/issue13-expected.png create mode 100644 tests/regression/monotonepngtest/issue13b-expected.png create mode 100644 tests/regression/opencsgtest/issue13-expected.png create mode 100644 tests/regression/opencsgtest/issue13b-expected.png diff --git a/testdata/scad/bugs/issue13.scad b/testdata/scad/bugs/issue13.scad new file mode 100644 index 00000000..5956e67e --- /dev/null +++ b/testdata/scad/bugs/issue13.scad @@ -0,0 +1,2 @@ +cube(size = [10,10,5]); +translate([5, 5, 8.1-9+0.9]) cube(size = [5,10,10]); diff --git a/testdata/scad/bugs/issue13b.scad b/testdata/scad/bugs/issue13b.scad new file mode 100644 index 00000000..a604027c --- /dev/null +++ b/testdata/scad/bugs/issue13b.scad @@ -0,0 +1,2 @@ +rotate([90,0,180]) translate ([0, 0, 8]) cube(10, center=true); +rotate([90,0,270]) translate ([0, 0, 8]) cube(10, center=true); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2124dcd7..5d9bbbbf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1215,7 +1215,9 @@ set_test_config(Heavy cgalpngtest_rotate_extrude-tests # Bugs -list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad +list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13b.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue584.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue591.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue666.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue791.scad diff --git a/tests/regression/cgalpngtest/issue13-expected.png b/tests/regression/cgalpngtest/issue13-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..cb7fda7578819948dd06d462024f232609c2c8c1 GIT binary patch literal 7847 zcmeHMS6EZqww`N|NCGHL%0`hOO_8dgC@KL9MJXx>hLQ+&P@;lL(Ij961q2bKMp3B& zRFF=BY&R+v1OW?>hz$uP2oVU7+?jn|@54Fwe)r{m`zgtoV~#e*n*YB>u6VdP&X?1Y z0|3l-cG|oX02F>j0Z#f6rL~C#z>;Imo9#W%Aj7>IlJ%=9=e7MYkEKCkJih&-!P?@$ z?&c)jT^D2Oc05a6;r{U3Ra+9W=@?r-xb{Q#9{*`seKTsJ!h4g7-3T&B>SmlGXbj;*|&l zFod8OoW7b8aF!4K02h_OZvaKfaya_k3soU-5eK5^P~?oo5Zj;lu7-;k`UWB$Fz%u# z;qYhEOt^@0mJo<^;!Xrfsu0|Ch586ZQ5sPp9XOHBv>FoWFdW%`!uh8<|MbrP^Cycl ziNkGHpZb|dOLrY@Vb2EtzD&j|*%%7Oe*WY?@Qzet#GtKP*}>Gp^7z)Lm}BtraH}Tq z_LXrr`WKe>zDQjQZ<^P&oGJ>>)4iCOw@0`cIuuSdL@fw>(I=D>E8(j5{uc#V-zBw#F z)1C-67d+W=vTdM@aZ|3_CMsYLa?1oa*YqGns9+>hntli?@1>{Q*ie%w}${(d#SSubOZiA&RRJUu3T z$E7$eu+98>xfOouvM0{xM$j%5(9%;I>1Bsl1f{}UZP?;3xsq(d@ou)n_VtaIU+HxA zLNUll^V1i6$vtNmWpv#_re>(yw}m}4T>sV@mQm~A=+3Pab^I@;0>5EL*ld(>-UdUk zwfInx@Z~QGsm{r!9toRm4x4NA0298ptJr!L@t6o|%fPg*wq(!JQ9CTL@8dzAX%of! z1_u)`+IG!3+{&$pv{QQJUoPD{w7zYuj$4+hK>)@wi#9&yK*i^$wDIfC4GpUwJB1Sb zoVORSI3_CnKN$D9r=X*eMqF3;^kdh?Pv$X4efv7StrO1^w7FHB(!L0_zBhO#TBLhP zJzZP*eq~nzT%ipV8Tx1ajap{QEaK0PM=-x=lqB38Z9_$g)%TA|(2Vd&2 z@50{ zF&ujvb3F){qbSOpl*_P#pt=AeZY(umE3cfB|AxGP-6fA-xKIgTE$456Set{v5Zyah zdP6+^-%9NNh5cWxFdS#1xe*Mb42IGD;?^1%h8qkcg&yDreFnhiuq<^|DD;^H zBQZi6vS9QLP$6JNRcIf3=2Iiz-<3{8A?h=q-E@LmqF@W;#I;Cq9T(&9d=RpD5=Z4M>cTHrjlalyhCeU^u#~&7pUq1ZE-8B1zpZfVpi73E0dl zkakK!<2ycXp}G>dU_akcdTOwk=BX>)rJeHcNsTStX{J>CmLMg~twf-(%S9fRjk6I! z%HOnhN~8T>N>|EH@j3H~8>QFv%}p>w7A!>Z4L&TN#lJ4`|0`*5>sXaTDLx{HxCHiS ze%Edn=zR_B(fOCi(jIjrg0F>@snQ<3Mh9n_KWo6MeN~>?_+}@oLW3cNg6>^&WA1F) zTybtDZk8(%znN&Xn;TQ?ph>3EXx6u4*O;0~fh~B;hz7|LCY^3EcOTccsAxOm01qQ|& zn*c&({^af-u*Ap6au{7~lWRdu?fT#KP{INKBd?46!HvP0ZP^LQgacsV&zaWR?TNV9 zIurXP3xU1d@y}LfiuA~{v_f?|yaSfl0Ige%D4Xse*)0VmZ=Pt9tq)2=M5po1hW1II z`k~NV{;N;9)!|>4!J#L86RyGYh~tgy8`o}Pj><5Pa>=_7MsC*Z*Q&`gYmEK!3++hf=gbIm9d(;W^I;^F_IzjxulgwvGaGL6q$BvT924D(rn6)!)9-fY3?O+?fm>(Vr0Wm z9`gE-`_CEdibxau?|Jk_a{0avk0+Gx%fSIc-dxeo?$Uu${r5`%i6(qf<2dm-78EqR z`gpZ$lswvKfZr`cT=CA z{X5uT`n|773gr(#l30F{4@lKjz;LjO3SamR%y{|m6-3DxbA&nCeZ6$$AP1T(8cL6h z9h?z{T-#3ZqLf=qoeOU=!x>O#B*~2&wW4K)DfT=a$?WKv)-ZH{b^i^yzu}dy%EWHF z@nLt~J)uN6Dj5m=t$1(con!=L!yv1-VtHR1uWPZBzJ&&mruezWD4o( zl|-gn2hZJe`5aHVr*FPEe?p__wR^Ak^Vf^C_Qn&7yX?MJaSW+Obkn-m)+^8jm=(mF zjizly!rYuQ0|Qt$Bsj*fTSR4U22a z^uKV@lA*W&v$|<76i5UrwP$Yo68&!!esPXtB*b?I4w59P@Mv9z>qo=m8HeX!hP{~J z72Trl^Dpeo!HZ0-F$P@*US$>Thv!%>=797({~XyesdlzZy-dh{a!8P8hkXYcIKICH z`Si!;9cOP3?{4<{u!FB7Oa!h`&tb_W_TlwPvM~wqRkT6vO7UDge@IOV(DT>(TUt<$ zhi>Z-<)!+7&Bac?r+We^JE`PDcUeqfOUZq3d5^}UUmG6U|E728)Fh#V6X7pi6~gLe zE5uVzRl!*BzKh&IN(_};5Z}ubp5Af)a5BnFbGh}y9NoBVL8D@Yn1{`9bq6nrvmY6B z#kf2*XKv!|>(|DW!J^xK>N_|LW`tLT_`8A4Duj#KnAbf~8FcoKsrB~~WnV8E(b9G1 z>r4f6cGYBqQ^OG&EoxNqz{8LFhv(8FR!8e0ZAx5UZ)NCQj$amgWKI~8dDR4Dlt*<8 zqJd142VLZ@RnHEg1Sj3?d2#d^haYRZ2?ILop{`3cp zrdrbq^B6T#|L>#M56_Jrz4w5PUCsK4=QXrPtxqGqo^c@2O8pysSimRg455mcEES9# z6(1F%oYe%XBZa5gCK`Qb%in|&g1@n%VmXw_3l-w|)^EbEfM;Hz#TyLUW*9`i-R{ZH zoG z-9LKf2LaOLe`4ns$@(pcIE zWQ?}uel8R*o(P8L9p4`_30YCp$|XirKc2cw2fw&aqg|Bf{cHsdPO(;_j5suP0ft0- znz3Jt1ojm@u3W9MOcQ#~(@L0rj8b0KlDvqF6lrF3>*2F5e-m&T4UJNSn`qV}`~E_i zDGs;3Q&HbQB44L;=z+RE2<&VQd5Et+O?KkHd90dI(!GX}S*{Vei;FSC{Bbb-XX3RZ zbILESe-7rPjGtC6dBp&XO!`Quk>7H7xxf1z09h1Hp8!y`ph?ejlU2RuV<==A>*aCu zgLsKPq<1SJKPlne+y?o{K?D()e9nbioDAWhPOawz9MlO+2q4E`HU*Nx=aAq%jPZpm zHyCwp#ICl)(JLEx5zw9jB%||8OZF>6-swsNC6M?){a8pw?d5~_K!ZN2N+8%F2U30x z6LPS&CnR;qC%a%hGm?HlFBS#xow}m@ru2=&8uCBGg|iWotphyl%7#A7uW0#@qN`xw zXjFzd+$9HDs6*04DZ>th+_Wn0*8fa8|I(Nj{o+(#qzS{5jHbIx&iQ<6twQ@$X)gIT@hu%oZ$+Oqt&e|Ct|BU*}KVX()iFHAhj6xP0*n-xsp6i+c(!n8y2l~9u<9m$7;fQqo!tU{aTIunb49tRnFFex8^6c zG#j2ccjXI5jVn|+W~FbZUk)Rsh@t(EkN)*(Y`i{@Zu-mX~xRa7Ak+8>VEd|xdp zj<&Ffyx>U69idfcxPePQRqCm62wB6)61p(`X>Vc=TiM)G!x*QWDSOx~&J$q$IJ#a}QUN~@YY5>R~H;!{v*tlb7# zXyj_aRGg=>aP3ExaEX@MakSueM$q&906q&0e)z8WK~`q%V9$}%TAEh` z;*q+hg*SrxRxmCsem57KS%>xXwRtr)g1fg|h?VaYnG}KdeUk6Ff3@cKa5L zkl&nI{ZN&o@Ml>*b}`mX^}aTd&#s|p&_wmLA^svj>klVEq%c`YiC(vb24kcM5ItnFtgXjQ$Xh4_| z{ky?4D~7MaKGK8AMkD47+vw!CFK)p5NK~1k&SGr)D9W;XtxiQR?~32PYOINP{|Gyv zctk?Vn||X4UTsS{gSyGwiYpV!mONG^a_;D7CQHlXH<`HSYofb5Iq3Dvl6L%8@n6!H zxQiv#5YkHA!1dykkYlg`N_n+3L9$4JaE9^AH8hUVk!XBttYlXy=vS?$rxKsR5S^n5|@uNo@&&E1uytH?)&?8!$Dd_@?@hLCfdRS z3D;^rn!B!a*fAVEM3z~#%*5g;oyOR#yNktE+Sj%>3&g1ZRpExWk<03z`5oBHJ|8$> znFSouTE4pBrzpH-xm`5R(nsBEk+9ts9lfU1ct)>z>kQg!=RTYbe!W{a=Aw;#tVZT@ zzgxZbasyx9wY%(wjs;3ileA~6zNfhT{d(W02Cslz<;dbZAzSD)k*P|&6X-j*261F~ z``S;^E?gghhY@B_#S2A$+CglZ3vI%4mOL{}5?V25e)LUpcaLHyi zDGwuX_WSQj`_oo#Kx{CWaZDi>xx1nUtD$;%tcl)5E@4j3 zJApp)KDokdMcV{SI?eRJIU6P?+Mh;JBX89 z55=?+c^l;Ki+cg%g^t3ZIol(j+pQ5Jy0z{bRT~04G#T^gDV1J{Zlcj?s5)c_=d_ua zxFwL;yM8zOxSWS6SAF>na|(ZBiUKWe8R;KJ-2fa7JHyGyLYYhAt4XjAdibmHHb_X| z31x^RGl^)eWY5VmvMLqzQT??Zj-o$pghwZzyl9XCBa~U}u3Vre5Wrlz?bi%yBM4RY z=_X96Qg!yczQ&XhNmp}dIJO5Z;s=MJiI{+1<#v&deMD&jovp}BDBb}vR4IUC$`lx^ zw1tvgj+@lOQ06Ljc$I&Vy42LOmVe$V*kF3;_D_Xz47FG6i!2 zc#`%E1C4pW3B|kP*2WNTpFpzkkJ*2U@E>*pMj2+c@|!pxu$A}O7S(UG*sBx|-I zQOVNLBD)GPmO&xR%yWIt_xmqA&+|)u@qYQ-_qDw5>%Nv-l9Pj#n6RQSf*@ix)|So) zf(3|0@aV4#iu;NYM5)=v(%dxyGd-{;V@GSKfHz`pmoLLs%)GaqP|!^X=*nzlhA5n# zcr6pM`*gkx;j4uj%_Qgc?Y!Juj~~71Na(2C-aT;r$MGkgXY>t*DjU}3yN$S3R0M- z@QZyme8e&p2}CN<1%v4-n=7=3^%!q4Ndl36pNa(ZMs$O4D#8%JOA@+ViO7zS+CUis zk%%1T!{H?ZvMj5|oUB&lh zx)zHikVvkJ4~ZSqF?Q!Ho7QQxZjqHlMCQbz_t9sX4N41nS=T;sCL)jC87)2m zo4wn|u=6Z9c-^jx@7$VW+O`)z-v#>*?ny8i;uJ>m->c1CGtN!vn7xq%IoEuR~fV zMm@Jb8JN}hYkK!4RS&BhAJvc>mENJ4iq#ilhj-UnAAa2sL&h-b1smmh=HePf#55&@ zcLrrS^E35QBK3W1I{UJPuP4O|A5|6xvKRE~GXH~!Tm;f~G9=DxS`Q~?$?loqFL)(};h_`dq4 zaHwRQlJ^8zuG#-QPw)Bgj%Xu6-YMek%AlwetQ#O2MfaWBCT$ zpw#xEyLvGaYYw4J!^(AT<1^(Gt77a2;sPlwaRO4kCYg0k;NGj3aXHEZL9Ly;Ox)U` zJZ*QCh-q&#l@tid4(aw{c}1VWIMu}^vl>L>Tz;GP4mX=xetOa4s25Upa_Rdk&oP=o zPjX*jLskLnPa!;2M^gWsjHJM-?}-@AY*wlJK8n zja!?Tg_Ngn2j4(p-FC)Ytdf8763w0$ZdI54I}uS2N<2M-M>VAf8wrN5nM5yypQOz? zyWca$R^m#hx%U)#Kl8XFhwculr5|A`6DJq7X11i0yUji>vLv$B4__JRxdZH(xqboIBH zlEc`@YpbX5$6%k2JoT=yR-PsM=L zjloFXkIs2AwcK_ga=pMk->;4HS6sIc5!b2S*jv-fB3)kVomFb@jP^7L;Ssx$$5eZs zp8bl1-U74Td?j30#|hc;x1%vb+04gfP=8{ZsDt}8!P#pnW5U>BgW?T;B`Q-aiH$BCIpNO`?B8{1eUf)`)swbMv;TWtq^lvlDFw#_hkWYFGh+~urzx8Ej|F&Oq0&pTluD@nKB(q(v2FS?a$V5v1{JX$_$@mI&goPf)u4x3HYJH+q;SWW;cMAj z22E3_rq=ImF^nqZ@U<6W25ZikNJb`4iKomw!Xw2jKPNfLExZ4auWV$GV7Y2>)6Pbk4+t!^=6&nB|0M1I(1D?E9u{x&rZ~VhzrRMwYkX6#G2K+8jUjrdR1A} zXo~);mn=NhdU~KG16OnKS=R;ZB4=rBU7jwo&SabCUF`HKHXJUsOXT9{^ zGp=rYdp4^jF45tFmUlPhrOW(2j8kbyTJqimntFujXtyrN(6!y4CWY)*s=Oa;!$^8% zUWuDpt#rMzn2Q)6u_AR?N%tS08*|63a^0`-HK-xt{ryTV*KkHowWB4x>1P5_N&&GQ zyfseKrnOveRqlNLNA3bQkGuA96x%LB7VL_`tWC459fdRKoz91AW|u-c%v><(4OZrI zxq0HZTVw>xztNueeCK=8CaQtFF4HdULfNriTz~A-(upFKv0G>emy2uG}xS|NPCXVdTr$rDlv^c8bKh*G!y$suPvuBBPKZ0}zQd1)9A0vMCM!Do@9#j+q%#eWM0S=jd*9*VGC{2{Oz-_7e zSwH)bsKzb%5iEKR>5Pxs>opwZNLHNe@#%`{&TGg_Vc()65$$bnpYnJ3kPFlqvz?xX zkIgm{ke2?Ookxce8}FgKdRtL;E-dTp{ItOTT7wo%;odQ5+6x(Pqm{dmq;)QCkwe|- zofr)Xr9SuZI@NS-p{Z3VU89x_V0!C&w|%${8?vJAd{&DgCw)=z_%krxA(*N_3sZPw zhh2^NT_;r7Ega7P-}SQLKoAT4Y)uD;F9q3; zpjk97yu_Kjvfa?KkdGw0uTqH2;bx{&0VDHd+#bsp_X9nd$cj>jNfcg zKcEXubTULELmF6)w?8Nia1-c^FWrjjbb=rWzMO&TR3#vrGE>b#Q9S7Mamhp}$AixN zU^Ix;A#(_2-$5z2gtN!{9Ye{@2cCOmHBibeAfC09&>$9qfM_bzLMfL5Q5HW(w??Uc zYdh{>tqW%xR$+yFol1THIt`9ON2_TF>u{&RyqxHRasUhAx=b_+pfT^;?g0G=?< zz)ip1gP=tJMnFz4?so%tQ;&cY$|#}F7`s4eM}5&{fZdQL&iL}7_T8f*FF(nwR%Sz;P3L1NOzK;Ap0U6(xROv*wgsAi9bs2+kqmD1R<)%lz;}XavmDX zdO>aAiV3NK5kEi&OAqT4kPk~leiT9$xxrA%1XftU%8ClyU<}p{hhs{I$4LV#byVc= z5T6`yL(VKqo6)z6V)3rSb8B;n z_d?qJd>X2wM#gKg4gSo|q48oTKOEPK`N1ndwTe&c-IlaC+no>no`my`g#6n9+^eLx!8e(o_~LOA?bcC~fcF*LXQ@B%MW<%>`qJk`-+3No&UihGn?YB z?u|+D;olD4=j#{FJn3HS8^S4HDZhIJ!`OencdIY`NNdK&AeQ4GePrGgt5|49xua<@ z;o*9RSVKuNOqH7u_kL6S@{d#emv?BN_^X1O6aDFlHin_*|G_Sa_UN{aM^>>}NYJA0 z8#Q|L9vQE8nf&H<8@F2nW^N{h>%NG4Ym-WoYvimyqz8}otUNt?Jbcd#;x95@Q}02G z+Vjfk>VVlk`Pd+`prmN-G2=??u9frxVGl~if#xh#ik84XWxj5z6IF~oKP50CSKBe^tiE@IVp}yBe5g|98Gc%>%Lp;re>mXM@qY-;Z~uBSr5^m?vKl z35&J)!JLI)39?@rRlKYDFBi6DK;g_(P#@=nhDhw;XhS!D3>EAuc)M!fUCfNR zVdDAfLxY-so?SKHw{F(a6O)I$-8+o*{g)^*jOmFPq_=`Qom3+ik&VX`KlEo*QU77&p6b|k_E~4N5+kC{lc}h zN{*`sFI>lJFH}^=qz&xLRE3EBth>iTIQpTxB9f_AM40Ut?oc%?^ketz>7U_czQpih zXAps|oKkaUF;k#GH=$>xQfrq#%yuc&yMnT*3O!?I7PLHg_UlM9TEkLZS8nQ^wE_!F z3?v3CR?V1mZ#_Z4V#b-<3D{HoD)WEF1hCLX&lPg$^^Y&iL=tJ8D()r09Cw0e$2vAX zpn}1oNU<%yiM*N+tKsR&&9=*t1r0uad`}XolB*&=`Qhcgyww#(MX2+8g{tJ(65PCX z@$zp$%bgdgOE&bmVk(8rE0eB03}xg{kr!N;%i+QI`M5phAmg8HTwhCT01>?bsi&@c114^N_$VkAR&BcG> zY&85QAqm%yQ9pUfITv5hAjkM&HbGCj207@s*uf4LTIN=77NyrnP+gXd*MhoNW=`mq zQLW)!y0lCEZ>kA3<>>9TdBnqr=CE5ep9S=&khX<5z`BsjxTL2JnOq3)XCKpjv3)* zP<2BFXHU9eFiz!RlQDL~o4^~A&F<<_Ci+hVm(i8?4rr~2!^Q|2;Kz4BEpUah@ZO{- z2B0XEYjfj!P*>?tSBnPCf55xHH*^!CO}kQI*L$eOKg1v8{VM?LE!hzW#h?hP^@DRx z9DoY{nM2U_@+??T7dNR1C5#ReOMI9jREYmRw3z`EfVxG<>4tW}3EBnMS^5f;9Rn=_ zA~2GJwwIIe_;z0Ky(2(#i0@yfI{aew|2S6H^c(VzYhQSEFcN_uoBa-!k1f1o{|C2$ ByJ!Fa literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue13-expected.png b/tests/regression/monotonepngtest/issue13-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..cb7fda7578819948dd06d462024f232609c2c8c1 GIT binary patch literal 7847 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 ByJ!Fa literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue13-expected.png b/tests/regression/opencsgtest/issue13-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..9863a793d710626c524866b0157f9e800b73d119 GIT binary patch literal 8213 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 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue13b-expected.png b/tests/regression/opencsgtest/issue13b-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b02397d24201ccb8ebd91a9a1e5a2a29730a673e GIT binary patch literal 7268 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 Q@b4kC*UG`N+`>QcKkVl^5&!@I literal 0 HcmV?d00001 From 7a8574aee28a85ceb3ce79c203957cf7bb7856fa Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Fri, 16 Jan 2015 14:37:47 -0500 Subject: [PATCH 100/174] #1165 Added testcase --- cgal/data/degenerate-L.polygon | 4 ++++ cgal/data/degenerate-L2.polygon | 4 ++++ testdata/scad/bugs/issue1165.scad | 5 +++++ tests/CMakeLists.txt | 3 ++- .../cgalpngtest/issue1165-expected.png | Bin 0 -> 6914 bytes .../monotonepngtest/issue1165-expected.png | Bin 0 -> 6903 bytes .../opencsgtest/issue1165-expected.png | Bin 0 -> 7235 bytes 7 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 cgal/data/degenerate-L.polygon create mode 100644 cgal/data/degenerate-L2.polygon create mode 100644 testdata/scad/bugs/issue1165.scad create mode 100644 tests/regression/cgalpngtest/issue1165-expected.png create mode 100644 tests/regression/monotonepngtest/issue1165-expected.png create mode 100644 tests/regression/opencsgtest/issue1165-expected.png diff --git a/cgal/data/degenerate-L.polygon b/cgal/data/degenerate-L.polygon new file mode 100644 index 00000000..91cba326 --- /dev/null +++ b/cgal/data/degenerate-L.polygon @@ -0,0 +1,4 @@ +0,0,0 +0,1,0 +1,1,1 +0,1,0 diff --git a/cgal/data/degenerate-L2.polygon b/cgal/data/degenerate-L2.polygon new file mode 100644 index 00000000..e1b1aa42 --- /dev/null +++ b/cgal/data/degenerate-L2.polygon @@ -0,0 +1,4 @@ +0,1,0 +0,0,0 +0,1,0 +1,1,0 diff --git a/testdata/scad/bugs/issue1165.scad b/testdata/scad/bugs/issue1165.scad new file mode 100644 index 00000000..9338b16a --- /dev/null +++ b/testdata/scad/bugs/issue1165.scad @@ -0,0 +1,5 @@ +translate([0,10,0]) difference() { + cube(10, center=true); + translate([6,5.5,0]) cube(11, center=true); + translate([6,-5.500000000088,0]) cube(11, center=true); +} \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5d9bbbbf..744af9a9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1231,7 +1231,8 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1165.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad diff --git a/tests/regression/cgalpngtest/issue1165-expected.png b/tests/regression/cgalpngtest/issue1165-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..e3c21fb37701668eee5139ef4eef52a015584c1e GIT binary patch literal 6914 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 Oh|LDa^@Ucflm7w7@Hm42 literal 0 HcmV?d00001 diff --git a/tests/regression/monotonepngtest/issue1165-expected.png b/tests/regression/monotonepngtest/issue1165-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b8199f788356cbb43f610db22867c5deffff12e4 GIT binary patch literal 6903 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 literal 0 HcmV?d00001 diff --git a/tests/regression/opencsgtest/issue1165-expected.png b/tests/regression/opencsgtest/issue1165-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..608a9b807eb94e1f5cbc9b1980627bd043f5fc61 GIT binary patch literal 7235 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 literal 0 HcmV?d00001 From b217b083945ebb5d9b9c5107f6a9234c1cef2167 Mon Sep 17 00:00:00 2001 From: Tim Deagan Date: Sat, 17 Jan 2015 20:49:18 -0600 Subject: [PATCH 101/174] Cleanup of files to add export icons to all export types. --- images/AMF-white.png | Bin 0 -> 4254 bytes images/AMF.png | Bin 0 -> 629 bytes images/CSG-white.png | Bin 0 -> 4254 bytes images/CSG.png | Bin 0 -> 726 bytes images/DXF-white.png | Bin 0 -> 4254 bytes images/DXF.png | Bin 0 -> 620 bytes images/OFF-white.png | Bin 0 -> 4254 bytes images/OFF.png | Bin 0 -> 611 bytes images/PNG-white.png | Bin 0 -> 4254 bytes images/PNG.png | Bin 0 -> 665 bytes images/STL-white.png | Bin 0 -> 4254 bytes images/STL.png | Bin 0 -> 586 bytes images/SVG-white.png | Bin 0 -> 4254 bytes images/SVG.png | Bin 0 -> 723 bytes openscad.qrc | 14 ++++++++++++++ src/MainWindow.ui | 26 +++++++++++++++++++++++++- src/mainwin.cc | 8 +++++++- 17 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 images/AMF-white.png create mode 100644 images/AMF.png create mode 100644 images/CSG-white.png create mode 100644 images/CSG.png create mode 100644 images/DXF-white.png create mode 100644 images/DXF.png create mode 100644 images/OFF-white.png create mode 100644 images/OFF.png create mode 100644 images/PNG-white.png create mode 100644 images/PNG.png create mode 100644 images/STL-white.png create mode 100644 images/STL.png create mode 100644 images/SVG-white.png create mode 100644 images/SVG.png diff --git a/images/AMF-white.png b/images/AMF-white.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b199229e362436e3ae47622b7e72278f049952 GIT binary patch literal 4254 zcmeHKZAg<*6n@`#&bbY3U|(221_ed^+a^m0Qkl#l*#{8@8f!$*CxQJCe^f*f`X?d? z7ezuy{Yi*^NWn@9$`2Y6f>D7H6a_+B5$wC?Z1?8f>#oyTRIoFi_nh;bbMHOxdGEX3 zb?t2SmRqVUilUVJ8a=zA?S!&YT-!T4zeAMOw7WYS^(MPh$jYgv@l}eR{!{JqazyF6UuS6D* z@eYUM5*9z0OeVj=_R8|c$H#A|sv59bt;><~UY4iH0=f9n(a{TLv-t$Y5{X1SSB}6X z1zTz^xPXz7kq#{0$!9Vc4D>22Sr$~l@bK_4i^XzLT#X)q=of0|EnsM9s1?ugvVMVB zEY_#z3i0RNgx%fUWoY|N-0fQ|ctl)4)AH6Xrc3R43&1E1JGq1wcRHOR=`2eK{GQt= z7EtWK|J;Ek)LtC=hdO{m#6y6~XBb&uR`92Ikm-j!(1>OMf0Fp3pCT(RlDKm@eAL&5Filzr!&JSFra(oTV Jp8k6Oxu5P&X>b4l literal 0 HcmV?d00001 diff --git a/images/AMF.png b/images/AMF.png new file mode 100644 index 0000000000000000000000000000000000000000..a140bad0e63a451d5278bfddc4c819a991539c25 GIT binary patch literal 629 zcmV-*0*d{KP)=d;SK~XqRPB+VvOV(yq-YvWNkes<91H-)e@4UDFeKT)&7DgiwY-C=?2+Uav1Yj+2ka<4?olTCG+(5{bl9snqUr zx!epTIw%3tG;cYMb5<#}+GsQ;!{U<3;_XD!Rx349KVQ-j<*olf7dZTliXG#Xv& z5#H%%&Atg_GMRbXwy$`8yWRdhj3VrdKsK8_-)uG))=gAu^}i6v<#N-OW!?7UhG8rX zgFx3JER{-IDwWDzrPN2mFy_`JxYJ?72>{A<-I!q*bEauN*@zdBV#G2gFeWf^0%O^f z@)&SMzX#OGigw)v_6dH-hd&d1)`#o*&cFCxU_$eE0h2ul9}zn-j8kwLhypEnQV$D~ zA7YRB?9VRudnANCoe3fU@CtY+Syr*B*efqWBTmq&v zKOay7SGDmev320y05y=&cOdWE-nOW>NRT`id)?=U$ybT-^w-}8M{*a&bPd=aumk6O zaZ^2ZU@@!+PXODyFpmN=0l40z^vZwNQ*cJZ4$BWq1URVS(*g6}1K(u)1{k+_ET&Vx}vy2!B{ejUg3%heqO$e)K^ph4eve zkrk9B5s~yGC`>aV=U^a75eY{9DUb}yXdiApuin>=<6bolr0^Zj-se2$Ip@6hoO`!h zy}76$)tF_JBq`Nd=-7g6AtWc^yS%FEJ5rK+LxDqz(dS0for_QmhYGirOOh#_ppmXz zodr=};oO+7@79>pwHX!8j+>HXUgUJFDK0T+EavWBIHoo<6ItHl@o4RKd%a$-FHsvG zi9~vW!QlS9yu1cA59xngfY}yg<#@+1XjA(P-QzlPLq94{AQGT8EPE_xn#742A>LH!v^|QSt~{ zRN$&~+y%6^w^w5EDxOKF)6t_a=@?f5KA&%&(P%s^u0}^7wkOKRETFBetrX{YK7N64 zI9wmEO{6{QO;}S?lZf% zGNucd-hqF42PRSbe==0@eE|RCtK{qJ!4J`ErE7&}E_93B_ZGg-D!ydsONG9d@P>u< z5XFRA;0*8+5Tgr?Wjp}f0{BFO%pW4B2)-1wJqo@Mw3F-`&JZstm|5xrnL}n|rN!BI zfhUCUj762agS>-3#V}aFcawmi*QXWOCOV!95)e9I9engw%-iXg_4&w8fEK_EP?5z* ze2iV-Ir4l5!M_46KpHR<7~lptysT4(xFD`gN5b&}hzhRIXau}FUhLP^};lNe~0JmYK#a>NRQwffTI!Q81SA2~MO8TS LiyZgYx{m(>I|bov literal 0 HcmV?d00001 diff --git a/images/CSG.png b/images/CSG.png new file mode 100644 index 0000000000000000000000000000000000000000..1cad44400f4d4c8dd80ca4a2706d6ccbe906af47 GIT binary patch literal 726 zcmV;{0xA88P) zO-NKx6vuyaoi`dutH4c#5|LrF80Mo|)F$X-)22m)l$eZQDMSoKiwG*JMMzQ6EG&!+ zi55kRP%<%yaFlTo6yYqQHU&e5^=5pH<7;yVj*s`oF*IAuh0Dx2^E>zc-?``9d9cF6 z_cuZ9?d@u8Y^=|+tixW6-|x>VxEz4?CN=;8pOzidInwpw=Y};-%O>-^q*^5()**p{qUC!ll zT>w>8RkI7=bLFgAwt#Rrd^VTMoh#afLgCj^6k%BcB9X|+Y&LskUZ7Ib|3pAE8f`XB z^M=!J7)IYx2q;;E@p!yuU|`_BQYvj2M#sDZo||LY1pvynZNFg{9jR1mXgMw-#R`v# zfQo<>7f=~q?*qH^X9jrh!E6BP_4kj!HxI4`hzR>FkoT&GtH2Cki`QL~#s@_-()iVc*uwCf(j6G6S*&KZu}bzuh%b%J>$&6R$ZZPE%QPg*PRlrbxN$)EH-n_DIn%{6V?GOz&>sN z1fBx-9NZCLKd?^QlfXmZwS#Na9TwL14`2v*1bnaj5&akA57C$WOtNs5FaQ7m07*qo IM6N<$f|MLjssI20 literal 0 HcmV?d00001 diff --git a/images/DXF-white.png b/images/DXF-white.png new file mode 100644 index 0000000000000000000000000000000000000000..0afe5f2f35f5108c2335e349a0d4998a89b08dab GIT binary patch literal 4254 zcmeHKUr3Wt6#u?&?mvQHF$oGGivGOFHW^VweygZd_&+Wn6bflhr!$1)fp|RrTozof*E=(rjA3G8!WIYwe#-nRWD_#p zZns}U@)PNF`WtMI%r6>^-cwbz*=n_}fzLacpC+3q#E*}UUoxA`XJ{^!N+k>V2wYmQ zrRK5=7#kZqhveNnl1`_ipTde|Sp`HQk<%87<+7NKUV%6+)h=4V=;-J%yvM%$1c^jq zD4#23yyPJa27@NFeE_?iM#58K0!=GgyXY>pmn;CQG@RrLO73tt!qO-!m{^@{lnW?# z;D7GG3TiJeUF8no@=ya5l8+$!0J zKWGzC9LGO-$tBUjMWHT^ijqY_{vd(~3U1<S%M1K^ZNAS0Lf(Xif!8y?fYi4`Fjve*b_i1l{#Oq*Ke;HsMO+r0Z6CQCoRjG^6G|R6bAvY zW)tS~`Dm$Bno~+G7=|&vYJpoVHXHy@uIq*j!x%SB^W{eTh!jJP5x@vw=m4YGRIw9q zJLFej3fQWB2Z0s+>?g2Y>&L~Ic_0cr@~PN^SsawXy3X4z5$1T zQ@}5wAJyI{@KI~az&+u)FKSAF8@gsYcdrHTS?E`VF3$vqJABm_V4DxX6X2T8iEce0 z0Wv~==o$0e1CaGR_gjK`KZjDo=bX16IO6f11LlB6hdLkh(gHaB%s^4-mj%>Yp}!Z` zlRh($>1P}M0bY9wTfmt1P73{*)|W(6?)z5&Z(6_!G4;zr-=+0S!v98Z&8`5l2bO^A z9Xt!b3*fuH-wWK-*EO+RGr$(nGkbuidbgA)%GrD~(!yLESmt~OMSP9oyZ4s|i*!{M;za=H2}7E6b0ekPOo zkW40zy4~)3vKX>2xPeF{qB)(;2#N<%snio$a`Hk-|qiea`K<5D{B z2BOjEDHIQhOeT|wz6who^J-vdXy}O5YVG3H=oWB&v3$-31_uZC;yzv}E|5;A`-*Lg z(Puq`Jv}`Y*!Ejk?Fb4U<^?ou&fa;rl+W4#W@$LdWmMeZa12PZEWxon%UEe(We5J{ z9auu||H)M8`v88+H)DMIv9yIu}i9!RE5lzI=#0JoP zKr2AsiX_kv^ujOB$prMX0F95+V#YNFi->tO!@FYmTXvxB^2NHYmZojgkH5Lyd*2f{ F{}Z;^sks0E literal 0 HcmV?d00001 diff --git a/images/OFF.png b/images/OFF.png new file mode 100644 index 0000000000000000000000000000000000000000..c26dbf74ed35e2eb8b52b1cebab6c615c193d6c5 GIT binary patch literal 611 zcmV-p0-XJcP) z&ubGw6vscAWRiLm3jRVb9^)y^4-gUYp#Opg5h;>rQEvee6g-G{Djs`~60y*8FA}jL zA|8^k0Z(ehL#4GyQK{}OYksVk2~3CGG?h)`ArBtRoB7V$&+fdL9T>62{$*0BR1)=i zeZlj*3t^f>BC(lDrEb(}wZ%vQip8R6G#YcB=Uq-FlP|+`tyU`=i^Yn4C>ycHp_c@=YjnidCLK-YnfTKp@h2F__~*3kMVRD#~v zF{1{;Dq63Bxj~NN7aHXhungQ)pYxFFf8Otk9fh3$Hbb_~ih6sZ`~q56JBUUp39j_{Z~K+F!-3(~wu5vXuY;002ovPDHLkV1hPe5XJxi literal 0 HcmV?d00001 diff --git a/images/PNG-white.png b/images/PNG-white.png new file mode 100644 index 0000000000000000000000000000000000000000..6f94e3f8793bc08c760e778ab312b0126d5c0eba GIT binary patch literal 4254 zcmeHKUr19?7{B+MSIAHm=hn0%9!Yoq<@4#!H|#$3qb=jC=wzPAtHiJ zii)x#(3hSq2qNc52#ll*#TQG9D6-m|TfgsmPCL_c{4po#I>ol^($CrU3H~bOVICT@4YL~*c+=3HffqOhoEbn*VaR6 zYxeD`u#M=h9K)I)`MgKdT$_B}^8K}Ty}&i{2_Ao!^mNJx0s*76w6x1+v(>8NW3kwW zNF;K+tgP(5%7^sJZXg&88Xk`)h~oZeH2O%D+-kLY5{X3Sz`#JR-|zpX^2<;eRC>4D zeF?>n#N+WVkSkSwgM)+DbzQG>I-P6bGp6!0R0f$o91fqi+wCXFHZwC5llcg`xF9RV zB{$ID-`|4btvr*(Vxd=I#k8abLZMKD!{N9fR-;ECuG5tlZJ@8O?+~8j<+%l>r>DE- z>e5*+xCz_a+p{qC8@StH6g(ytFpNce7u}Wef(;|y~->rF#Mj|SZ!c+ z0{`*^R?z!@61wd3Ksxu0b3rcRHnQ07__&2r^1z`OkkJ&B0U(P4z;6pqEj$TywSxYn zpf7~}v0&rk1cZIuj}ogI-~k=vjD^@h6zk1QKd%AUa)Eb%ihjUQB>NP!tbuI!?f~)t zqL097Q%b!Y#c~p$N6?sRGFMYfmw`fdiQQDm8W@M=EJHnb5$<5f^iI7@VA;S_vVHJ^ z*(~7IOg;=w`|H+`wH*9CPz9_3k_6+t zO_;PMCHRS(u$U~+tpn)2<|KXxI=NE9UqiQrPk=h3u@liFP*FDweDhI^hAB)U5lvwm ztwB#`nQ5zstp{uRdt1o#qu_MByNlQ*{dZt-tL)EAK!26f5xV+hD`odp)OdS#`rCd2 DBJ46g literal 0 HcmV?d00001 diff --git a/images/PNG.png b/images/PNG.png new file mode 100644 index 0000000000000000000000000000000000000000..75a64adba8a94b33075bfde0bba1708903db3a9f GIT binary patch literal 665 zcmV;K0%rY*P)1urvdM`kf=WQp&a=oB67o|B{!}V<3UY;lh$M2HVqxI)Kv57ILG1KEBj2a zY&I)OrP91*S(9!)p-||1Boet$EEb>jl|Uww5lc%;4=l?%6Ap)8x%o93jYJ?22*=~` zXg;5>yAth{fUfIzEz3G5gs4?2mBVg+u~_V(ZQExJ!`KFVb@LOwY@SFYZkeWe5g-^0 z{`rS{%g>s=2_%!r8Phbcw)@Ry^JhPT&=-MJDm7iN*Kc=B6r#2+1k&mBDZ?=Cb=x&f zo9_n!&mhd@a$|);;gJyHv!-cN9S7WMF>nHaux&e}Y1)*o>x+Z9hy+8%h`@-z&2Nx#R+*o-oNQnBY0`)=U1!@8@$2|ond<&Fb^-@slE z0#V?b$C|%@ai=W!1RMY^E4HH!ej1RMwG*yM5&$oOt-wa$39t;jRmM9MC`;QG#kTCA zK)c*y!HK{o;2^L=_J07g4u0o> zHF*S=9L5dhlfR)C1y+FTvSfg9$-En@z_bz%-FPSKAaG2!Ps{kKc|Ay0fSW$^`#Es3 zJEbJ%xfIbu zq7{p!=tr{DK>#5Em=G3&XpG}0J|jIs$c z0=^ps`W$6RkHvY|XTbBUp;fv1RqRASHTf9EPDiv4c&=ar_zPgCf{WlPJ%OO=FR99g zI6AZgG;X4wz+-?qr~B{+K_3KEnq(cItm_Cg6F|cs5M&6Tk4TzC0HCvfg@7r*4!NzQ zDS#rQhzYQ@z)>Iud<2MG!0n3E#z*xfJc-zcl=vek<{r8>V*Lf6iBJ)3B~1ZJpyr3*!FQ_ZhSH@Olsw`=5hn9Z=E5?UcZd?C8M3wma2D}e< H%cH*m5hjUW literal 0 HcmV?d00001 diff --git a/images/STL.png b/images/STL.png new file mode 100644 index 0000000000000000000000000000000000000000..50949001025b51ce6d5f30bd64d0ce6b23c4a8ee GIT binary patch literal 586 zcmV-Q0=4~#P)GD#2wK|!n(L=Xa3#7$CIXdzy8*hvb(Ad=vrRtD5Y@V7h;Y>wmb;&EW> zbwT`TY_f3!USnaU*r~0*YPDX(3Q(<9MZ4Wza9y{OPN(05`Sp4|Bauj?^ZESYMx)UU z1>G%xWm$8s>s}Q?Y;-!E=`g=sF1O@)-WA)n4*_4o{KResHw@#E<2W|~lF8(sf4C2# zyfZRDp-{N(IL_UzdcWWQ6-N?A0w@-X*Sp>BlWiS^*w_<*QmJ&ww(a?#T}rtc2f&U= zSg+T!&1UnN5aP3xa(3GU4+e}J01%$%rKFUzmSw#j#YQ9;vrGUc0AmN3$WHfxDd2!A zw}8#Pf;tC$13aJp1|F;SnLwLPSAgTb`iH1n@j>7vurGM_0C#{k&>Q6{IOQ9BPEFAT z;GNQ=zo3*H2}a_^;}aCIO$8wPeYD#0(cv+ z-PhR2s->n|+ct1|$Q;mVSr>s#6@dzH9@ww!Ch%1AgRu_WQ{|6=wx7N>ovcp|qW?nv Y0zT2Maz!=d$^ZZW07*qoM6N<$f+e*OdjJ3c literal 0 HcmV?d00001 diff --git a/images/SVG-white.png b/images/SVG-white.png new file mode 100644 index 0000000000000000000000000000000000000000..8b361cd3cc96c3ba0d0e8d3514a3368806d4e5e5 GIT binary patch literal 4254 zcmeHKT}YEr82-Lb=l(PX7X4i`gQ5t!a9b9EP|b8jCL&=Z^&t@ymVsTQ7a@^F-bhrm zRgyveTu2uYT||~$sapuaZYserx)Zf%F}Jz(yx-1QC)=my0x5ju`Of=3=Q;0r&(Alv z>lNjtd6sn+Ns{tBW$sF}c7iDf&xWR^Z)kFA50<*61pRgNb>9SIK3{gUL6WTb1X;R! ze+@|E1<#=pfd4+ijzhP%N#r)6-{*ii&#lG{paL0Y0BkaXOtoOs+;Ek(YYO4F-cVkx1kW4-cqy530)ZB@*?f-rW@ct$=`;ct z7kpiJ!3FsJ{)?EriD$~n%A!{xV_Q%GLqkJ#7K`PYI2#>-7%$eJw}8RH!5W<7joA}K zqtVXU++yN6FJWtIs|nlw0IMCrglEJF6lLDpMY*m&X8{$J%UceSUlpg)>?J=R_sh9wKz0lXf^ts@?0?%E_c|{yg$@75_SEOkx!C8SR)<;?^PXhl1D&{f;~&Ki`1Bo^tPNX4M{^kHXV?HL1iu#`Bkg{2keQCFn0#0Oy7%C!;B#&S z{#KT=9{v>253B%^h5>efwuX#W_XKDJ=su(j@h*VdL+U_qgcE4%7}qXv$5RRBaxg#z z(j7wpyq%AQ{|+D<2Nd8D1u$BGc6rf0CxY2d8VldY3D%Ai&yPUD7Ih$A3((p4fKLFK z6S${&$wvqC@%uyC2OMDWGvuJ{C8Oiw_H(N_GrL7ar-4@tbRVc<6To*Q^$P~vdLRan zy-7COvx4VE)GY9~S-wr+iUEE(wH?sLfTRMr(W`g~=;8$00iK*C6StUT6M%th;1>X4 zfLkvd%Gm?(;(sZCRx7RsVajM1cJt({0P*6H@Q&EeG&SJ)WTX*o62U3br9KHk;WyUwo%}^q4^-hnhV_)IJJO__0b)nuXbI~PcUw|S=t?#3V(5a S481L*Dm*3S?#Fx8%Rd06hY^tg literal 0 HcmV?d00001 diff --git a/images/SVG.png b/images/SVG.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c18281c35eef34f3600f0c12469611529e6c6a GIT binary patch literal 723 zcmV;^0xbQBP)9kfmS%_jU|_!g{O6nheDlrhTi9X?{K=%Q zt}ZK+$qc!!d(n>*3Wf5KNaT7togUs$0f|Jy%4V|zuIqM$!{HBpyi%zY4Fm$=rlzJ{ zsZ^@qD|EdAa=Bc;>$+Dh%UYbCo<8lzYiw*B^gOTAah#pNS3jP$p2eflXkW2dya5ml z2A6(AU#TQ!#R6in*v(?Gcw70)%gf(4q6jMz5Rb=u3WdUhRTC|1@t+82X=!P99Ot2l z+qONl5dzjM!ela8Gdeo@+_J10+qSz`9q`Hun=SybJkJZ+w%wh}<;FMTA+p$Fs|u(J z*m40?EB8Hc1Za?c8u;;-Yt#U7&7T5F<%p+%S-{iUPvE|cU()cm#@t?QtWU5y;HeQ$ z#k^-Oz5{T|kX1VmYy%d=cf?orUgI7VY;uiw9&km!1iU27Hv(tX&_Kk$H`~2Urq3tL^BV#<{EEj|Dp*bup=DKo_7U%mR0SR~j~D z2p%)iIS1I<_icons/background.png images/scalemarkers.png images/scalemarkers-white.png + images/AMF.png + images/AMF-white.png + images/CSG.png + images/CSG-white.png + images/DXF.png + images/DXF-white.png + images/OFF.png + images/OFF-white.png + images/PNG.png + images/PNG-white.png + images/STL.png + images/STL-white.png + images/SVG.png + images/SVG-white.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 6722aa2d..272bab7a 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -794,13 +794,17 @@ - :/images/export.png:/images/export.png + :/images/STL.png:/images/STL.png Export as &STL... + + + :/images/OFF.png:/images/OFF.png + Export as &OFF... @@ -1053,6 +1057,10 @@ + + + :/images/DXF.png:/images/DXF.png + Export as DXF... @@ -1132,11 +1140,19 @@ + + + :/images/PNG.png:/images/PNG.png + Export as Image... + + + :/images/CSG.png:/images/CSG.png + Export as CSG... @@ -1166,11 +1182,19 @@ + + + :/images/CSG.png:/images/CSG.png + Export as SVG... + + + :/images/AMF.png:/images/AMF.png + Export as AMF... diff --git a/src/mainwin.cc b/src/mainwin.cc index fb2e4d15..b04b2acf 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -497,7 +497,13 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(viewActionOrthogonal, ":/images/orthogonal.png", ":/images/orthogonalwhite.png"); initActionIcon(designActionPreview, ":/images/Preview-32.png", ":/images/Preview-32-white.png"); initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); - initActionIcon(designActionExportSTL, ":/images/export.png", ":/images/export-white.png"); + initActionIcon(designActionExportSTL, ":/images/STL.png", ":/images/STL-white.png"); + initActionIcon(designActionExportAMF, ":/images/AMF.png", ":/images/AMF-white.png"); + initActionIcon(designActionExportOFF, ":/images/OFF.png", ":/images/OFF-white.png"); + initActionIcon(designActionExportDXF, ":/images/DXF.png", ":/images/DXF-white.png"); + initActionIcon(designActionExportSVG, ":/images/SVG.png", ":/images/SVG-white.png"); + initActionIcon(designActionExportCSG, ":/images/CSG.png", ":/images/CSG-white.png"); + initActionIcon(designActionExportImage, ":/images/PNG.png", ":/images/PNG-white.png"); initActionIcon(viewActionViewAll, ":/images/zoom-all.png", ":/images/zoom-all-white.png"); initActionIcon(editActionUndo, ":/images/Command-Undo-32.png", ":/images/Command-Undo-32-white.png"); initActionIcon(editActionRedo, ":/images/Command-Redo-32.png", ":/images/Command-Redo-32-white.png"); From 083bf4313f8cc96262eecf6316cfc90c7494d918 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Tue, 20 Jan 2015 16:03:31 -0500 Subject: [PATCH 102/174] Allow the state to track cache lookup preference. This is important to allow lookups to prefer Nef polyhedrons in cases where PolySet->Nef fails due to zero triangles. Fixes #1027 --- src/GeometryEvaluator.cc | 42 ++++++++++++++++++++++++++-------------- src/GeometryEvaluator.h | 2 +- src/state.h | 5 ++++- 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 72490314..f950ce12 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -366,14 +366,17 @@ void GeometryEvaluator::addToParent(const State &state, */ Response GeometryEvaluator::visit(State &state, const AbstractNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, OPENSCAD_UNION).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -400,7 +403,7 @@ Response GeometryEvaluator::visit(State &state, const OffsetNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -412,7 +415,10 @@ Response GeometryEvaluator::visit(State &state, const OffsetNode &node) */ Response GeometryEvaluator::visit(State &state, const RenderNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { @@ -437,7 +443,7 @@ Response GeometryEvaluator::visit(State &state, const RenderNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -466,7 +472,7 @@ Response GeometryEvaluator::visit(State &state, const LeafNode &node) } geom.reset(geometry); } - else geom = smartCacheGet(node); + else geom = smartCacheGet(node, state.preferNef()); addToParent(state, node, geom); } return PruneTraversal; @@ -501,14 +507,17 @@ Response GeometryEvaluator::visit(State &state, const TextNode &node) */ Response GeometryEvaluator::visit(State &state, const CsgNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, node.type).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -583,7 +592,7 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -736,7 +745,7 @@ Response GeometryEvaluator::visit(State &state, const LinearExtrudeNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -844,7 +853,7 @@ Response GeometryEvaluator::visit(State &state, const RotateExtrudeNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -962,7 +971,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, false); } addToParent(state, node, geom); } @@ -1038,7 +1047,7 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node) } } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } @@ -1047,14 +1056,17 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node) Response GeometryEvaluator::visit(State &state, const AbstractIntersectionNode &node) { - if (state.isPrefix() && isSmartCached(node)) return PruneTraversal; + if (state.isPrefix()) { + if (isSmartCached(node)) return PruneTraversal; + state.setPreferNef(true); // Improve quality of CSG by avoiding conversion loss + } if (state.isPostfix()) { shared_ptr geom; if (!isSmartCached(node)) { geom = applyToChildren(node, OPENSCAD_INTERSECTION).constptr(); } else { - geom = smartCacheGet(node); + geom = smartCacheGet(node, state.preferNef()); } addToParent(state, node, geom); } diff --git a/src/GeometryEvaluator.h b/src/GeometryEvaluator.h index ca9b30dd..dd4f2131 100644 --- a/src/GeometryEvaluator.h +++ b/src/GeometryEvaluator.h @@ -54,7 +54,7 @@ private: }; void smartCacheInsert(const AbstractNode &node, const shared_ptr &geom); - shared_ptr smartCacheGet(const AbstractNode &node, bool preferNef = false); + shared_ptr smartCacheGet(const AbstractNode &node, bool preferNef); bool isSmartCached(const AbstractNode &node); std::vector collectChildren2D(const AbstractNode &node); Geometry::ChildList collectChildren3D(const AbstractNode &node); diff --git a/src/state.h b/src/state.h index 7739ed37..f396622a 100644 --- a/src/state.h +++ b/src/state.h @@ -7,7 +7,7 @@ class State { public: State(const class AbstractNode *parent) - : parentnode(parent), isprefix(false), ispostfix(false), numchildren(0) { + : parentnode(parent), isprefix(false), ispostfix(false), numchildren(0), prefernef(false) { this->matrix_ = Transform3d::Identity(); this->color_.fill(-1.0f); } @@ -19,6 +19,8 @@ public: void setParent(const AbstractNode *parent) { this->parentnode = parent; } void setMatrix(const Transform3d &m) { this->matrix_ = m; } void setColor(const Color4f &c) { this->color_ = c; } + void setPreferNef(bool on) { this->prefernef = on; } + bool preferNef() const { return this->prefernef; } bool isPrefix() const { return this->isprefix; } bool isPostfix() const { return this->ispostfix; } @@ -33,6 +35,7 @@ private: bool ispostfix; unsigned int numchildren; + bool prefernef; // Transformation matrix and color. FIXME: Generalize such state variables? Transform3d matrix_; Color4f color_; From c7a3e206d8971527d49ddcdcb5329dc3c3e42969 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 01:04:31 -0500 Subject: [PATCH 103/174] minor build fix; avoid generating empty -I or -L arguments. Needed for MacPorts build --- gettext.pri | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gettext.pri b/gettext.pri index 84fffa55..26a562a4 100644 --- a/gettext.pri +++ b/gettext.pri @@ -19,8 +19,9 @@ macx: { GETTEXT_LIBPATH = $$OPENSCAD_LIBRARIES_DIR/lib } } - GETTEXT_CXXFLAGS=-I$$GETTEXT_INCLUDEPATH - GETTEXT_LIBS=-L$$GETTEXT_LIBPATH -lintl -liconv + !isEmpty(GETTEXT_INCLUDEPATH): GETTEXT_CXXFLAGS = -I$$GETTEXT_INCLUDEPATH + !isEmpty(GETTEXT_LIBPATH): GETTEXT_LIBS = -L$$GETTEXT_LIBPATH + GETTEXT_LIBS += -lintl -liconv } QMAKE_CXXFLAGS += $$GETTEXT_CXXFLAGS From b64ef905a05037b6bb8c37faea74dd851b90bcd5 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 01:04:51 -0500 Subject: [PATCH 104/174] Clarified OS X build --- README.md | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 97d6c9e7..c1b91a43 100644 --- a/README.md +++ b/README.md @@ -123,29 +123,41 @@ To pull the MCAD library (http://reprap.org/wiki/MCAD), do the following: ### Building for Mac OS X Prerequisites: -* XCode, including XCode command-line tools (install from XCode Preferences). -Prerequisites that can be installed through MacPorts/homebrew: -* [CMake](http://cmake.org/) -* [automake](http://www.gnu.org/software/automake/) -* [pkg-config](http://www.freedesktop.org/wiki/Software/pkg-config/) -* [libtool](https://www.gnu.org/software/libtool/) +* XCode, including XCode command-line tools. -Then after you've cloned this git repository, run the script that sets up the -environment variables. +Install Dependencies: - source setenv_mac-qt5.sh +Run the script that sets up the environment variables: + ```source setenv_mac-qt5.sh``` -Then run the script to compile all the prerequisite libraries above: +Then run the script to compile all the dependencies: + ```./scripts/macosx-build-dependencies.sh``` - ./scripts/macosx-build-dependencies.sh -You can also install the prerequisites using -[MacPorts](http://www.macports.org). Unfortunately, -[brew](http://mxcl.github.com/homebrew/) doesn't yet support CGAL and -OpenCSG. +After building dependencies, follow the instructions in the *Compilation* section. + +For the adventurous, it might be possible to build OpenSCAD using _MacPorts_ or _Homebrew_. The main challenge is that both these systems have partially broken libraries, but that tends to change from time to time. + +1. **MacPorts** (assumes [MacPorts](http://macports.org) is already installed) + + NB! MacPorts currently doesn't support Qt5 very well, so using Qt4 + is the only working option at the moment. However, MacPorts' Qt4 + has a broken ```moc``` command, causing OpenSCAD compilation to + break. This may be fixed in MacPorts by the time you read this. + + ```sudo port install opencsg qscintilla boost cgal pkgconfig eigen3 harfbuzz fontconfig``` + +1. **Homebrew** (assumes [Homebrew](http://brew.sh)) is already installed) + + NB! Homebrew's ```qscintilla2``` component doesn't support Qt5, so using Qt4 is currently necessary. + However, Homebrew's Qt4 has a broken ```moc``` command, causing OpenSCAD compilation to + break. This may be fixed in Homebrew by the time you read this. + NB! Homebrew's ```harfbuzz``` package requires X11, so you may have to install an X11 server. + NB! Homebrew doesnt have an OpenCSG package + + ```brew install cgal qscintilla2 eigen harfbuzz``` -After that, follow the Compilation instructions below. ### Building for Linux/BSD @@ -220,9 +232,9 @@ For a 64-bit Windows cross-build, replace 32 with 64 in the above instructions. ### Compilation -First, run 'qmake openscad.pro' from Qt4 to generate a Makefile. On some systems -you need to run 'qmake4', 'qmake-qt4' or something alike to run the qt4 version -of the tool. +First, run 'qmake openscad.pro' from Qt4 to generate a Makefile. + +On some systems, depending on which version(s) of Qt you have installed, you may need to specify which version you want to use, e.g. by running 'qmake4', 'qmake-qt4' or something alike. Then run make. Finally you might run 'make install' as root or simply copy the 'openscad' binary (OpenSCAD.app on Mac OS X) to the bin directory of your choice. From 83e3c5a7e1ea1405382db2bf5ea6f2bd986d9b43 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 01:09:09 -0500 Subject: [PATCH 105/174] Updated prerequisites --- README.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c1b91a43..11ec3b3e 100644 --- a/README.md +++ b/README.md @@ -88,24 +88,23 @@ libraries from aptitude. If you're using Mac, or an older Linux/BSD, there are build scripts that download and compile the libraries from source. Follow the instructions for the platform you're compiling on below. -* [Qt4 (4.4 - 5.3)](http://www.qt.nokia.com/) -* [QScintilla2 (2.7)](http://www.riverbankcomputing.co.uk/software/qscintilla/) -* [CGAL (3.6 - 4.4)](http://www.cgal.org/) +* [Qt4 (4.4 - 5.4)](http://www.qt.nokia.com/) +* [QScintilla2 (2.7 - 2.8)](http://www.riverbankcomputing.co.uk/software/qscintilla/) +* [CGAL (3.6 - 4.5)](http://www.cgal.org/) * [GMP (5.x)](http://www.gmplib.org/) * [MPFR (3.x)](http://www.mpfr.org/) -* [cmake (2.8, required by CGAL and the test framework)](http://www.cmake.org/) -* [boost (1.35 - 1.55)](http://www.boost.org/) +* [cmake (2.8 - 3.0, required by CGAL and the test framework)](http://www.cmake.org/) +* [boost (1.35 - 1.57)](http://www.boost.org/) * [OpenCSG (1.3.2 ->)](http://www.opencsg.org/) * [GLEW (1.5.4 ->)](http://glew.sourceforge.net/) * [Eigen (3.x)](http://eigen.tuxfamily.org/) * [glib2 (2.x)](https://developer.gnome.org/glib/) -* [fontconfig (2.10)](http://fontconfig.org/) -* [freetype2 (2.4)](http://freetype.org/) -* [harfbuzz (0.9.19)](http://harfbuzz.org/) -* [GCC C++ Compiler (4.2 ->)](http://gcc.gnu.org/) -* [Bison (2.4)](http://www.gnu.org/software/bison/) -* [Flex (2.5.35)](http://flex.sourceforge.net/) -* [pkg-config (0.26)](http://www.freedesktop.org/wiki/Software/pkg-config/) +* [fontconfig (2.10 -> )](http://fontconfig.org/) +* [freetype2 (2.4 -> )](http://freetype.org/) +* [harfbuzz (0.9.19 -> )](http://harfbuzz.org/) +* [Bison (2.4 -> )](http://www.gnu.org/software/bison/) +* [Flex (2.5.35 -> )](http://flex.sourceforge.net/) +* [pkg-config (0.26 -> )](http://www.freedesktop.org/wiki/Software/pkg-config/) ### Getting the source code From 1a4599f213848d410733794b1f063b4859389ed2 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 02:06:35 -0500 Subject: [PATCH 106/174] #1165 updated expected image --- .../monotonepngtest/issue1165-expected.png | Bin 6903 -> 6903 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/regression/monotonepngtest/issue1165-expected.png b/tests/regression/monotonepngtest/issue1165-expected.png index b8199f788356cbb43f610db22867c5deffff12e4..481e887368d40a1bfca62d0db29ea88c321eed5f 100644 GIT binary patch literal 6903 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 D3*!+% literal 6903 zcmeHLYdBPE-(PE)=mi% zR0Kg39X8l*LJ$l@43Q;&9Z#CusofbaB4DrcB?RN-z+j+Kde zYs2FF6jiInt%jO6bF3UuTi2n1ajijYf0)KJUgqj6Dm{0t$@ECEt2?si{*>fNZz1nm zZitnBa?XzC=kg6>l}>2wlcKKd>3J$~(GHb14GtEo!_QgCch%iQ>fSe7L^oDV>4E~Hm#a6(E5d%=bgo02i{#2#qob-DJP|pG$1&eqy2e`x z#pk1yUqe$+CHk7qZb z_r8~!dg5Hy+?wvE0;#L^xAg^5Tb#ev7Sn}tx9c{JT5AhhRp~4#`JwYsjt6|MV-ZZu9%IfJ>}#V6`iL}_YX>*B5{B}CqTlC!}DQR1$ee$_ug zs0GjCzCEXII&*7(=`J}GFR)d(pwL;U;3FeYGIaQK=E8?zqiw!J*QlIoR=(O9%i_A& zr(XTz?&)0>wrK6M;Ksz!>iON)VfVU}659LjT@-5%?T$PxSw6JM;Kf){+KH~c#z}qS zuo@)aH5`?R{4zEE=RMw!>U+;>T~*%?>ovCIP0BNQ;#|4xs8*R-GF@|d&heQcjd}*W z%o3%{(Ga!r%Jo_g*sa4}BW+V21ZuG;-1;of((G|Sz18C{o$FD&Nw()_1U4zkx}Yi1 zOzdc+vyc@JD|#!4N0tR$RlbzC_$(e)-1za5m2BJ3Y8T0{Fjul5NNdRg0g{$j&9J1l zrB(NC-7(77lmcICG$=!(3D;BQD)!tq2~u5l=CpQTfNXKBVb{r%7+T||%HmJPUpJ+(Jw&~B^?q!aLm0+v z0#%Uy8HG_~Aw-ca&UMBA-s-8lNZja!&G(HB;i%J`CtDHs=!#?*YI1 z|6^Q&NnN%mPFrTOLzh&`zm1EGr1rBd$P0tvFWMTD9KC;i z;q67D>(#f<+YblQiDl>I0YJe89@b*udVc{NxW~hox#0_7==(XFg&g>@YZZ8cIhTbz z_Au0enbHTNa_(9*90e?ovE%YWUui?1Mev2Qkzb1!_+8eu1G8*LahB7Ub-Hc*b%qkpOlDcuw^50q|~WAfP1YD+;Z1u^v8FSc+i8>ZkbKI=Dv7z%#VxF(|v zeoF(toxkvMHu&ull$Q11tbuSMz~27F?*WKCx&oxsEr#}&+TV?kcr~-;1QSn;GAZ}F z5ijoC<^M?aZ0h(f<102>kt=E|#4G7-z+)#Li5Rm|Gt#ua(?ivrf zaX3N)5M2duJ#y++AnF6HMVYN+9{dJ*;Mz0};8=?Vh-J;hGhz0kY1rfd1kMPYNh=KE zbm0NzDpK8S6hEaC_?isG11LV^Q#%MJPuUWvj@*ZpAP#};%2kIC00SLm7UGbw${EYT zr&p#o3btCfpx##ovH&U@o;^!w2@4=`MN|~$9w{YVz(GM&Nr+eMl&&$7qqTslV6A&{ z@I?eBoL@G64zRQWi+=4@)^Ndm5O=6%lP3X7L2Ruq8QeQSNnfWsd=EAfAcd(d6oAEr z;7|GOpd)D5lg5c(!Rx<{165M5(a(NwGzy;5G@02F%lO^~mHRn26 zpE4o5R4<}rc%?#|cl9g=U9x&$a@()IhsKFcDU4DG9`vdU+5}&sz^|7zO33o#1x0h| z4wJ>e$U>Ecyg2D?4XT#{_OyE$bh!I6*r9uUKKbNKgYxi!W{>m2gaa{;B^GCP|C@F+!X|>(85R{mKRT`s9GKg^0O40v1EKv@WrrwA5_OR*LE3_+o7Gha7xJFSOX5pdbLs&OqB`sTd%;I^mrCfnOQlr zn>H45@Cd?Jgg>PhWMH5r2x9zX#sQKUADA(0-O0*+5>m!3LWyJsN;D1!QsI^xfX^go z0GJDi7`rgRgYllddF+>|x04 z|5eQqd~75$Ms}$HSyvx0L?VG87~MAjDM$oDo|{`9A``O$Ko>>m0qAuQ4gtdx?--Zm zCZG~ogZG+53YP%w9YDLeX@*n>j!uvcXaO-0Ty`g6fYiYPbt}zkbd9})u7@rzwG_uv zIpz0EA$&OwkYGEPNR!=V80i1YRe`Vt+7S^hhhm?=u*FXl(&5rr5Vh=G$&fJv{f5h> z$d;)EHLw1qJ6N6uF>ucA=VS+e=DKLP{#IoM%?{k`;3$*%G8|e+63{t|uBK*EB37f= zGYH*Vf%EZOEp4_u;U*xoYL-3UbM+YHZz9xT`A2Soh8OJ=S#PEQ$r#qeGvwBCV##Ef zN!DL~1JQ3v3Ee|C+cd0(Vg{f&?wc8P(8T}huRN^3FGDdKCFy<`5I#%@ zf(tuSyMY&LL;<5v!T$^1+j>`j3F7>Nt#IP6O#MW}+6R8( zDxCZ)y8CIGcynWY&tGAy+!;YnJauN-Y_eJ<*nVZwbeJ_dv<=YJsJ&kvyD>bxr8jc+ zK!8LMT1UH?L;PA9=&X>6=0$mf;q+p2bWo4XFIkPNIYdj3LZ)yba5&8fI`)alGU&F1 ze{d1gCL$)y%4P+FdmKjQ!?D7Rnz*zeMu%Sk^wv+9Q-kTbH)-h%0iw%z5ql&@=p7cO zP1{PKwG9K}Cz|*`>o`KFtuY~mC=ujOpzYyR9h+9?1HEYTw|{d z$~u4f_^01K$(>G%jARwz>8JkLtEs_rd&a-DOx9}{4NL3s7Hv;oCTq`Ed%C8)W}wRE zgkJ;~V@7=F(zoZY4WGYC-b-Tq!A`4>QV?h?b?gh%m}WYZ(=X=Nfaq0DinXby6ti|g{FH;EVY;36Q(|Re4ixh;;6KEtft=xam1&OG57k?>7IH|VzWK*;6+eqfM-i|2 z$+iZ!@sy^Fl1#Pp?ULjzrMt6`S9Wosk5aJi^0}oSnyXmz@@74jA&%@miHuq0h?`JOlyltm z7pfW6;&aKLNrmFP&o))>~hEMOkyXbf)(GsSB%1ZXE(f@I+wF;nJg+e!cNf{%7z^Wb#r> zrwVG%*JhMSPM>&DM>Ru}M@L6?z>@jfk|MIs9KeEHZ%<(3g9r?={CQR-coH@5zHVC*;k$sl2Kys4jWv8S+z zm+vB+(vq!}q?~G(SeI8umhe=BUzFzwZTJQDsF$S1J9dv8s9&_*I8hIKnS$+;=)FU^b6D!#xlIShc54AtT)A}T0yuc&k@2~O{6(o)q4;W__k(m$ zznwqN<%-bJ9xaRC7HH_@ER^Fsv`xOw=J0cPcdE>ms^&9Al!ER0b&=~tr6eI+C&S-1 z!7eCZf1VSLz%Gf0rJ>IjSb86*(D%FWHo0r3v7zr)SZWVW?t35#T z{2vni`w#bt-+m5FUMQl_7A@`yrkO>AeCLz9iv)uKyFO+Y`|M From ce5a367b8f64d6cd1b5a233796672559d193729e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 02:13:13 -0500 Subject: [PATCH 107/174] Clean up incoming polygon. Fixes #1165 --- src/GeometryUtils.cc | 45 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/GeometryUtils.cc b/src/GeometryUtils.cc index ba312de3..46f02e79 100644 --- a/src/GeometryUtils.cc +++ b/src/GeometryUtils.cc @@ -25,9 +25,11 @@ static void stdFree(void* userData, void* ptr) { This function should be robust wrt. malformed input. - It will only use existing vertices and is guaranteed use all - existing vertices, i.e. it will maintain connectivity if the input - polygon is part of a polygon mesh. + It will only use existing vertices and is guaranteed to maintain + connectivity if the input polygon is part of a polygon mesh. + + One requirement: The input vertices must be distinct + (i.e. duplicated must resolve to the same index). Returns true on error, false on success. */ @@ -38,12 +40,39 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, // No polygon. FIXME: Will this ever happen or can we assert here? if (polygons.faces.empty()) return false; - if (polygons.faces.size() == 1 && polygons.faces[0].size() == 3) { + // Remove consecutive equal vertices, as well as null ears + std::vector faces = polygons.faces; + BOOST_FOREACH(IndexedFace &face, faces) { + int i=0; + while (i < face.size()) { + if (face[i] == face[(i+1)%face.size()]) { // Two consecutively equal indices + face.erase(face.begin()+i); + } + else if (face[i] == face[(i+2)%face.size()]) { // Null ear + face.erase(face.begin() + (i+1)%face.size()); + } + else { + i++; + } + } + } + // First polygon has < 3 points - no output + if (faces[0].size() < 3) return false; + // Remove collapsed holes + for (int i=1;i allindices; - BOOST_FOREACH(const IndexedFace &face, polygons.faces) { - const Vector3f *verts = &polygons.vertices.front(); + BOOST_FOREACH(const IndexedFace &face, faces) { contour.clear(); BOOST_FOREACH(int idx, face) { const Vector3f &v = verts[idx]; @@ -99,7 +127,7 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, FIXME: This currently only works for polygons without holes. */ - if (polygons.faces.size() == 1) { // Only works for polygons without holes + if (faces.size() == 1) { // Only works for polygons without holes /* Algorithm: @@ -107,7 +135,6 @@ bool GeometryUtils::tessellatePolygonWithHoles(const IndexedPolygons &polygons, B) Locate all unused vertices C) For each unused vertex, create a triangle connecting it to the existing mesh */ - const IndexedFace &face = polygons.faces.front(); int inputSize = allindices.size(); // inputSize is number of points added to libtess2 std::vector vflags(inputSize); // Inits with 0's From dc9769e6adcb4614bc387faf0baffbc8fa0eff64 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 02:14:43 -0500 Subject: [PATCH 108/174] Moved fixed bug to issues --- tests/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 744af9a9..5d9bbbbf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1231,8 +1231,7 @@ list(APPEND BUGS_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue13.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105b.scad ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105c.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad - ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1165.scad) + ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue1105d.scad) list(APPEND EXPORT3D_TEST_FILES ${BUGS_FILES}) list(REMOVE_ITEM EXPORT3D_TEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/issue899.scad From 125fb788e1454f7b1ea0b1b1d5f14a40dca7f62f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 02:15:01 -0500 Subject: [PATCH 109/174] Moved fixed bug to issues --- testdata/scad/3D/issues/issue1165.scad | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 testdata/scad/3D/issues/issue1165.scad diff --git a/testdata/scad/3D/issues/issue1165.scad b/testdata/scad/3D/issues/issue1165.scad new file mode 100644 index 00000000..9338b16a --- /dev/null +++ b/testdata/scad/3D/issues/issue1165.scad @@ -0,0 +1,5 @@ +translate([0,10,0]) difference() { + cube(10, center=true); + translate([6,5.5,0]) cube(11, center=true); + translate([6,-5.500000000088,0]) cube(11, center=true); +} \ No newline at end of file From eef129324f0640f8cc87e39a8495038e72f0284e Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 09:39:37 -0500 Subject: [PATCH 110/174] Added test result --- .../throwntogethertest/issue1165-expected.png | Bin 0 -> 7697 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/regression/throwntogethertest/issue1165-expected.png diff --git a/tests/regression/throwntogethertest/issue1165-expected.png b/tests/regression/throwntogethertest/issue1165-expected.png new file mode 100644 index 0000000000000000000000000000000000000000..e4c5c6154106b5bcbfddde756f8bbfe38300aed2 GIT binary patch literal 7697 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 literal 0 HcmV?d00001 From 9808b2c14f787dba0614c9d495f268958bc9275d Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 10:01:18 -0500 Subject: [PATCH 111/174] Remember to update wikibooks on release --- doc/release-checklist.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/release-checklist.txt b/doc/release-checklist.txt index 118c9f03..95a977e0 100644 --- a/doc/release-checklist.txt +++ b/doc/release-checklist.txt @@ -70,6 +70,8 @@ o Notify package managers - OpenSUSE: Pavol Rusnak - MacPorts: Frank Schima - Arch Linux: Kyle Keen +o Update dev version to release version in documentation + - https://en.wikibooks.org/wiki/OpenSCAD_User_Manual Build and Upload Release Binaries --------------------------------- From 8e75fecacc54ab346f6dd628a34b77ffb0e85306 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 11:18:22 -0500 Subject: [PATCH 112/174] Display non-manifold warning after F6. Fixes #1162 --- src/mainwin.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mainwin.cc b/src/mainwin.cc index b04b2acf..0409e51c 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1823,14 +1823,18 @@ void MainWindow::actionRenderDone(shared_ptr root_geom) if (root_geom && !root_geom->isEmpty()) { if (const CGAL_Nef_polyhedron *N = dynamic_cast(root_geom.get())) { if (N->getDimension() == 3) { + bool simple = N->p3->is_simple(); PRINT(" Top level object is a 3D object:"); - PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no")); + PRINTB(" Simple: %6s", (simple ? "yes" : "no")); PRINTB(" Vertices: %6d", N->p3->number_of_vertices()); PRINTB(" Halfedges: %6d", N->p3->number_of_halfedges()); PRINTB(" Edges: %6d", N->p3->number_of_edges()); PRINTB(" Halffacets: %6d", N->p3->number_of_halffacets()); PRINTB(" Facets: %6d", N->p3->number_of_facets()); PRINTB(" Volumes: %6d", N->p3->number_of_volumes()); + if (!simple) { + PRINT("WARNING: Object may not be a valid 2-manifold and may need repair!"); + } } } else if (const PolySet *ps = dynamic_cast(root_geom.get())) { From 0ce207b950d036a855bb078fab89205f13588f16 Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Wed, 21 Jan 2015 12:52:53 -0500 Subject: [PATCH 113/174] Updated URL and release notes for snapshots --- appcast-snapshots.xml.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appcast-snapshots.xml.in b/appcast-snapshots.xml.in index bf167139..fa076e20 100644 --- a/appcast-snapshots.xml.in +++ b/appcast-snapshots.xml.in @@ -7,9 +7,9 @@ OpenSCAD @VERSION@ @VERSIONDATE@ - https://raw.github.com/openscad/openscad/master/RELEASE_NOTES + https://raw.github.com/openscad/openscad/master/releases/2014.QX.md 10.7.0 - Date: Wed, 21 Jan 2015 17:43:04 -0500 Subject: [PATCH 114/174] Added new Preview and Render icons from @atartanian --- images/Arrowhead-Right-32.png | Bin 4196 -> 0 bytes images/Preview-32-white.png | Bin 4196 -> 0 bytes images/Preview-32.png | Bin 4196 -> 0 bytes images/blackRender.png | Bin 4196 -> 0 bytes images/preview-32-white.png | Bin 0 -> 732 bytes images/preview-32.png | Bin 0 -> 705 bytes images/render-32-white.png | Bin 0 -> 775 bytes images/render-32.png | Bin 0 -> 748 bytes openscad.qrc | 8 ++++---- src/MainWindow.ui | 6 +++--- src/mainwin.cc | 4 ++-- 11 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 images/Arrowhead-Right-32.png delete mode 100644 images/Preview-32-white.png delete mode 100644 images/Preview-32.png delete mode 100644 images/blackRender.png create mode 100644 images/preview-32-white.png create mode 100644 images/preview-32.png create mode 100644 images/render-32-white.png create mode 100644 images/render-32.png diff --git a/images/Arrowhead-Right-32.png b/images/Arrowhead-Right-32.png deleted file mode 100644 index 42dd282b0f9b21968a3c2635067f15217bf5e039..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0KA zI0SzG{+;*b%NHHODruzR-@kv|K>Yga*RNJIvI4)cAP4*h0wDeQ`}gl2_*K(D7Ulq` zBYyt)@gs@`*5Ec0*#S^T{Qdd!XC7`HRF*+^0MrrxfBpK^Ol7OE8;8vSNRF6!_wHR5 z>^i9=ipv2YM}Pn@o34KP^eG3Gtiv>hkOM%D`19w_-ZyXF@L}qvf(S7V06F6C-@m8d zzke@A1uIdFAl3m;N8J4U`LhD52^8{3aRAg2Pl2T-^@?s%9RO7S{@b^2b`<&>p`8>5 z0Mo&9pzjS3x~ae-)&W4vZv*3Bg$h=p8bOQ$fR>;C`0=9zs!l5L2sr>)1{?%tKLILP zhiMEx2LMaKjc?z+rCliqatvtV)dshUQJK*YAU_0nCf>fy SS6IImWP+!wpUXO@geCx7iR=yl diff --git a/images/Preview-32-white.png b/images/Preview-32-white.png deleted file mode 100644 index 26f718c2fea3d91e8d1f04bfa6fdb6ffea00b9cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 zcmeH}JBSle6o$tjON_hA6takfB}I@0m#r)*<{{Qr5}n>@dsxUv*F z6;c#sDSkC}gE=B2xWMOwWU{3w>X~@#!p&R9jzrX7HMG9?8SpdkcNxfJGJ(Nh@b=I} zMx)Uow$IgSRj%P|q~Gtq8Y10p_nvd~dcB820=?Y-=?mb`1OR-^%{%&#N#Kr~-ILBR zjHEah0jTWeY-R*V?R^Ve2vFy}xe);THsC`67Gd3^6q|D+0Ol6y-^pgPE0szmTrQVY z3tZE*aJ$_;Td&toiVm_t2x>Ip^m;%D5b;+FROU{nvrZXytg=Xk*l$B7ifygcYMr;A z_q28r0A!73tD%=>{LT2t*f;k@UDsDV0Xo0zBtWE}1dOu0&gb(-<$S4B3ZmZCVz`qn@V$nkNVQ39Z3A|Q7Nk*el5! zlu9K#MTxY()$)t%e4%#S@Ap@t3@2 z$Qh30!)X@YpxRxeL*Yr-mJ#Vu8$;3=HsJU%QaeI76miVXn*;T+ zPb5HijAkWiJvUb!{tqsK!0~s3GLp;XW^H?}z^rrjvyJsF*0zv!uh*krwx_6(yUk|v hxKl0!*aR^%@ZV;jb7gex+16K?0;tNh@{{7`%|F{C;luy{ diff --git a/images/blackRender.png b/images/blackRender.png deleted file mode 100644 index da50aee561d349c2203969ae8c3313713114b346..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=hEV2xxn{IEF-UGAan%e-9KL1*0J_ z8Un!PA876*VF@n2h8dv0K0AgH9L zEx_dfkRvoTHTOC=IM6nS;Bx@T5uhAmZf;Jy974zeAV)xRh!suZf*1#Y90AQCVN`bn z2@d$JudkmqAPxZf{xh)1_M*DwAOi`705B0gHZ?Uhpo!~}9OSt~0mDVkZ1&jDIm zS{q$lTzF_|IW7n2=;-uEL_{#r+;VgW023Q+QaV1Lz!D+Q@{cr2>4Y2rOz97SDP0er sI-1D=3zwxdPw6ys{iwmCAuyOjVA|6ittSsWyAN`sr>mdKI;Vst07YENzyJUM diff --git a/images/preview-32-white.png b/images/preview-32-white.png new file mode 100644 index 0000000000000000000000000000000000000000..7001b9cfc9dcdf81647a297a8e9607ac6cb007f1 GIT binary patch literal 732 zcmV<20wev2P)L(*qm`9lP<)`V5RIaxs6~o2{s}2|D+R$yP>@9j; z>jRQacIIc18y&};*}I$BTv+DpdEDbD z0^5M+Ku1J(6nNH7&{H%}VN&RL!7+?J)u6lzg7yJKR z(&S=9CLkfxGk^K$>-+-}Z`jrP>MUP+*mXj+H9!nwt z+y#b~dnBtuEf3+n z=MRXd?v6#?>14AzJA1d6FAO&~Z)U#l$GkVQ&^k8CZ!ZwAgjfgM1q{#wT#){`rBYx6 z@DS*>#`XgbI!Ss&tlaD|_crhdSOcgc$cKddl;`|zpa#sgL%KpN*;If572sr=P$!J7 z1m@&`H40GRm3ZWSo<(nfwFRD`5-{O2aTjn8s7l;-7C?Sh_Ie3C&YFBwtOrDcwpIxv(Xv5S3#8zXCJ!&W!+d2Fy6{N8}-a z8YQF-Y5<~XxvWt;O1oUa(gM<8XO!gzM literal 0 HcmV?d00001 diff --git a/images/render-32-white.png b/images/render-32-white.png new file mode 100644 index 0000000000000000000000000000000000000000..6c17bb9fd30de46c8d7fa56880989961dcb1524a GIT binary patch literal 775 zcmV+i1Ni)jP)00007}NklpbjIp4Wb3kW1zOW$g$uB;t)cE11-67@M}Qd{>&=3XCm@v50(`Y( zefDGhH=2_3a#VDY;#9aB2EEU|JkAo zaMxsdvkxR*#}N>H!kI;ZX_Is!B*)QjYr1$+i}F9pi01YQEnIG9N=HqBfI zMsi%kbLpcwiin!D#iTlP3YWn2EboYB4BxLxb>-4%{uOxdvbX*P0007uNkl7_@+OzWKOEtn@AtX)`G`Y24C(JX>Wp2$4B+WA4z$+8aXau> zo!$WE0ULo&N*k$_V+XjPPF?_AAu_^5KjdRg73OQ1QP4hzKr^zf?Z}A6?+}L`rxhfv^A;+BjGX{L*qcP~_fSM9jJn#u(zZ zhtTH(qiS=?_N1p&;XSZ^j+$r&TnA(lWC}zloSX*6BF1ngq&1gBYr$gD63D`Fkiow@ zqD}X9dV*kR#Pz$D=xM8e|KY-AcHR<1DU2-%NnGO(6NGO8@cL!^;7=D~L&hq;&IXL&O7b72-aD+;lB-FdW!!!yjqrsLd?!zx`9-W`sZ^ eLdJTf0sa7#H?1mV45MKH0000icons/prefsUpdate.png icons/flattr.png src/AboutDialog.html - images/Arrowhead-Right-32.png images/export.png images/axes.png images/export-white.png @@ -47,7 +46,6 @@ images/left.png images/blackUp.png images/blackNew.png - images/blackRender.png images/Rotation-32.png images/Shape-Cube-32.png images/Open-32.png @@ -71,11 +69,13 @@ images/orthogonal.png images/cross.png images/perspective1.png - images/Preview-32.png + images/preview-32.png + images/preview-32-white.png + images/render-32.png + images/render-32-white.png images/animate.png images/orthogonalwhite.png images/perspective1white.png - images/Preview-32-white.png images/crosswhite.png icons/background.png images/scalemarkers.png diff --git a/src/MainWindow.ui b/src/MainWindow.ui index 272bab7a..89ba4524 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -245,7 +245,7 @@ 0 0 1397 - 33 + 22 @@ -750,7 +750,7 @@ - :/images/Preview-32.png:/images/Preview-32.png + :/images/preview-32.png:/images/preview-32.png &Preview @@ -762,7 +762,7 @@ - :/images/blackRender.png:/images/blackRender.png + :/images/render-32.png:/images/render-32.png &Render diff --git a/src/mainwin.cc b/src/mainwin.cc index 0409e51c..6aaa4840 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -479,7 +479,7 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(fileActionSave, ":/images/Save-32.png", ":/images/Save-128.png"); initActionIcon(editActionZoomTextIn, ":/images/zoom-text-in.png", ":/images/zoom-text-in-white.png"); initActionIcon(editActionZoomTextOut, ":/images/zoom-text-out.png", ":/images/zoom-text-out-white.png"); - initActionIcon(designActionRender, ":/images/blackRender.png", ":/images/Arrowhead-Right-32.png"); + initActionIcon(designActionRender, ":/images/render-32.png", ":/images/render-32-white.png"); initActionIcon(viewActionShowAxes, ":/images/blackaxes.png", ":/images/axes.png"); initActionIcon(viewActionShowEdges, ":/images/Rotation-32.png", ":/images/grid.png"); initActionIcon(viewActionZoomIn, ":/images/zoomin.png", ":/images/Zoom-In-32.png"); @@ -495,7 +495,7 @@ MainWindow::MainWindow(const QString &filename) initActionIcon(viewActionShowCrosshairs, ":/images/cross.png", ":/images/crosswhite.png"); initActionIcon(viewActionPerspective, ":/images/perspective1.png", ":/images/perspective1white.png"); initActionIcon(viewActionOrthogonal, ":/images/orthogonal.png", ":/images/orthogonalwhite.png"); - initActionIcon(designActionPreview, ":/images/Preview-32.png", ":/images/Preview-32-white.png"); + initActionIcon(designActionPreview, ":/images/preview-32.png", ":/images/preview-32-white.png"); initActionIcon(viewActionAnimate, ":/images/animate.png", ":/images/animate.png"); initActionIcon(designActionExportSTL, ":/images/STL.png", ":/images/STL-white.png"); initActionIcon(designActionExportAMF, ":/images/AMF.png", ":/images/AMF-white.png"); From b14e6986979211846703a9c2f323cafe4f29176a Mon Sep 17 00:00:00 2001 From: b4zz4 Date: Wed, 21 Jan 2015 22:23:43 -0300 Subject: [PATCH 115/174] =?UTF-8?q?espa=C3=B1ol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locale/es.po | 1012 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1012 insertions(+) create mode 100644 locale/es.po diff --git a/locale/es.po b/locale/es.po new file mode 100644 index 00000000..2cd1b89c --- /dev/null +++ b/locale/es.po @@ -0,0 +1,1012 @@ +# French translations for OpenSCAD package. +# Copyright (C) 2013 THE OpenSCAD'S COPYRIGHT HOLDER +# This file is distributed under the same license as the OpenSCAD package. +# don , 2013. +# +msgid "" +msgstr "" +"Project-Id-Version: OpenSCAD 2013.02.07\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-12-22 23:28+0100\n" +"PO-Revision-Date: 2015-01-21 22:23-0300\n" +"Last-Translator: Ernesto Bazzano \n" +"Language-Team: Español\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Generator: Poedit 1.5.4\n" + +#: objects/ui_AboutDialog.h:51 src/AboutDialog.h:15 +msgid "About OpenSCAD" +msgstr "acerca de OpenSCAD" + +#: objects/ui_FontListDialog.h:102 +msgid "OpenSCAD Font List" +msgstr "Lista de fuentes OpenSCAD" + +#: objects/ui_FontListDialog.h:103 objects/ui_LibraryInfoDialog.h:77 +msgid "&OK" +msgstr "&Aceptar" + +#: objects/ui_FontListDialog.h:104 +msgid "Copy to Clipboard" +msgstr "Copiar al portapapeles" + +#: objects/ui_FontListDialog.h:105 +msgid "Filter:" +msgstr "Filtro:" + +#: objects/ui_FontListDialog.h:106 +msgid "" +"