From eb33929a623da3858f8105e54f0834f8393f5414 Mon Sep 17 00:00:00 2001 From: vsr Date: Thu, 13 Dec 2012 08:40:36 +0000 Subject: [PATCH] Merge from V6_main 13/12/2012 --- doc/salome/gui/GEOM/images/3dsketch4.png | Bin 0 -> 8299 bytes .../gui/GEOM/images/3dsketch_2angles_rel.png | Bin 0 -> 7100 bytes .../gui/GEOM/images/3dsketch_angle_abs.png | Bin 0 -> 6087 bytes .../GEOM/images/3dsketch_angle_height_rel.png | Bin 0 -> 6997 bytes .../gui/GEOM/images/3dsketch_angle_rel.png | Bin 0 -> 6157 bytes doc/salome/gui/GEOM/images/3dsketch_dlg.png | Bin 0 -> 36260 bytes doc/salome/gui/GEOM/images/fused_wire.png | Bin 0 -> 1399 bytes doc/salome/gui/GEOM/images/iges_unit.png | Bin 6488 -> 10444 bytes doc/salome/gui/GEOM/images/pipe_path.png | Bin 0 -> 9274 bytes doc/salome/gui/GEOM/images/pipe_path_dlg.png | Bin 0 -> 24830 bytes .../gui/GEOM/images/wire_before_fuse.png | Bin 0 -> 1451 bytes .../GEOM/input/check_compound_of_blocks.doc | 4 +- .../gui/GEOM/input/creating_3dsketcher.doc | 55 +- .../gui/GEOM/input/creating_adv_obj.doc | 14 - .../gui/GEOM/input/creating_complex_obj.doc | 2 +- .../gui/GEOM/input/creating_compound.doc | 4 + .../GEOM/input/creating_dividedcylinder.doc | 6 +- .../gui/GEOM/input/creating_divideddisk.doc | 14 +- .../GEOM/input/creating_hexaedral_solid.doc | 36 +- .../gui/GEOM/input/creating_pipe_path.doc | 44 + .../GEOM/input/creating_quadrangle_face.doc | 52 +- .../gui/GEOM/input/creating_sketcher.doc | 6 +- doc/salome/gui/GEOM/input/faq.doc | 12 + .../gui/GEOM/input/fillet1d_operation.doc | 2 +- .../gui/GEOM/input/first_steps_guide.doc | 12 - .../gui/GEOM/input/fuse_edges_operation.doc | 16 +- doc/salome/gui/GEOM/input/fuse_operation.doc | 34 +- doc/salome/gui/GEOM/input/get_non_blocks.doc | 14 +- doc/salome/gui/GEOM/input/import_export.doc | 8 +- doc/salome/gui/GEOM/input/index.doc | 6 +- doc/salome/gui/GEOM/input/partition.doc | 10 +- .../gui/GEOM/input/partition_explanation.doc | 12 +- .../gui/GEOM/input/tui_advanced_geom_objs.doc | 10 +- .../gui/GEOM/input/tui_complex_objs.doc | 87 +- .../gui/GEOM/input/tui_get_non_blocks.doc | 2 +- .../gui/GEOM/input/working_with_groups.doc | 15 +- idl/GEOM_Gen.idl | 61 +- src/EntityGUI/EntityGUI_3DSketcherDlg.cxx | 1164 +++++++++++------ src/EntityGUI/EntityGUI_3DSketcherDlg.h | 74 +- src/EntityGUI/EntityGUI_Angles_QTD.ui | 48 +- src/EntityGUI/EntityGUI_Controls_QTD.ui | 30 +- src/EntityGUI/EntityGUI_Type_QTD.ui | 87 ++ src/EntityGUI/EntityGUI_Widgets.cxx | 14 + src/EntityGUI/EntityGUI_Widgets.h | 16 + src/EntityGUI/Makefile.am | 1 + src/GEOM/GEOM_Engine.cxx | 17 +- src/GEOMAlgo/BlockFix_SphereSpaceModifier.cxx | 12 + src/GEOMAlgo/GEOMAlgo_Builder_2.cxx | 26 +- src/GEOMAlgo/GEOMAlgo_FinderShapeOn2.cxx | 252 ++-- src/GEOMAlgo/GEOMAlgo_FinderShapeOnQuad.cxx | 2 +- src/GEOMAlgo/GEOMAlgo_GetInPlace_3.cxx | 2 +- src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx | 3 +- src/GEOMAlgo/GEOMAlgo_Gluer2_1.cxx | 1 - src/GEOMGUI/GEOM_Displayer.cxx | 26 +- src/GEOMGUI/GEOM_images.ts | 8 + src/GEOMGUI/GEOM_msg_en.ts | 75 +- src/GEOMGUI/GEOM_msg_fr.ts | 253 +++- src/GEOMGUI/GeometryGUI.cxx | 268 ++-- src/GEOMGUI/GeometryGUI_Operations.h | 1 + src/GEOMImpl/GEOMImpl_3DSketcherDriver.cxx | 49 +- src/GEOMImpl/GEOMImpl_Gen.cxx | 3 +- src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx | 174 ++- src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx | 14 +- src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx | 44 +- src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx | 14 +- src/GEOMImpl/GEOMImpl_IInsertOperations.cxx | 23 +- src/GEOMImpl/GEOMImpl_IPipePath.hxx | 61 + src/GEOMImpl/GEOMImpl_PartitionDriver.cxx | 19 +- src/GEOMImpl/GEOMImpl_PipeDriver.cxx | 29 +- src/GEOMImpl/GEOMImpl_PipePathDriver.cxx | 242 ++++ src/GEOMImpl/GEOMImpl_PipePathDriver.hxx | 167 +++ src/GEOMImpl/GEOMImpl_ShapeDriver.cxx | 127 +- src/GEOMImpl/GEOMImpl_ShapeDriver.hxx | 12 +- src/GEOMImpl/GEOMImpl_Types.hxx | 6 + src/GEOMImpl/Makefile.am | 3 + src/GEOMToolsGUI/GEOMToolsGUI.cxx | 6 +- src/GEOMToolsGUI/GEOMToolsGUI_1.cxx | 4 +- src/GEOM_I/GEOM_Gen_i.cc | 11 + src/GEOM_I/GEOM_Gen_i.hh | 3 + src/GEOM_I/GEOM_I3DPrimOperations_i.cc | 80 +- src/GEOM_I/GEOM_I3DPrimOperations_i.hh | 8 +- src/GEOM_I/Makefile.am | 3 +- src/GEOM_PY/structelem/__init__.py | 8 +- src/GEOM_PY/structelem/orientation.py | 25 +- src/GEOM_SWIG/GEOM_TestAll.py | 38 +- src/GEOM_SWIG/GEOM_TestOthers.py | 17 +- src/GEOM_SWIG/geompyDC.py | 198 ++- src/GEOM_SWIG/gsketcher.py | 107 +- src/GenerationGUI/GenerationGUI.cxx | 5 +- .../GenerationGUI_PipePathDlg.cxx | 392 ++++++ src/GenerationGUI/GenerationGUI_PipePathDlg.h | 72 + src/GenerationGUI/Makefile.am | 13 +- src/IGESImport/IGESImport.cxx | 8 +- src/NMTTools/NMTTools_CheckerSI_1.cxx | 29 +- src/STEPExport/STEPExport.cxx | 53 +- src/STEPImport/STEPImport.cxx | 19 +- .../ShHealOper_ChangeOrientation.cxx | 60 +- 97 files changed, 3909 insertions(+), 1155 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/3dsketch4.png create mode 100644 doc/salome/gui/GEOM/images/3dsketch_2angles_rel.png create mode 100644 doc/salome/gui/GEOM/images/3dsketch_angle_abs.png create mode 100644 doc/salome/gui/GEOM/images/3dsketch_angle_height_rel.png create mode 100644 doc/salome/gui/GEOM/images/3dsketch_angle_rel.png create mode 100644 doc/salome/gui/GEOM/images/3dsketch_dlg.png create mode 100644 doc/salome/gui/GEOM/images/fused_wire.png create mode 100644 doc/salome/gui/GEOM/images/pipe_path.png create mode 100644 doc/salome/gui/GEOM/images/pipe_path_dlg.png create mode 100644 doc/salome/gui/GEOM/images/wire_before_fuse.png delete mode 100644 doc/salome/gui/GEOM/input/creating_adv_obj.doc create mode 100644 doc/salome/gui/GEOM/input/creating_pipe_path.doc create mode 100644 doc/salome/gui/GEOM/input/faq.doc delete mode 100644 doc/salome/gui/GEOM/input/first_steps_guide.doc create mode 100644 src/EntityGUI/EntityGUI_Type_QTD.ui create mode 100644 src/GEOMImpl/GEOMImpl_IPipePath.hxx create mode 100644 src/GEOMImpl/GEOMImpl_PipePathDriver.cxx create mode 100644 src/GEOMImpl/GEOMImpl_PipePathDriver.hxx create mode 100644 src/GenerationGUI/GenerationGUI_PipePathDlg.cxx create mode 100644 src/GenerationGUI/GenerationGUI_PipePathDlg.h diff --git a/doc/salome/gui/GEOM/images/3dsketch4.png b/doc/salome/gui/GEOM/images/3dsketch4.png new file mode 100644 index 0000000000000000000000000000000000000000..b5a4d9eca0e68b620e3ccc1aae18459b77dc5650 GIT binary patch literal 8299 zcmdUVWmJ@3wD&_vgE-O%N(zeLAYBTB)Byeg1*D~jIwXhg?vNO1kdC3d zyXQXq*ZbkF`{7;deLvj0?ppB7ndihl=j^?I`*-%4pf}30q(pQ?005B6%fVCu0NWG* zuu=%H!8h)rLE+#Bp`DzT16V%>{s&>1-rY`<&nRa zJ`CRcQtIK;a2aFS%q@#YX-Dr0CNCe?G^D-J-WnbnU6YwwKYnLXQf(mp>h2p(B3xXV z(c%DpiiuNhLdBEI&cQ`qNNd7G9~9lc$P^ce>QPJ9C+#Cn&L;Erd6&AmV1&2l_NjOmCg{p;w8 zT$h&Sb|9OPzRX99M0+t`MV;_;W_V`p3sB7&K^QCbKH&6D`{_`=aZ%3tj{vjg{*{Whb?m$q^SY zO$T;4>bzXB7WJ+h%maS;8)FC5RJDbkgs9wjj|inxW4|P{H34YYQ}=V;9Y5Rhw)y70 zZ4Rz|HsjKVSZR^Y5dj1EtuU1};U6nMe~Gg$ukS z1SjpV=a8-e{JO)iAE%r?2KY0KC28LLd0{|F@tOx9ka^F3*ulpBbkgkTJ&^suhzbDM zSRw!W9=D4DEDT_siN1t2y&F0bo+bN5(JBLBlHt)_W7cjm?Sm;hin?yaW!|2iF-4cN zjZKEzY3VU^1wua}l2VL+=Ndxballif4;wLy5rSS$Ykjh%$>%FlWp0q9$$j~mF=uNx z*ZIOa=j3{8odfpki>9@ztwzx*9yEG6Jm2gj(MCMya&k~!o8-OdmX9%Z@prIXT6wBl zE~*5Zoqb`a)SbwU^Gv7UP_utz^7yOM`2O&@q<$sOTi9&> z`YCGG#wb#NzS>*!0SecE)`W8YiH?A-nKjK&Ws4TY`Sv&b)!ns%2P6*a@4iXH0?N@& zxy6l}F^KBT!iUeO1Yl4s&5kyV=jic5`pl?qqu$hU7Z3h38(qv*VlNIXL*A<8i>1@F z&HQ^UW1lesQI(j~`+E`*M=vYx>Z39z*C{!QB&Sa0dOY@tt$0wfDoDaqXJnfN0KNZNWmX3_14=o>) zxZF>+VG&uGeutS}-mFL%t(i{UN2#1R=M9Rx-$7lK^B=ZB2v{M!#FpYB^re$VWI4+} z`jkR9WxsK;eb5|z6s|{RzWReGTwjYXcR;*BtiR0VK?fUM0}+t>{}52dl}6!a7f~eX z8ivyUUnm5F>Cu(iz40uZYC$MD(v{N0LO{@MtMiFhFtmqPjiRd=-Hdu91sKe2|GFDU z{R@HI#zW;dlS zcZO}?n@x*0y`3R`9?oV~^jFvAv3*OQ-oG%BRe`d+>yTN_e6^O@F)Vp$&tJ7g)tw)w zOcBm``mOlbj7pYAP{GRx}# zP(ckyChzx}X_fK}U>-ldIINvVFdi2Mepi}h*vWP^Q$(a|;5vYDr*09CR760$P#~_h&)z>>FJ4^o-guj>Mv_4B&|}!cBT?5Aq1_wSE*!I zSEj9x-W!OpLaM*GRL$~QME(3a^6fDt2m}X?hT>x?NnH7uKZmqaPh{58OoW^2F%5(m z4NZmyyD{C@MR-}#P+x6V%SD5+U{3DPEs2rWFb3v!lkf%T8v%mIt+(XH)(sqI!TwB1 z+_?#e#<;;eAKGyEuREZQi;IO!PqJPy4@o#BIqHs;AAI#K?Ozin%gG-kRc`u>#KbC_ z%bZn|J_Z9VA9I{fE}Aq!Uo_X)a$)7@*(PjhuF~6*oXvEVZBxTe$YNA+eqAz4U2C1! zosbtK3y-zVq+VxswSHqV{R6uF_t3{q4azzNn=wUW0w0|AN`@+Hzq zxT6qDh4SYgH~5u*Pc17{we?Dl9sb8D{{GZY)y^n+PQyp6kSqvu35iK!hQCZWJXSq0 z3YsBcO8eN*i4|gcpSdAwU_3T6s+bhyc&H9F_Duh4kZgIk$t#T0gN(^IEJW*$fjgOnCsz6`2i{P@82-W~k%eNZrAPU=fv+6L-AVm= z*~0FeGwLHs<`J0v)=eIPzt7$smN+kKd*`D~M_f2)u`ZGR&tyHbv}W(o4S+Dw6;I10 z8C{6cj3kL_u?-qougHr?ZcC`>4YRas2u}WI7k_6*3f$^-e`V-lmI<7Pc#DP8ro&W5 zKILErPRoqhrTG$~^>F+k>$=!TU@@WJxYd-RMyLpB|D@Kp_x(MhBR%E;Irh7(g_(a@ zjYXC(#mDOjnP1zYTGPNVm1AlLZbxzMvrK&MXm;Tw!tTLbRH4V+&ID6lm=7I{H!Y#e%qtQ$`xaMI+)n z_b|>UkY8~;Lv6b&$7YMxqG>0`*2ZD38jRgh7csgmVp%#4NfnN zMnvfeSAEZXwxjsL#v!dJnTwq`)Yc z<*lW|Saa%__gQz0QAd<3cj9@KW%OHr+S1m$FsR{ktA;yt^p)%-B9i9D$O4cDr8K2i z1ztIi`|TT+!ZW5>e*FAN#zIB&O^!X^SM?4PePzJqZWzZp)2`wlIarQ);GtV2AY|xb>{>%XOaeB~;$xA@ia~uRfSSJsd#PzMB;BOf zEb3qHVEmX|&TH$Lw?_EW?@X7Nfz%L$<%&gf>jP!VQ9+xy)OL#g^n38v^v{toUM}G- zgD?03`kLiaA_hNR@14Cy5`QzYkcsMmMR_{^>Mr%lF^Uu<-z;7nsu)jOSPLkT8B=6I zRCxLg29r{P^GIh?V|soJ5q@1rSS2NTt%&G8#@hFY|4kJYCHoY$J@5YIxqL!8iz0Dh z=hLYe3sAQd^kuxF+rHAo$N}ZD4{f9R)84W=k?5R1dF%9L1nd!nmIF+$K$V7?5uW=s zt(trSA+l}2oRB1mzkSy)`X$s*-bNa^r)l(#B#DdWSpjI6ljFq|xU<+D~6uX)o^=?GxkDWa#$BGF0(G1S@=79)!hB>(CI!)fGP`xzhE)i`!%i5^IBY5$_ zoF0rQ{xMmaGW^nJV1$*_+5Xw2ju6c|5Rn{rlisbwf2J4Azwwm4f4>A05%dOhMz(6Q zq~YCa4VbCF#_g%PA>K`mLqoq;V!?8o4TL<$Y%^$QYY| zJ6W2e|J;u`g7D$}{b-dvFw<~%D3I;%et_G*>5Tu)k04%mEFU*gh4Gop_V6cc6|<8< zXJ0?>*Cc5(5IU$^P-Dt%s&8_>stP!M`~>By-x~OmwQIG`w6%;)z?%i1%L08vvAa#} zJ%hK<@ssPhU;Z;nn>vk-1t;y6CDcXj8=d+z#pNzjIB30(rMvL%sg0D&-U0FuO{fp> z;SX-^VaJ6Bl3eRP?Yk_dpdcc+i$mlcxjYib_@9%$=@s#X*9$sgQL z5k22Q2!_?YI1CO4$t2sd;1yb3kMd*-aMnka zTL}SYDQI4ns)CBmw(%M+Ao?gyaIY{bx%@TM5!)x}M^CPb>II%O2QV(b#y+f%lSvc+ z4&wVm(UezlJs=eVJmpr8FgM^7e=F=rw2ccmlsQ0gTq1^eKxPAI29rjb=lZJR(N_Wn zgeUS@%L?m3W`tNiaay8r?C4v1!U4oavPGJI1{>X$zx|A$WzKYL8z2PO4SkIROgY6t z1_AI!%SW1bM@D(KD5?R?k5?4faWX{&tgs$-!NcJS>%_@yxIl}cF_bft>A55J%U{n; zCP~5JaOGlsPq%61#>}ppsR`qhw7Vu8N8OKkxxqBh_i|243YgQwFTSL3tc}W-ajGBx-uNmyuRQe z)e?IANU(6ULKivN)4N`EU|`n7!zlzZMW93p>f}3B45rTVok{yiye(@3#loY-ZPOfD z@oA+eciqdUYAe2qNL0?5Q=D&(SLxI5-#Da*aWU_H$5_g1E%|8i1a+~@j9zD4PELli zDV{o>j=7Vxl=%bx&^k7?)l9SQ*@mr=qW?9kTGk#TbZzIR<*^V)I*M$rjPfu zdEHP5I8$kM{Xu}_uXlR1D|Ug>8TqZ(e`0bwwU*SLLR*&pj9 zm$}$+e}lS>VJFDZwLwR5K9dvJ;(~#TS;*uB0RUNn(l1W0axO_5qM+1UasLwAHME%- z4g%45_J^^>>)mn4O7>oVEw>-3HXr~QLjC2m8CPz+M5B5`Ym)yyny5BH*74daYNW8fB-b@W=6Rc(%gySBoPC1q-p0(iJQ;naTxWBwV{P#Z+q7T z0SYbq;<7;aI%a<@gIn>F$Hx=}>*H;Z1NiDT)PN3AEE1uG*PrSjcd1M6bY8pX-t#$0 zP-5II{bT~PxD_kffum$U%mZ=cFClhleZAh%NIP2a(`Z2I=}b+7ew~+wVjA6V9bp&# zor($;lJnKrTjvV?^!xCQ(-ST;kxo|Y!fcX5Po&>`(9{QJMUYAL_9>Fh-7A3GBH14e zn+F7Dsi5YrzhPBBisNtAS0ZGnvLgaB&k|NWqX2@R%}%G^QJDuqAy1u#*Q_IF8iKc4 zl;ux%ognN*gdm~xkq?LO?sx6fZ6LM{^6?G0Scl17jf-;VyozWxv0`yiNAv-G8|y6) z+a_VpuUIs}#urS|$h?=HOlM>`ytpWmsJm!olGdj9RLIL8;XOXYIkL{u-jW8OVKK1s zxo%x_?Oe($G!f+JD*-fq#&;5|87Gvcyz6c(u$%4b4U=1*o^~-35m!z(QM|O{HKFU_ zl14f``S5d>7dT{zGc|18hD9c398p8OzhY?;qh3(+)xT(;{l{<(caFc$BwlxbabjEd zPeRUtzLFA_dXVvZ={a|*_{^iF6R){l6YM=0l)Hlm=SQ!y>IHR^G*C^e9~o!w!t+%c z#yUO!aq5@1PC<4`pZ-Eh=KP9I0`ea>PmVhqu~016gVm@wVNbb#>`}WK1;=BgY3?@j z^%K%!nYcjH-V~qdSEoQ*I(kv-2?fN=LyJGw{b26E2XSuwCz0RgcLz)7iq*tUjP_@d zex>)MU?0puf7H2V|KGr3UUzeXAp)R_aooCN^99FnZV!W)gfvMOiZ zq5u#ZSA=4?i}0AVERMX7hpMaHl&!6>s99VxM}s#}FMqhEfCFs8xDJq%*$7npm2F+6 zRiT$yqv9tSllJMvBt7uf$H(Bna!u4YvSnLeo-yWBlV&k=7{O~_2l7I&uSL{ z@cVOV++k*OpEIyuOg+75(s4->nWdCPzRttUWM%Xl7tjm{TZKO0zxL}VTS}>O=Pppn zYcT7(a0ahuao_Ig8K+ITtZboLTM-AzuK+-CpFi$=I5}@U<~~)7PNVZo=OrHSu*(x2 z8*;SJ&E-|60gCKD4VlnxTAuZQbkshOw-`N||Jx^l<_A~3cp2rkX`I~jX?yt+f0H`l zcgK#XL$pI209fv?TTjTqSnL0!pDRIOFtTrfR|`g~U&C%(9aR@1roEVl(w&00>f;;0 z=mfN#C&N#*yNXgC1u=&+f0a>|^W;DV_Mqb~U#^CJ84LEPvi8a?{)kGxmOz6W^=jD& ziWraWZ4#G$9|+zrP@O0IcClX(L=CueG9S7uWxcRHfuqYIcweqwDFHr|ZYezzE}253 zTa!(Q3$>)=2<&jr@G3U%Vzs3@!NFk3O~;0t(M1kfj+vUvzqBc%#DLGMdKFWoa?&&1 zT1UfXpD)acGL1csf95s{(crXok$r!|f=(_Nu>jsTu5FJ_Jx+hx+M;Lnras#yihHat zq3UE_7wOD8Egu{U)>H)LaH4t>ZkF_eBjW`h#17cZq_#=q(*gjF&;nmlRb#Z@o;htK z?4Aq*vrEtxrQ76kG_}~lz?PD5%7ZTI@UhnQxE)s0LATZ0shk^@RcNu=S3~%f*}^H1mtCuVTDo#e*XcpeEIPJ literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/3dsketch_2angles_rel.png b/doc/salome/gui/GEOM/images/3dsketch_2angles_rel.png new file mode 100644 index 0000000000000000000000000000000000000000..7e815d4ea12d21722b8701a6307a3014c31189c1 GIT binary patch literal 7100 zcmb7JXHZjJw+{Fs3L+@I3w(f}CLq#;ger(20U{t$#aBX+UQGy~5(K0uMS4Ot6a_&# zgkF>?U3v{2LJ1|*d*1KP+_^vQy)$>_oY~3Rd)8TJuV=6ItaZW+^tG87co;w+5R=YB zO(PJ9rWLqhmuLZr=YHyCV7Tn|(99E<9|7(#8atM?Oc03IMMqQZiC^l*q>I<{M(tHuG4up@p+nyiLaM#%k&-$z?=A@4ox}-rp*>@!V=SjK_Hji z0W=M0Ms!&M^ivH^qk0v^0P^^a0DXLiqYdJtuz?oR2|-nllRsr2TsHu#lIcLXvOJD@ z6gH{IaPG&C^$p8!394EHf9Z|&F6Yv?pRq{^+WvdKT1O^^FM9b_+dWxDtW3UE!#2#u zU|;jTgv1prjy5DKE)JC(gN$+Av_W;1aam%J?9;|8pEa&8g84E}5S%ng~va=&{ zt8HM|FJrRcN8QVW14-qk8=}~#Wr3x_({q7PGypCV$^)!-SQfG5mmaDD*? zJRoBqW;J$agAuq;#|G?cc@#sWUKrdug|+BFa>3@tgB(DG6lP{DW?b#V)q@eVkou+V z`MMMy`gmN;)FGK(u-ui8J+=>=ox7~noRdW4_Z8rAzgfr^=5)U{~e0W>>c%aaNynjveE%)K35bTRPzY2Ph* zo)hwxXa`}K(8l|O)2-&XZl(4f{sTCaKP5F^GmCtNyUJbD0E-PM zMf$~}a-MZ@;s&s7G<7U zO@N2%a;j&G5e^UjjD9oDSWSpiyz)JW0g9z35fvYkMV~lOWjy!Uv`&v7T9a}-Ec}IE zsIIn!?PFdwWgZ#JrPwjXy(>6*mPy!p;DpDY?p5t~m|3=)r`tsyHq}LU+if5G$PdWC z<44~zF!do0Q%SvDid)VtXkPLA^+^<42e$!~Xny1#?WUhUrbIf^F$C9CaT^y?QX#ea zr07oUTz{Il-3ylq3XKzgMMN~zzE}#M`Dg+{7cJ9cHYkb+oGyK=_AdAi@-xxPZdCVO z^N&<=eSs8e>X5FZJt4_^c@Ec#i;p%av!dI!Xs_+bKtvtbD7cB9Jfxi!7ul6p{sNYdK z6U76?5^gee>qdlGe4g){4vlHLu`Hn%5z}M<3}G?VAsPYEnFJ|Tk@JU!LAWM9u7}V4 zDQsHWI;6Re)1J!`5g%fjEPx?22E`_l|Nb|Ei%}H&x(~rcCyE{ILo7#_r+YOD)rdvkJkf)5oz{h2hi@af1p93kgv;brC=ijcb~}nfF{ev*Q7LRt?w}qK3|_%(BFS zXDyv1L|V+)Z~t|FklJs=&z210irY`fH7J%ZjxC+w#wkk2Mqw+=%AR_o5n#3~VWFn; zCj5kA1=4E>AX-tMCcO;JlQ-0QLNtAj>LTQZ>^Qd}(t{lP5DN1OKMaf-6r&Cd6-kv= zWMfq&zMYzADqFk(##%awRu+gKZDnYDYb3&D&QCCYMv1|V21*A~T$UKD1kZLJj{DL> z=?pd-((>px^@h;wVr_djK~2(GsZd|;T?xrXH9YxyZ?@;T_`QtHrr>JEJ*!V)(s)`} zhr8J0+#0u-DBW!iz#=}8{0gIsMrb{Lq|sU1WQ#w;A;VDFm+<%dsfymLP`XhHRK zjGt%RvBH#gyu!i(tug;tGixH8hWsQpiOmDhIn_o=iW9jm54=^gd}5WGR}m!YfM%dz zzX@8}=pXJVmC2K|%73ugn|)dRv_C zGb9Gp$*iQhGuFV|I_!R|gV*ml4gB?TzVvL3UiCCR;S-mz1>b=eP^=fuyb$tAsS#h2vsOpj8& zMLX0hYs~ryN(qa@-}Lt{CpLSZlDj9RwO&)F+QJ&umi1 z>E@?vVELg5S1oXz$B)KT{ufvldGavRmCAxKq1+xzL6tw86t>?uiASr4=V^jb)Dv|F zH;*v|5^0guQe!P4ci;8;ll+yVD`B`yA1=em=ixE=Co9Fhg%kE$@6)pQyT+bzn8N^cFB-#H-$h3ztq=w!ogU&ED&oT@p7x9``MWJU~Exco#QHf7H5t=&UeG) zRBZ1N%r0%aX%6q7Jay)LY4JI9bV5J$ zSphXN_jQ=`r%n%LqQHf_eOR=3<$R?H0K8wdS=s*_hU|=NSk&6F8=WcDxXW)=pdY}Z z%X2X-KNS1H|7827UA-GKJe{Dr@#IEc7^$8(tJ4mTjOgJKh^HQ{9`C>B%p#~h zR#Yst{xszDYCWUQ;>=kSECc+BV=RIAL#q3b5$#t>)Se0Z^ z>2^*k4hFKW?p?GB{`DUOdd@(E;99xF8$w$}};QC*x#X`_XDA z^YsGuMTDQYS?|CP=s31Ab+}NZ8ZJ~aCp(I}%r)Y~1{d?hHvCZ^!jIV( zBCp8TXX+jGHm2z^iotb8U*{J8gXhRhrCBd+xKQl=`x9_NT*UClDi`oDClqT|Wze6@ z*Qb%;n0u`!f>#iVr4E*7M`Xr(z`XAdBSsNaabxed$8aJ1{B4o#vw<#jO!Q}i=eGFGo4#1rAO*Y>XsbyG`2-tWU;;f@+qC6Z=7YZpN( zH#sgY!cphfO&#yIxF)yMgu#)hWv0+<6D+Pt#Nzm~r;(ACAs1kU&=X^$yN-Ghx$!{4 zXCs+|?<%%ZMf1W%NudH_58xTm023vNwk?ElscAfJf@MZULo0;~5-`W#bGrnb^+Sds zRZp)gBiovu1j84@*tMO8mB{w_bx1q(a40k4 zte^xX2@!86qwfaaf}uQGWl2JTKi;s(iqkdi-ADkad}P z(vYiti?pRlE);;##4(MqhtH$@pVx#RJn;*rKafi9V-_6qIYa$~IZ-?DMbt)dR@mlH zx$4M+m1vy0Q-09S4Fws;sdR;13v}PgM~rTOVds7%WU`VscWhv~*O8sW*_6PGVn{Rg zcX7|bzwM*&oRFde4<@ZY*0(0VF2qF3i5u6*enmT>1HP8)4lqHnZ=|Y|TUQDm3swg% zzhd>Eu6b_IW0A~Pdmr7p$-Mk?`3gS=K@i0-Z|fy{d+nf30XMqDsgXcd;a@=(?_XBh zo}T+{Yz7_w%UWl>L`7kF5jf<)e!{L}{yyDy846T%ZQRYCHG3@+8_e>lEbvZ+~s#d(ON~XV$$4Md1nIV{^Nx1Gv&L8l~eX#Kh0HC5hSGXDleWD60 z-2owN$UvLIHr2p}yvX5yo+X+@G({eKcYTfgQ-Ux}KASISykD4K?x%-m1y+6O@7p_l z%cM?5(tYjS*taF$*~h^~oY3~fm;-t7)ynKK;V(VgXE*&6Nyq1DTiU`2qy^D7g){B> z_}e|prhsYhU%*VQt}^sm#j+M{^H_YTt%yv#-|o*Kn3)VW))}%vrPb{u8TVoijqu%R z$#|$w-6W7=pr=ZY)O4IeaZSF8zY3Pdjz-@I6){<)SyLL;3ci@sSJ1EwBm=Qnu{{Lk z;$<0dZ&qFe!3eI1+oOYOEAHv(IYr@`I;-|IZ;fb;0A%t(fK)Hl)Jj>D^r7gu)YZem z;{+@+ZQAm5l@`SSF+G!^oj}C)$&$Mr_5)3fhfL`Uzs;NOZ?=({qdWXF4me)y#}yC0 zq_Dx%Z242I2PLPUJ}}0^{|tL?l7m@N^u0Dl%V(OU@%6=a;a{;;(J|FwI9eC?M7VY? zEGK`pKhINTOlIP2bacEe@T5f??mbOZ$ij==@(zi41Z098rH1Dkfz=2|G8ub-JpkJ4`O#h1Ja-UXA%F8b_-LhppCr8?+waIJvsr zMucg~rV6{6-QMxQi$FmhcRhk}GanG=&0#9a>E2uMzmG)s@7&?xSh9LmHZx;0gp2l7 zltQ-u*`OA8bS|-$i~3B~%hvz!al(!Q&s>@S*SJPpx?1hN>L@b=(-4WWtTCPzKnS%U z=|k@2qIEy)HI@R}*Mw7WWX{h@qOen3w<|i}6~L;5G(TvKfaB$iHeRn;@k2Q-4FFw( zBB$v?qn_4b5fzNnI?}bAsp_Og`uw{3q4`(ej==$~q#^5Qx~6;osMHEL`g}USatlv= zHD}${E->g0m4YlHW?*y)=A~DwY|G4OPdc99caG1|`9VNRJuC$Xi6Ggd!Tm!$e#q{J z#m&nOt8UCenO12^JYc3p4fyQ9rr9aIPnXX`zt~}iylJxYueIx_KsZpc-}$j~N{a-z z9KQU-UfrUg$@+?A-MQD_L4juV-zVO7-We7ogMrxlMztsF$|W1zQJ z?SY7oR$K4yn!107dlBFoo^lI52Qo*bmQwnD3gw%ak({uzl=X*A|!aK56%j z&1G`Te7iDcEWV0xPYubjKZib9foN4GsT27&T>{2ic z>XFuD%Y!=&L8Y5{^DBnOy7{YD!HzT+GrZyPUM629b>guy7lN!Pic_Y>va*V;KNI!< z9l$ao46zCTuFX1*rahGegi_8>d)%_)utxz zGF^c1D;otm6{{6KJy$?u0IMa}Jd`D_ri@&+JYZT+ByReh9L-M#vq(gPE4@SxPrJi( z@wghocZA2-Q=yiv+%D}G%$q9wRa?Is5{_SO4xV&572r$)s9&#Hmon7t%*AkepA;Fe z8^ig3IT!5ku8ccHy-BCZnt+fV?$x6)+9S)0$P!4Yv8`nA!)Mg>Mb5yzx`(fxomXE6 z4&@hC%M{t0n^V;Wm->V#O@*$R8}%o|NY;ZhigVg}b(JV?N&e(`D4w_!d*u zBwxi}N7I<2hVk2X+3YVz5Tt}HG~8qUP81W6t| zcj9&YRNm-lLc-}X@^r-f+p5c0$9dkAOPSeijuc9(eb|R*s*e+E2$BL&87akpk(sUa zoFwMULa*dLSYtJx{j+uxSv)Fv<=bNGMxm;4Z9XAt0mq#<_5z9j&T1{Nmcw^uO*F1| zCmvs&eXqs0`{OB=g1ahdYL%nj<;j_5FazV4MEp-z9DI|uHzl~{aX(?v;NNWvztjnlOW=krx@uWOShoL zdDNsgNOTUF6eWzO!ZL@1!BiV@2>I#O5}UfMfOQw z@gRu7*~951po@E9Wr3=wPx?KUg=uZ7qkdv%rM1ZZcv@8+th}i8BjrOCUXUl9&?BWc z6#SKdeNBO<;M6ZrN;!TOq+RsPX_;5;W}km8A0HGy6c8D2iiHh zAnITt!GR77T<@Bj;}V`f=Bb|`B+#4CffnaGjt>SH7~+}FPW%#>s$Lt7TmadTmUfE# zvk{t0pSzLHk76r%KvIwq^wC&)K;T3fe9j2eFle#9!pnT1g0QH)Cu6?p2x_PWBp*Ys z_MRfK6FH!uysG{I6&0AB<<*1?&b0zMuaF3RD(S4B(v}wAAgI(vZ5)&U`)ujO; z3MNkpD*n0J$8AEVO=I4e^qdmXJ`r6%`PpUqx&JFl_}BS->%G;6y87v=_HHa~P~%V` z0l%q2Svk|t_c^qBQkhTa6>sr%6j<%(2Q@sgs6Q_?A{1JsDE=KZ|CxaHIo>Xj^$6qy zN!|DbeXKvuKaiPpN?Ln&v}koZ=GYt*Bn{}J%7~MC{U@m~?Osd2WAwYYXaXe^?Y<(( znQ#&G#b}&bienK}nif%X_B|M8z9eK9$yFjt&MsiQ0E*3XhJO&Tv-YiP&rQtbr^5=u zx#T79d$g@as)vTTr&(GGfD*Nw(T)W^(bCd}yFMFhzq7YPCj5n32B0;2_5&R`Wi&xa zKgkZ8t(l`)@6+n7P|Nj5EDNT2>`S2Mf6hLvtAhk5RybK(2A-QVGC9kQL$t5_f>f7? zr5qq=wgPsR5JH;I)Sf>ym|;e>VE>{MBW(CQHv`$+7g$*df1%h8VJo}pQd+Q8%IHK3 zlF9dm?;`bm{nG^TaljR*dirAq&c;qRba|`d>4Z68a0ufPd`bvGcX;J2QZSj;PnEbo`~_m&V&<32Uqq8r1O>RbzJD37F?A{8ToKNE{%ASU zFe7rvdX@wu?&FT+L^0OtHFCgPxnl%_Ai0zNj%Cl9V`5EVLj3_^CPge^GM&u3H9aSr ze&>5?7~RbY>WSMImbrwKfu`hO#M{??Ao8aR?sD3RLB%y)g+eY11^o@;OhXpUrH2FMX@-%gG43xOn8x0CM}+`KcjjCguP7e)Zp&!hey8 b6G6rsB3QEI#~9#q97yMZzGk7i&D;L~-6|Fh literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/3dsketch_angle_abs.png b/doc/salome/gui/GEOM/images/3dsketch_angle_abs.png new file mode 100644 index 0000000000000000000000000000000000000000..ff81225b757c15cb1567fdc6dc592d31b53254a0 GIT binary patch literal 6087 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/3dsketch_angle_height_rel.png b/doc/salome/gui/GEOM/images/3dsketch_angle_height_rel.png new file mode 100644 index 0000000000000000000000000000000000000000..333cc19e9fee2c5d8fce61b0ba8956e0e2f1652c GIT binary patch literal 6997 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 H>(~Deaz@D4 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/3dsketch_angle_rel.png b/doc/salome/gui/GEOM/images/3dsketch_angle_rel.png new file mode 100644 index 0000000000000000000000000000000000000000..f57c097a42a0435177ab0b7dff055f3b780266b2 GIT binary patch literal 6157 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 G-~IzPqV%r- literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/3dsketch_dlg.png b/doc/salome/gui/GEOM/images/3dsketch_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..2edb64da6f280f83f8d1b7eac01b639a91e2c2b6 GIT binary patch literal 36260 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/fused_wire.png b/doc/salome/gui/GEOM/images/fused_wire.png new file mode 100644 index 0000000000000000000000000000000000000000..108f33fc5727707ad1d7892773e64fa3535ff945 GIT binary patch literal 1399 zcmeAS@N?(olHy`uVBq!ia0y~yVEhPV&*fkOlG=jT_5&%-0*}aIp!{_p?qp08c)f^$ zfmPGf#WAE}&fB}bMYr8VS_8LeM{ikWbo$p4S0&~E6JIAIpGVKX9<@{s^_psO@vQ&a z^rKmiE%+E*eiVLTVuzTa2y3Z!9e7@|QvwIISU(Kj0EjQHN z8oxbTd#izkuJ8I4$HU^T-#Oi+IB8k<#pL7ZNB0Q4n7B+{=XcfW_Zy6T?cK^wrO*AK zdibA7t-an_;llQ}8NcL~byZ#|w-Jk&yDa}iYYC@6XV{bX)i+(T*KRedv#PRO8aw~e zmkWJyd^+F4KJNInoAKI{Q$M?2F05?(z_odLsRZx(bIMEC?Uw#ky)byyOZ~!?cV?;k zSmwVK`gok5%fP>WQs+-QpW7>+uCAFrb8Yso_}y!NUd*->OkKXtX!@6fZ=SB7@j)z6 z+2X)^^N-&Qc@7)=tNF2I@$YpnyE{A_&03lFY<*ZeXJ7FDT)yD6CGXND|2tTm+V%IQ zyYvyeTgMHyw689hnfPnL%liV|dK%Wdf0o+ThdiESH)HP^p$@;B7G_2DTmIBk>ANU4 z_@=ntmtAgT{3SX~U))LHuu0q2EypibR{mXEQF`ys!5qEwFTX#Tv+L#GJn8zQZkuD? zFMqnk_kHc{iYDLZ{Z%sC?!5fRYNMENyJFTRW9?@Nb5`dW-aghnhh^O%zQd8T^`BN>(V-}=%nmhrTso)T7jRRYW42q+4J`1<{X^aS>C35E~n~M zdFY!5Jo&$ctpgOC-{7pPI95e(v)djm}rM7U#u#T;`3wanADcg{{W< zk>53KK0n*2uD+Ig+sgOLcF)^vd{X1|HJ_^7MSmYV^u=p#dmJ|1x7>Dllcs9(ESV#p z=U^B-M5 zwitc>l6~Ah*6izZ$JdRfJ@b2RO*b&CkG)v=YklQu@%lKf+L`AzXaCmePjzKY)8}6O zx9*EoqHP*?^OXF>4wu!pZ=Sy1u1#nAGf*H(xIi_?3X`aow{c^^Z8pDT>2t=K{-CP?j38x z^vr?D@Kh;ejxT-re_Ppa|J(Js?3 NgQu&X%Q~loCIHp@n==3a literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/iges_unit.png b/doc/salome/gui/GEOM/images/iges_unit.png index 60aba603ad83270687dedd20473e3b4036efca92..cb74fb319fb952aabef33c434e827b0b76a211e5 100644 GIT binary patch literal 10444 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 LQkJY1HwpPaWbivn literal 6488 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/pipe_path_dlg.png b/doc/salome/gui/GEOM/images/pipe_path_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..e2f969d8c56f9707f73cc59ceb4cfdf57748aa65 GIT binary patch literal 24830 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 literal 0 HcmV?d00001 diff --git a/doc/salome/gui/GEOM/images/wire_before_fuse.png b/doc/salome/gui/GEOM/images/wire_before_fuse.png new file mode 100644 index 0000000000000000000000000000000000000000..0a339796454edf1a612f85e8c5ee24390a017992 GIT binary patch literal 1451 zcmciC`#aMM90%|(9;ePi(g~&2>Ea=(xvZ6#%fWFSb2+(gx)`}V6Nb@DJsoRDZF-Uo zvuc=57l};HHgt3%w_!6Ovc#H|k&R5&*&lFzJ^k=`f8NjY{{2Np2Kg9*c7Xr@F!b~F z3Izb2C2g=5Nc)FT19CJ%T?C*5`TJ^sxlF+4_J-jRw_{f1GMXxJJ)! z)>*fb)nTbNas4~lj8zWx%i3O$T`;kPymm5h;?LRWw%$JRv5m*z(TnnPJFhl|MU*4d z@hhJr0&|NSj8mtjK|Df`5ZaGTbmQRO9@{v&KeWXAjGiJ*P0yi5SC)27rn@^R;lshIUFOFP7cD09q;2`ANMmO!-6eF1yceb``W zchaaJcd<03dYOu^sCOasn1?nQw*`}Vd*>cc=8fK#$6Jr}f+v(8F*Dm*&}9o1ve3%E@@x;XTr9PlMFRijMFG=t&>Oy92}o zkPq5L{N7)F88gq7aik9e9eNs}&V1OA`pG_8+@Z3WNE)IAUU#|E0*Sg_nXZA%AEqpn z9O}ljI#_)*vvgC;_SDs|3taX16R5IJy<*aKd3q6U+Kj-XiY6UY;QC;i{2gO>eMcof zR{hXYn3;FbQ{ZS%bgzwN67?G(NAG0bSDLS0-D>L??6%&=+hDb&Ww|t5St|}%hX?lE zj>uwa;MgTpht~t#OQGDN8^13Slj9x26Bl%opWqTJ;h*IFRW2S}A1mB*~DWBypH3e{m(x&Tv5 zg43C25pV51Nsd+%E1>pPDfOVu?vd$af$$Q
  • Each element of the compound should be a Block (6 faces and 12 edges);
  • -
  • A connection between two Blocks should be an entire quadrangle face or an entire edge;
  • +
  • Blocks can be connected only via an entire quadrangle face or an entire edge;
  • The compound should be connected;
  • -
  • Two quadrangle faces should be glued.
  • +
  • Each couple of connecting quadrangle faces should be glued.
  • \n Informs of the following possible errors: diff --git a/doc/salome/gui/GEOM/input/creating_3dsketcher.doc b/doc/salome/gui/GEOM/input/creating_3dsketcher.doc index 651ebc461..6c44c25da 100755 --- a/doc/salome/gui/GEOM/input/creating_3dsketcher.doc +++ b/doc/salome/gui/GEOM/input/creating_3dsketcher.doc @@ -5,27 +5,24 @@ 3D Sketcher allows creating a closed or unclosed 3D wire, made of consequent straight segments. +Example: + +\image html 3dsketch4.png + To create a 3D Sketch, select in the main menu New Entity -> Basic -> 3D Sketch. -\image html 3dsketch2.png +\image html 3dsketch_dlg.png -The first sketcher point can be defined by \b Absolute coordinates X, Y and Z. +The first point of a sketch can be defined by \b Absolute coordinates X, Y and Z. When the first point is defined, it is possible to add straight segments. -Each segment will start at the end point of previous segment or at the -sketcher first point, if there are no validated segments. - -Segment can be defined by: - - \b Absolute coordinates X, Y and Z of its second end, - - \b Relative coordinates DX, DY and DZ of its second end with - respect to the previous applied point, - - \b Direction and \b Length of the segment. Direction is set by two - \b Angles in selected coordinate system. +Each segment will start at the end point of the previous segment or at the +first point of the sketch, if there are no validated segments. The way of segment construction can be selected by the Coordinates Type radio buttons. -To validate the segment and to proceed with the definition of the next -segment, click Apply button. \b Undo and \b Redo buttons, +To validate a segment and to proceed with the definition of the next +one, click Apply button. \b Undo and \b Redo buttons, respectively, remove or restore the last segment in the wire. \n "Sketch Validation" button applies the wire, built by the @@ -33,9 +30,37 @@ user, "as is". \n "Sketch Closure" closes the Sketch by a straight line from the start to the end point and applies it. -Example: +A segment can be defined by: +- Cartesian coordinates of its second end, which can be either: + - \b Absolute coordinates X, Y and Z, or + - \b Relative coordinates DX, DY and DZ with + respect to the previous applied point, + +- Angular coordinates of its second end specified by: +
      +
    • the \b Length of the segment and an \b Angle in the chosen plane (OXY for example) in \b Relative mode. + The angle is then relative to a local coordinate system with the last point of the sketch as origin.
    • + + \image html 3dsketch_angle_rel.png + +
    • the \b Radius (i.e. the distance from the origin) and an \b Angle in the chosen plane in \b Absolute mode
    • + + \image html 3dsketch_angle_abs.png -\image html 3dsketch1.png + In both angular modes you can additionally specify the following: + +
    • the second \b Angle (latitude)
    • + + \image html 3dsketch_2angles_rel.png + + or + +
    • the \b Height
    • + + \image html 3dsketch_angle_height_rel.png + + +
    TUI Command: geompy.Make3DSketcher( [ PointsList ] ) This algorithm creates a wire from the list of real values, which diff --git a/doc/salome/gui/GEOM/input/creating_adv_obj.doc b/doc/salome/gui/GEOM/input/creating_adv_obj.doc deleted file mode 100644 index 648a18ae9..000000000 --- a/doc/salome/gui/GEOM/input/creating_adv_obj.doc +++ /dev/null @@ -1,14 +0,0 @@ -/*! - -\page create_adv_obj_page Creating Advanced Geometrical Objects - -New Entity -> Advanced submenu allows to create additional complex topological objects. - -
      -
    • \subpage create_pipetshape_page
    • -
    • \subpage create_divideddisk_page
    • -
    • \subpage create_dividedcylinder_page
    • - -
    - -*/ diff --git a/doc/salome/gui/GEOM/input/creating_complex_obj.doc b/doc/salome/gui/GEOM/input/creating_complex_obj.doc index 0d0404336..46c4baa90 100644 --- a/doc/salome/gui/GEOM/input/creating_complex_obj.doc +++ b/doc/salome/gui/GEOM/input/creating_complex_obj.doc @@ -14,7 +14,7 @@ axis, creating a body of revolution.
  • \subpage create_filling_page "Create a surface" from a set of edges.
  • \subpage create_extrusion_alongpath_page "Extrude an object along a path", creating a more complex trajectory object.
  • - +
  • \subpage create_pipe_path_page "Restore Path" of a pipe-like shape.
  • */ diff --git a/doc/salome/gui/GEOM/input/creating_compound.doc b/doc/salome/gui/GEOM/input/creating_compound.doc index ad1a899fe..ecb165584 100644 --- a/doc/salome/gui/GEOM/input/creating_compound.doc +++ b/doc/salome/gui/GEOM/input/creating_compound.doc @@ -22,4 +22,8 @@ Entity - > Build - > Compound
    . Our TUI Scripts provide you with useful examples of creation of \ref tui_creation_compound "Advanced Geometric Objects". + More details: + +Perhaps you ask yourself : \ref partition_explanation "What's the difference between partition, compounds and fuse operation ?" + */ diff --git a/doc/salome/gui/GEOM/input/creating_dividedcylinder.doc b/doc/salome/gui/GEOM/input/creating_dividedcylinder.doc index 169666a39..14a1eb36a 100644 --- a/doc/salome/gui/GEOM/input/creating_dividedcylinder.doc +++ b/doc/salome/gui/GEOM/input/creating_dividedcylinder.doc @@ -2,11 +2,11 @@ \page create_dividedcylinder_page DividedCylinder -The Divided cylinder object is a cylinder divided into \b blocks for easy hexaedral meshing.Two division patterns are available : +The Divided cylinder object is a cylinder divided into \b blocks for easy hexahedral meshing. Two division patterns are available :
      -
    • A square pattern which is frequently used
    • -
    • An hexagonal pattern which ensures a better mesh quality and especially less acute or obtuse angles
    • +
    • A square pattern, which is frequently used;
    • +
    • A hexagonal pattern, which ensures a better mesh quality and especially less acute or obtuse angles.
    \image html dividedcylinder.png diff --git a/doc/salome/gui/GEOM/input/creating_divideddisk.doc b/doc/salome/gui/GEOM/input/creating_divideddisk.doc index 2d471e6a1..6b6011b17 100644 --- a/doc/salome/gui/GEOM/input/creating_divideddisk.doc +++ b/doc/salome/gui/GEOM/input/creating_divideddisk.doc @@ -2,15 +2,15 @@ \page create_divideddisk_page DividedDisk -The Divided disk object is a disk divided into \b blocks. It means that it's a shape prepared for hexaedral meshing. Two division patterns are available : +The Divided disk object is a disk divided into \b blocks for easy hexahedral meshing. Two division patterns are available :
      -
    • A square pattern which is frequently used
    • -
    • An hexagonal pattern which ensures a better mesh quality and especially less acute or obtuse angles
    • +
    • A square pattern, which is frequently used;
    • +
    • A hexagonal pattern, which ensures a better mesh quality and especially less acute or obtuse angles.
    -\n Moreover this shape can be used as a basis in an \ref create_extrusion_alongpath_page "Extrusion along a path" operation in order to obtain any tube shape prepared for hexaedral meshing +\n Moreover, this shape can be used as a basis in an \ref create_extrusion_alongpath_page "Extrusion along a path" operation in order to obtain any tube shape prepared for hexahedral meshing (see example below). (Another alternative is to create a 2D mesh on the divided disk and create a 3D mesh by extrusion in the SMESH module.) @@ -21,13 +21,13 @@ Example: To create a Divided Disk in the Main Menu select New Entity - > Advanced - > DividedDisk -\n Then there are 2 ways to create a Divided Disk in 3D space. +\n There are 2 ways to create a Divided Disk in 3D space. \n For both operations : Specify the parameters of the DividedDisk object creation in the opened dialog box and press "Apply" or "Apply & Close" button. The result of each operation will be a GEOM_Object. -\n First way : by radius and orientation (plane "OXY", "OYZ" or "OZX"). The resulting disk is located at the origin of coordinates +\n At first it is possible to define a disk by its radius and orientation (plane "OXY", "OYZ" or "OZX"). The resulting disk is located at the origin of coordinates TUI Command: geompy.MakeDividedDisk(Radius, Orientation, Pattern) @@ -38,7 +38,7 @@ The result of each operation will be a GEOM_Object. \image html divided_disk_dlg.png -\n Second way : by giving its center, normal and radius. +\n At second the disk can be defined by its center, normal and radius. TUI Command: geompy.MakeDividedDiskPntVecR(Center, Vector, Radius, Pattern) diff --git a/doc/salome/gui/GEOM/input/creating_hexaedral_solid.doc b/doc/salome/gui/GEOM/input/creating_hexaedral_solid.doc index fbfa2dc3d..d08eeb91d 100644 --- a/doc/salome/gui/GEOM/input/creating_hexaedral_solid.doc +++ b/doc/salome/gui/GEOM/input/creating_hexaedral_solid.doc @@ -2,33 +2,30 @@ \page create_hexa_solid_page Hexaedral solid -\n Description: Builds a hexahedral solid. either of the below -mentioned arguments. This operation allows to build a solid bypassing -the intermediate stage of building a shell and 4 faces (in the case of -building by 2 faces) or just a shell (in the case of building by 6 +This operation allows to build a hexahedral solid bypassing +the intermediate stage of building a shell and 4 faces (in case of +building by 2 faces) or just a shell (in case of building by 6 faces). +There are 2 algorithms to create a hexahedral solid in the 3D space. \n The \b Result of the operation will be a \b GEOM_Object (solid). -\n TUI Command: -
      -
    • geompy.MakeHexa2Faces(F1, F2), where F1 and F2 are faces -from which the hexahedron is constructed, other four faces are created -automatically.
    • -
    • geompy.MakeHexa(F1, F2, F3, F4, F5, F6), where F1 — F6 are six faces from which the hexahedron is constructed.
    • -
    +Firstly, you can define a Hexahedral Solid by two faces, other four faces are created automatically. -\n Arguments: -
      -
    • Name + 2 Faces, or
    • -
    • Name + 6 Faces.
    • -
    - -\n Dialog Box: +TUI Command: geompy.MakeHexa2Faces(F1, F2), +Arguments: Name + 2 Faces. \image html block4.png +\n Example: +\image html image181.png +
    Hexahedral Solid built on the base of two Faces
    + +Secondly, you can define a Hexahedral Solid by all six faces. + +TUI Command: geompy.MakeHexa(F1, F2, F3, F4, F5, F6), +Arguments: Name + 6 Faces. \image html block5.png @@ -37,9 +34,6 @@ automatically. \image html image180.png
    Hexahedral Solid built on the base of six Faces
    -\image html image181.png -
    Hexahedral Solid built on the base of two Faces
    - The created blocks can be processed with \ref blocks_operations_page "Operations on Blocks". diff --git a/doc/salome/gui/GEOM/input/creating_pipe_path.doc b/doc/salome/gui/GEOM/input/creating_pipe_path.doc new file mode 100644 index 000000000..52a2e5403 --- /dev/null +++ b/doc/salome/gui/GEOM/input/creating_pipe_path.doc @@ -0,0 +1,44 @@ +/*! + +\page create_pipe_path_page Restore Path + +To generate a \b Path in the Main Menu select New Entity - > Generation - > Restore Path + +\image html pipe_path_dlg.png + +\n To obtain the \b Path of a pipe-like shape, you should define the +Pipe-like shell or solid and two pipe \b Bases, which can +be defined by a wire, a face or a list of edges.
    +\n Select unpublished edges checkbox - if checked, allows +selecting in the viewer the edges, that are not published in the Object +Browser.
    +\n The \b Result of the operation will be a GEOM_Object (edge or wire).
    + +\n Advanced options: +
      +
    • \ref preview_anchor "Preview"
    • +

    + +\note It is not always possible to obtain an exact or approximate + copy of the Shape by applying the \b Pipe operation to the + resulting "Path" wire with the first Base as the base; + though in some particular cases it might + work. Thus, Restore Path function should not + be considered as an exact reverse operation of the Pipe.
    + +\n Example: + +\image html pipe_path.png "Path (red) between two faces (green)" + +\n TUI Command: geompy.RestorePath(aShape, aBase1, aBase2) +\n Arguments: Name + 1 pipe-like shape (shell or solid) + 1 +shape (edge, wire or face) for the first base + 1 shape (edge, wire or +face) for the last base. +\n TUI Command: geompy.RestorePathEdges(aShape, listEdges1, listEdges2) +\n Arguments: Name + 1 pipe-like shape (shell or solid) + 1 +list of edges for the first base + 1 list of edges for the last base. + +Our TUI Scripts provide you with useful examples of creation of +\ref tui_creation_pipe_path "Complex Geometric Objects". + +*/ diff --git a/doc/salome/gui/GEOM/input/creating_quadrangle_face.doc b/doc/salome/gui/GEOM/input/creating_quadrangle_face.doc index 1aa7c91f8..63d2e9494 100644 --- a/doc/salome/gui/GEOM/input/creating_quadrangle_face.doc +++ b/doc/salome/gui/GEOM/input/creating_quadrangle_face.doc @@ -2,39 +2,45 @@ \page create_quadrangle_face_page Quadrangle face -\n Description: Builds a face using the below mentioned -arguments. This operation allows to build a face bypassing the -intermediate stage of building edges and wires (in the case of -building by 4 points) or wires (in the case of building by 4 or 2 +This operation allows to build a face bypassing the +intermediate stage of building edges and wires (in case of +building by 4 points) or wires (in case of building by 4 or 2 edges). -\n The \b Result of the operation will be a \b GEOM_Object (face). +There are 3 algorithms to create a Quadrangle Face in the 3D space. +\n The \b Result of each op -\n TUI Command: -
      -
    • geompy.MakeQuad4Vertices(V1, V2, V3, V4), where V1, V2, -V3, V4 are four vertices from which a face is constructed. Edges are -created automatically.
    • -
    • geompy.MakeQuad2Edges(E1, E2), where E1, E2 are edges from -which the face is constructed, two other edges are created -automatically.
    • -
    • geompy.MakeQuad(E1, E2, E3, E4), where E1, E2, E3, E4 are -four edges from which the face is constructed.
    • -
    +The created blocks can be processed with \ref blocks_operations_page "Operations on Blocks". -Arguments: -
      -
    • Name + 4 Points, or
    • -
    • Name + 2 Edges, or
    • -
    • Name + 4 Edges.
    • -
    +Our TUI Scripts provide you with useful examples of +\ref tui_building_by_blocks_p -\n Dialog Box: +The created blocks can be processed with \ref blocks_operations_page "Operations on Blocks". + +Our TUI Scripts provide you with useful examples of +\ref tui_building_by_blocks_page "Building by Blocks". +age "Building by Blocks". +eration will be a \b GEOM_Object (face). + +Firstly you can define a Quadrangle Face by four vertices. Edges are +created automatically. + +TUI Command: geompy.MakeQuad4Vertices(V1, V2, V3, V4), +Arguments: Name + 4 Points. \image html block1.png +Secondly, you can define a Quadrangle Face by two edges, while the other two edges are created automatically. +TUI Command: geompy.MakeQuad2Edges(E1, E2) +Arguments: Name + 2 Edges. + \image html block2.png +Finally, you can define a Quadrangle Face by four edges. + +TUI Command: geompy.MakeQuad(E1, E2, E3, E4),. +Arguments: Name + 4 Edges. + \image html block3.png \n Example: diff --git a/doc/salome/gui/GEOM/input/creating_sketcher.doc b/doc/salome/gui/GEOM/input/creating_sketcher.doc index 7aa11153a..922f2a6aa 100644 --- a/doc/salome/gui/GEOM/input/creating_sketcher.doc +++ b/doc/salome/gui/GEOM/input/creating_sketcher.doc @@ -27,7 +27,7 @@ To create a 2D Sketch:
  • Select the \b plane or the planar face on which to create the sketch. \note By default the sketch is created on the XOY plane of the global coordinate system. If Local Coordinate Systems have been created in the study they appear -in the combobox and can be selected as a reference coordinate system.
  • +in the combo-box and can be selected as a reference coordinate system.
  • Choose a \b segment or an \b arc element to start a \b profile or choose \b rectangle to draw a rectangle. @@ -50,7 +50,7 @@ origin of the reference coordinate system.
  • You can define the segment by either its end point or \b direction and \b length. The direction is defined relatively to the tangent at the last point of the sketch. It can be:
      -
    • Tangent (colinear to the tangent at the last point)
    • +
    • Tangent (collinear to the tangent at the last point)
    • Perpendicular
    • Defined by an angle
    • Defined by a vector (Vx, Vy)
    • @@ -159,7 +159,7 @@ points in the current LCS. Our TUI Scripts provide you with useful examples of the use of \ref tui_sketcher_page "Sketcher". -A wrapper also exists to help in the construction of a sketcher using simple commands. +There is also a wrapper that can help in the construction of a sketcher using simple commands. The description of this wrapper can be found in the
      dedicated page of the salome.geom python package. diff --git a/doc/salome/gui/GEOM/input/faq.doc b/doc/salome/gui/GEOM/input/faq.doc new file mode 100644 index 000000000..78fa0d58c --- /dev/null +++ b/doc/salome/gui/GEOM/input/faq.doc @@ -0,0 +1,12 @@ +/*! + +\page faq FAQ ("Frequently Asked Questions") + +Here you can find the answers to some frequently asked questions: + +
        +
      • \subpage partition_explanation "What is the difference between partition, compounds and fuse operation ?"
      • +
      + + +*/ diff --git a/doc/salome/gui/GEOM/input/fillet1d_operation.doc b/doc/salome/gui/GEOM/input/fillet1d_operation.doc index 322b7c965..9893650c5 100644 --- a/doc/salome/gui/GEOM/input/fillet1d_operation.doc +++ b/doc/salome/gui/GEOM/input/fillet1d_operation.doc @@ -18,7 +18,7 @@ vertexes on this wire in the OCC Viewer and define the \b Radius of the Fillet. \b Note: This Operation Works for the Wires with Planar Edges only. \b Note: Use option Fuse collinear edges to allow bigger radius - to allow ignoring of possible secant points, i.e. the + in order to ignore possible secant points, i.e. the joints of collinear edges, thus processing such edges as one. TUI Command: geompy.MakeFillet1D(Shape, R, ListVertexes) diff --git a/doc/salome/gui/GEOM/input/first_steps_guide.doc b/doc/salome/gui/GEOM/input/first_steps_guide.doc deleted file mode 100644 index 17ca4e8c5..000000000 --- a/doc/salome/gui/GEOM/input/first_steps_guide.doc +++ /dev/null @@ -1,12 +0,0 @@ -/*! - -\page first_steps_guide First steps in GEOM - -You can find here some useful information to start working with GEOM - -
        -
      • \subpage partition_explanation "Partition, compounds and boolean operations"
      • -
      - - -*/ \ No newline at end of file diff --git a/doc/salome/gui/GEOM/input/fuse_edges_operation.doc b/doc/salome/gui/GEOM/input/fuse_edges_operation.doc index 7924f73eb..5f6b96343 100644 --- a/doc/salome/gui/GEOM/input/fuse_edges_operation.doc +++ b/doc/salome/gui/GEOM/input/fuse_edges_operation.doc @@ -4,10 +4,20 @@ \n To Fuse Collinear Edges within a Wire in the Main Menu select Repair - > Fuse Collinear Edges within a Wire. -\n This operation removes selected vertices from a given wire in case -if adjacent edges are C1 continuous. The function takes a list of +\n This operation removes the selected vertices from a given wire, +provided that the junction of two adjacent edges is C1 continuous +(i.e. the edges have equal tangents at the junction). +\n The function takes a list of vertices to suppress as a parameter. If the list is empty, all -vertices in a wire are assumed. +vertices in a wire are taken into account. + +\n \b Example: + +Wire with 2 colinear edges: +\image html wire_before_fuse.png + +Fused wire (only one edge): +\image html fused_wire.png \n Arguments: Name + a wire + a list of vertices (can be empty). diff --git a/doc/salome/gui/GEOM/input/fuse_operation.doc b/doc/salome/gui/GEOM/input/fuse_operation.doc index 4dd3a7bf5..df13c732e 100644 --- a/doc/salome/gui/GEOM/input/fuse_operation.doc +++ b/doc/salome/gui/GEOM/input/fuse_operation.doc @@ -2,24 +2,11 @@ \page fuse_operation_page Fuse -For detail description of the Boolean operations please refer to -this document. -It provides a general review of the Partition and Boolean -operations algorithms, describes the usage methodology and highlighs -major limitations of these operations. - To produce a \b Fuse operation in the Main Menu select -Operations - > Boolean - > Fuse - -This operation creates a shape from two shapes. +Operations - > Boolean - > Fuse. +This operation creates one shape from two shapes. The \b Result will be any \b GEOM_Object. -TUI Command: geompy.MakeFuse(s1, s2) -Arguments: Name + 2 shapes. -Advanced option: -\ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". - -\image html bool1.png Example: @@ -27,7 +14,24 @@ The \b Result will be any \b GEOM_Object. \image html fusesn2.png "The resulting fuse" +TUI Command: geompy.MakeFuse(s1, s2)\n +Arguments: Name + 2 shapes.\n +Advanced option: +\ref restore_presentation_parameters_page "Set presentation parameters and sub-shapes from arguments". + +\image html bool1.png + Our TUI Scripts provide you with useful examples of the use of \ref tui_fuse "Boolean Operations". + More details +
        +
      • For a detailed description of the Boolean operations please refer to +this document. +It provides a general review of the Partition and Boolean +operations algorithms, describes the usage methodology and highlights +major limitations of these operations.
      • +
      • Perhaps you also ask yourself : \ref partition_explanation "What is the difference between partition, compounds and fuse operation ?"
      • +
      + */ diff --git a/doc/salome/gui/GEOM/input/get_non_blocks.doc b/doc/salome/gui/GEOM/input/get_non_blocks.doc index 8df0e324c..1bf4806b3 100644 --- a/doc/salome/gui/GEOM/input/get_non_blocks.doc +++ b/doc/salome/gui/GEOM/input/get_non_blocks.doc @@ -4,18 +4,18 @@ \image html measures2.png -Retrieve all non blocks solids and faces from the given shape. -Collect them in two groups: solids and faces separately. +This operation retrieves all non block solids and faces from the given +shape in two groups: solids and faces separately. -\n Result: Two or less groups are published in the Object - Browser under the processed object. Reports error if - no bad sub-shapes (solids and faces) have been found. +Two or less groups are published in the Object +Browser under the processed object. An error is raised if +no bad sub-shapes (solids and faces) have been found. \n TUI Command: geompy.GetNonBlocks(Compound). Returns a tuple of two GEOM_Objects. The first object is a group of all non block solids - (= not 6 faces, or with 6 faces, but with the presence of - non-quadrangular faces). The second object is a group of all non + (not having 6 faces, or having 6 faces, but some of them + are not quadrangular). The second object is a group of all non quadrangular faces. See also a \ref tui_get_non_blocks_page "TUI example". diff --git a/doc/salome/gui/GEOM/input/import_export.doc b/doc/salome/gui/GEOM/input/import_export.doc index 70537f934..62a80da55 100644 --- a/doc/salome/gui/GEOM/input/import_export.doc +++ b/doc/salome/gui/GEOM/input/import_export.doc @@ -22,10 +22,10 @@ Select the required file and click \b Open. Your file will be imported in the module and its contents (geometrical object) will be displayed in the Object Browser. -\note If the selected file is in IGES format and the length is not -expressed in meters, it will be suggested to scale the model into the -metric system (see the picture below). This feature can be helpful if -some wrong units have been written to the IGES file by a +\note If the selected file is in IGES or STEP format and the length +is not expressed in meters, it will be asked whether to take or not these +units into account (see the picture below). This feature can be +helpful if some wrong units have been written to the IGES or STEP file by a 3rd-party software. \image html iges_unit.png diff --git a/doc/salome/gui/GEOM/input/index.doc b/doc/salome/gui/GEOM/input/index.doc index 26928aaac..55a17a230 100644 --- a/doc/salome/gui/GEOM/input/index.doc +++ b/doc/salome/gui/GEOM/input/index.doc @@ -4,9 +4,6 @@ \image html geomscreen.png -If you are a new user some general information about GEOM usage are given here: -\subpage first_steps_guide - \b Geometry module of SALOME is destined for: - \subpage import_export_geom_obj_page "import and export of geometrical models" in IGES, BREP and STEP formats; @@ -30,6 +27,9 @@ Geometry module preferences are described in the Almost all geometry module functionalities are accessible via \subpage geompy_page "Geometry module Python Interface" +You can find the answer to some Frequently Asked Questions in this page: +- \subpage faq "Frequently Asked Questions" + Other functions are available in salome.geom python package. \image html image3.png "Example of Geometry module usage for engineering tasks" diff --git a/doc/salome/gui/GEOM/input/partition.doc b/doc/salome/gui/GEOM/input/partition.doc index 9af094e70..dfee4899f 100644 --- a/doc/salome/gui/GEOM/input/partition.doc +++ b/doc/salome/gui/GEOM/input/partition.doc @@ -2,11 +2,15 @@ \page partition_page Partition -For detail description of the Partition operation please refer to +
        +
      • For a detailed description of the Partition operation please refer to this document. It provides a general review of the Partition and Boolean -operations algorithms, describes the usage methodology and highlighs -major limitations of these operations. +operations algorithms, describes the usage methodology and highlights +major limitations of these operations.
      • + +
      • Perhaps you also ask yourself : \ref partition_explanation "What's the difference between partition, compounds and fuse operation ?"
      • +
      To produce a \b Partition in the Main Menu select Operations - > Partition diff --git a/doc/salome/gui/GEOM/input/partition_explanation.doc b/doc/salome/gui/GEOM/input/partition_explanation.doc index 2725784af..5325b37e7 100644 --- a/doc/salome/gui/GEOM/input/partition_explanation.doc +++ b/doc/salome/gui/GEOM/input/partition_explanation.doc @@ -4,15 +4,15 @@ \tableofcontents -It is frequently asked about the difference between the above mentioned operations. It's indeed simple. Lets take the example of a cylinder and a box that you want to join together. +It is frequently asked about the difference between the above mentioned operations. It is indeed simple. Let us take the example of a cylinder and a box that you want to join together. \section sec1 Fuse -The \b fuse operation will make a single solid from the two given solids. It allows you to build complex models by putting simple shapes together. +The \b fuse operation will make a single solid from two given solids. It allows you to build complex models by putting simple shapes together. \image html fuse.png \section sec2 Partition -The \b partition operation will also connect the two solids but it will keep a face at the frontier (in brown on the picture below). The resulting shape will consist in two connected solids that share +The \b partition operation will also connect the solids but it will keep a face at the frontier (in brown in the picture below). The resulting shape will consist of two connected solids that share a face at their frontier. It means that this face is present only one time in the resulting shape and is a sub-shape of both the box and the cylinder. \n This operation allows you to identify different areas in a shape (e.g. different materials) and to ensure a conformal mesh when meshing it later. Indeed the face at the frontier is meshed only once. @@ -21,10 +21,10 @@ a face at their frontier. It means that this face is present only one time in th \section sec3 Compound -When you build a \b compound by using the build -> compound operation you just make an object that contains the two separate solids like in a "bag". +When you build a \b compound by using the Build -> Compound operation you just make an object that contains two separate solids like in a "bag". The two solids remain unconnected. The compound is just a set of shapes, no more. -\n The compound Allows applying operations to a collection of shapes. +\n The compound allows applying operations to a collection of shapes. \image html compound2.png @@ -42,7 +42,7 @@ In the frame of this example we can summarize the following differences:
    • \b Partition
      • \a Result : Two connected solids sharing faces.
      • -
      • \a Purpose : Useful to ensure a conformal mesh of separated areas of your model (fluid / solid , concrete / steel ...)
      • +
      • \a Purpose : Useful to ensure a conformal mesh of separate areas of your model (fluid / solid , concrete / steel ...).
    • \b Compound
        diff --git a/doc/salome/gui/GEOM/input/tui_advanced_geom_objs.doc b/doc/salome/gui/GEOM/input/tui_advanced_geom_objs.doc index 4b9047f34..1d469e9e8 100644 --- a/doc/salome/gui/GEOM/input/tui_advanced_geom_objs.doc +++ b/doc/salome/gui/GEOM/input/tui_advanced_geom_objs.doc @@ -86,16 +86,17 @@ gg.createAndDisplayGO(id_pipetshapefillet_position) \code import geompy import salome +import GEOM gg = salome.ImportComponentGUI("GEOM") # create DividedDisk object -divideddisk = geompy.MakeDividedDisk(100, 50) +divideddisk = geompy.MakeDividedDisk(100, 1, GEOM.SQUARE) # add object in the study id_divideddisk = geompy.addToStudy(divideddisk,"DividedDisk") # display divideddisk -gg.createAndDisplayGO(id_divideddisk) +gg.createAndDisplayGO(id_divideddisk) \endcode \anchor tui_creation_dividedcylinder @@ -104,16 +105,17 @@ gg.createAndDisplayGO(id_divideddisk) \code import geompy import salome +import GEOM gg = salome.ImportComponentGUI("GEOM") # create DividedCylinder object -dividedcylinder = geompy.MakeDividedCylinder(100, 300) +dividedcylinder = geompy.MakeDividedCylinder(100, 300, GEOM.SQUARE) # add object in the study id_dividedcylinder = geompy.addToStudy(dividedcylinder,"DividedCylinder") # display dividedcylinder -gg.createAndDisplayGO(id_dividedcylinder) +gg.createAndDisplayGO(id_dividedcylinder) \endcode diff --git a/doc/salome/gui/GEOM/input/tui_complex_objs.doc b/doc/salome/gui/GEOM/input/tui_complex_objs.doc index 7dcf151c1..2cdcf156a 100644 --- a/doc/salome/gui/GEOM/input/tui_complex_objs.doc +++ b/doc/salome/gui/GEOM/input/tui_complex_objs.doc @@ -623,31 +623,78 @@ from math import pi spring = MakeSpring(50, 100, 2*pi, 1, 5, pi/2) \endcode + +\anchor tui_creation_pipe_path +

        Creation of a Middle Path

        + +\code +import salome +import geompy + +# Create a box +Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200) + +# Get two opposite faces +[Face_1,Face_2] = geompy.SubShapes(Box_1, [31, 33]) + +# Get edges +Box_1_edge_12 = geompy.GetSubShape(Box_1, [12]) +Box_1_edge_22 = geompy.GetSubShape(Box_1, [22]) +Box_1_edge_25 = geompy.GetSubShape(Box_1, [25]) +Box_1_edge_29 = geompy.GetSubShape(Box_1, [29]) +Box_1_edge_8 = geompy.GetSubShape(Box_1, [8]) +Box_1_edge_18 = geompy.GetSubShape(Box_1, [18]) +Box_1_edge_26 = geompy.GetSubShape(Box_1, [26]) +Box_1_edge_30 = geompy.GetSubShape(Box_1, [30]) + +# These three calls to RestorePath return the same result +Path_1 = geompy.RestorePath(Box_1, Face_1, Face_2) +Path_2 = geompy.RestorePathEdges(Box_1, [Face_1], [Face_2]) +Path_3 = geompy.RestorePathEdges(Box_1, + [Box_1_edge_12, Box_1_edge_22, Box_1_edge_25, Box_1_edge_29], + [Box_1_edge_8, Box_1_edge_18, Box_1_edge_26, Box_1_edge_30]) + +# Publish created objects +geompy.addToStudy( Box_1, 'Box_1' ) +geompy.addToStudyInFather( Box_1, Face_1, 'Face_1' ) +geompy.addToStudyInFather( Box_1, Face_2, 'Face_2' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_25, 'Box_1:edge_25' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_22, 'Box_1:edge_22' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_12, 'Box_1:edge_12' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_29, 'Box_1:edge_29' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_18, 'Box_1:edge_18' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_26, 'Box_1:edge_26' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_8, 'Box_1:edge_8' ) +geompy.addToStudyInFather( Box_1, Box_1_edge_30, 'Box_1:edge_30' ) +geompy.addToStudy( Path_1, 'Path_1' ) +geompy.addToStudy( Path_2, 'Path_2' ) +geompy.addToStudy( Path_3, 'Path_3' ) +\endcode +

        Creation of Tangent Plane On Face

        \code import salome import geompy - # Create Vertexes for curve - Vertex_1 = geompy.MakeVertex(0, 0, 0) - Vertex_2 = geompy.MakeVertex(0, 90, 30) - Vertex_3 = geompy.MakeVertex(100, 90, 0) - Vertex_4 = geompy.MakeVertex(-100, 90, 0) - # Create curve - Curve_1 = geompy.MakeInterpol([Vertex_4, Vertex_2, Vertex_3, Vertex_1]) - # Create Face by Extrusion of the Curve - Extrusion_1 = geompy.MakePrismDXDYDZ(Curve_1, 0, 30, -60) - # Make Tangent on this Extrusion (Face) - Tangent_1 = geompy.MakeTangentPlaneOnFace(Extrusion_1, 0.7, 0.5, 150) - # Publish in the study - geompy.addToStudy( Vertex_1, "Vertex_1" ) - geompy.addToStudy( Vertex_2, "Vertex_2" ) - geompy.addToStudy( Vertex_3, "Vertex_3" ) - geompy.addToStudy( Vertex_4, "Vertex_4" ) - geompy.addToStudy( Curve_1, "Curve_1" ) - geompy.addToStudy( Extrusion_1, "Extrusion_1" ) - geompy.addToStudy( Tangent_1, "Tangent_1" ) +# Create Vertexes for curve +Vertex_1 = geompy.MakeVertex(0, 0, 0) +Vertex_2 = geompy.MakeVertex(0, 90, 30) +Vertex_3 = geompy.MakeVertex(100, 90, 0) +Vertex_4 = geompy.MakeVertex(-100, 90, 0) +# Create curve +Curve_1 = geompy.MakeInterpol([Vertex_4, Vertex_2, Vertex_3, Vertex_1]) +# Create Face by Extrusion of the Curve +Extrusion_1 = geompy.MakePrismDXDYDZ(Curve_1, 0, 30, -60) +# Make Tangent on this Extrusion (Face) +Tangent_1 = geompy.MakeTangentPlaneOnFace(Extrusion_1, 0.7, 0.5, 150) +# Publish in the study +geompy.addToStudy( Vertex_1, "Vertex_1" ) +geompy.addToStudy( Vertex_2, "Vertex_2" ) +geompy.addToStudy( Vertex_3, "Vertex_3" ) +geompy.addToStudy( Vertex_4, "Vertex_4" ) +geompy.addToStudy( Curve_1, "Curve_1" ) +geompy.addToStudy( Extrusion_1, "Extrusion_1" ) +geompy.addToStudy( Tangent_1, "Tangent_1" ) \endcode - */ diff --git a/doc/salome/gui/GEOM/input/tui_get_non_blocks.doc b/doc/salome/gui/GEOM/input/tui_get_non_blocks.doc index 6f648f9a0..b83ea9647 100644 --- a/doc/salome/gui/GEOM/input/tui_get_non_blocks.doc +++ b/doc/salome/gui/GEOM/input/tui_get_non_blocks.doc @@ -14,7 +14,7 @@ geompy.addToStudy(box, 'box') geompy.addToStudy(cyl, 'cyl') # make a compound -compound = geompy.MakeCompound([box1, box2]) +compound = geompy.MakeCompound([box, cyl]) geompy.addToStudy(compound, 'compound') # explore the compound diff --git a/doc/salome/gui/GEOM/input/working_with_groups.doc b/doc/salome/gui/GEOM/input/working_with_groups.doc index a09865efa..99b98bac9 100644 --- a/doc/salome/gui/GEOM/input/working_with_groups.doc +++ b/doc/salome/gui/GEOM/input/working_with_groups.doc @@ -3,8 +3,8 @@ \page work_with_groups_page Working with groups Creation and editing groups of sub-shapes of a geometrical object makes -handling sub-shapes much easier. Also some Boolean operations on -groups are available. +handling sub-shapes much easier. Boolean operations on +groups are also available.
        • \ref create_groups_anchor "Create a Group"
        • @@ -142,7 +142,7 @@ The following dialog box will appear: \image html groups_union_dlg.png In this dialog box you should specify the name of the resulting group -and set of groups which will be united. +and select the groups, which will be united.
        • Click the \b Apply or Apply and Close button to confirm creation of the group.
        • @@ -155,7 +155,7 @@ and set of groups which will be united.

          Intersection of groups

          This operation allows to create a new group in such a way that only -sub-shapes that are present in all initial groups together are added to the +the sub-shapes that are present in all initial groups are added to the new one. To intersect groups: @@ -166,7 +166,7 @@ The following dialog box will appear: \image html groups_intersect_dlg.png In this dialog box you should specify the name of the resulting group -and set of groups which will be intersected. +and select the groups, which will be intersected.
        • Click the \b Apply or Apply and Close button to confirm creation of the group.
        • @@ -190,10 +190,9 @@ The following dialog box will appear: \image html groups_cut_dlg.png In this dialog box you should specify the name of the resulting group -and groups which will be cut. +and the groups which will be cut. -
        • Click the \b Apply or Apply and Close button to confirm creation of the -group.
        • +
        • Click the \b Apply or Apply and Close button to confirm creation of the group.
        • Our TUI Scripts provide you with useful examples of diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 8f90021eb..f35c7935e 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -209,7 +209,10 @@ module GEOM { /*! - * \brief Get an entry of the object in GEOM component. + * \brief Get internal (unique) entry of the object in the GEOM component's data tree. + * \note This is not an entry of the data object in SALOME study. + * This is internal function of GEOM component, though it can be used outside it for + appropriate reason (e.g. for unique identification of geometry object). */ string GetEntry(); @@ -715,6 +718,11 @@ module GEOM in double theTrimSize); }; + /*! + * \brief Interface for shapes transforming. + * + * Translation, rotation, scaling, mirroring, offset, projection, recomputing. + */ interface GEOM_ITransformOperations : GEOM_IOperations { /*! @@ -1077,7 +1085,8 @@ module GEOM * \param thePath Wire or Edge along that the object will be translated. * \param theDistance progress of Path (0 = actual location, 1 = end of path location). * \param theCopy is a true or false parameter. true is to create a copy, false to move the object. - * \param theReverse is a true or false parameter. true is to reverse direction, false is to move normal direction. + * \param theReverse is a true or false parameter. True is to reverse + * direction, false is to move normal direction. * \return New GEOM_Object, containing the displaced shape. */ GEOM_Object PositionAlongPath (in GEOM_Object theObject, @@ -1105,7 +1114,6 @@ module GEOM GEOM_Object RecomputeObject (in GEOM_Object theObject); }; - // # GEOM_I3DPrimOperations: /*! * \brief Interface for 3D primitives creation * @@ -1485,9 +1493,49 @@ module GEOM in GEOM_Object thePath, in GEOM_Object theVec); + /*! + * \brief Build a middle path of a pipe-like shape. + * + * The path shape can be a wire or an edge. + * \param theShape It can be closed or unclosed pipe-like shell + * or a pipe-like solid. + * \param theBase1, theBase2 Two bases of the supposed pipe. This + * should be wires or faces of \a theShape. + * \note It is not assumed that exact or approximate copy of \a theShape + * can be obtained by applying existing Pipe operation on the + * resulting "Path" wire taking \a theBase1 as the base - it is not + * always possible; though in some particular cases it might work + * it is not guaranteed. Thus, RestorePath function should not be + * considered as an exact reverse operation of the Pipe. + * \return New GEOM_Object, containing an edge or wire that represent + * source pipe's "path". + */ + GEOM_Object RestorePath (in GEOM_Object theShape, + in GEOM_Object theBase1, + in GEOM_Object theBase2); + + /*! + * \brief Build a middle path of a pipe-like shape. + * + * The path shape can be a wire or an edge. + * \param theShape It can be closed or unclosed pipe-like shell + * or a pipe-like solid. + * \param theBase1, theBase2 Two bases of the supposed pipe. This + * should be lists of edges of \a theShape. + * \note It is not assumed that exact or approximate copy of \a theShape + * can be obtained by applying existing Pipe operation on the + * resulting "Path" wire taking \a theBase1 as the base - it is not + * always possible; though in some particular cases it might work + * it is not guaranteed. Thus, RestorePath function should not be + * considered as an exact reverse operation of the Pipe. + * \return New GEOM_Object, containing an edge or wire that represent + * source pipe's "path". + */ + GEOM_Object RestorePathEdges (in GEOM_Object theShape, + in ListOfGO theBase1, + in ListOfGO theBase2); }; - // # GEOM_IShapesOperations /*! * \brief Interface for Shapes creation: * @@ -3244,8 +3292,9 @@ module GEOM * \param theFileName The file, containing the shape. * \param theFormatName Specify format for the file reading. * Available formats can be obtained with ImportTranslators() method. - * If format 'IGES_SCALE' is used instead 'IGES' length unit will be - * set to 'meter' and result model will be scaled. + * If format 'IGES_SCALE' is used instead of 'IGES' or + * format 'STEP_SCALE' is used instead of 'STEP', + * file length unit will be ignored (set to 'meter') and result model will be scaled. * \return New GEOM_Object, containing the imported shape. */ GEOM_Object ImportFile (in string theFileName, in string theFormatName); diff --git a/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx b/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx index b44cbd49c..073969747 100755 --- a/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx +++ b/src/EntityGUI/EntityGUI_3DSketcherDlg.cxx @@ -26,7 +26,8 @@ #include "EntityGUI_3DSketcherDlg.h" #include "EntityGUI_Widgets.h" -#include + +#include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include @@ -65,19 +67,25 @@ #include #include #include +#if OCC_VERSION_LARGE > 0x06050300 +#include +#include +#include +#include +#include +#include +#include +#endif // OCC_VERSION_LARGE > 0x06050300 // This include must be *AFTER* SOCC_ViewModel.h because // of the constant ROTATE which is a #define in // GEOMImpl_Types.hxx and an enum in SOCC_ViewModel.h #include -enum -{ - NONE, - TYPE_LENGTH, - TYPE_ANGLE, - TYPE_TWO_ANGLES -}; +// TODO +// +// Avoid duplication of angle coordinates in cylindrical mode +// Check spherical mode in absolute enum { @@ -95,6 +103,107 @@ private: bool& myLock; }; +#if OCC_VERSION_LARGE > 0x06050300 +DEFINE_STANDARD_HANDLE(AIS_Text, AIS_InteractiveObject) + +class AIS_Text:public AIS_InteractiveObject +{ +public: + // CASCADE RTTI + DEFINE_STANDARD_RTTI(AIS_Text ); + + AIS_Text(){}; + + AIS_Text + ( + const TCollection_ExtendedString& , const gp_Pnt& , + Quantity_Color color, + Standard_Integer aHJust, + Standard_Integer aVJust , + Standard_Real Angle , + Standard_Boolean Zoom , + Standard_Real Height, + Font_FontAspect FontAspect, + Standard_CString Font + ); + +private: + + void Compute ( const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, + const Handle(Prs3d_Presentation)& aPresentation, + const Standard_Integer aMode); + + void ComputeSelection ( const Handle(SelectMgr_Selection)& aSelection, + const Standard_Integer aMode){} ; + +protected: + TCollection_ExtendedString aText; + gp_Pnt aPosition; + Standard_Real Red; + Standard_Real Green; + Standard_Real Blue; + Standard_Real aAngle; + Standard_Real aHeight; + Standard_Boolean aZoomable; + Quantity_Color aColor; + Standard_CString aFont; + Font_FontAspect aFontAspect; + Graphic3d_HorizontalTextAlignment aHJustification; + Graphic3d_VerticalTextAlignment aVJustification; +}; + +IMPLEMENT_STANDARD_HANDLE(AIS_Text, AIS_InteractiveObject) +IMPLEMENT_STANDARD_RTTIEXT(AIS_Text, AIS_InteractiveObject) + +AIS_Text::AIS_Text( const TCollection_ExtendedString& text, const gp_Pnt& position, + Quantity_Color color = Quantity_NOC_YELLOW, + Standard_Integer aHJust = Graphic3d_HTA_LEFT, + Standard_Integer aVJust = Graphic3d_VTA_BOTTOM, + Standard_Real angle = 0.0 , + Standard_Boolean zoomable = Standard_False, + Standard_Real height = 16., + Font_FontAspect fontAspect = Font_FA_Regular, + Standard_CString font = "Courier") +{ + aText = text; + aPosition = position; + aHJustification = Graphic3d_HorizontalTextAlignment(aHJust); + aVJustification = Graphic3d_VerticalTextAlignment(aVJust); + aAngle = angle; + aZoomable = zoomable; + aHeight = height; + aColor = color; + aFontAspect = fontAspect; + aFont = font; +}; + +void AIS_Text::Compute(const Handle(PrsMgr_PresentationManager3d)& aPresentationManager, + const Handle(Prs3d_Presentation)& aPresentation, + const Standard_Integer aMode) +{ + + aPresentation->Clear(); + + Handle_Prs3d_TextAspect asp = myDrawer->TextAspect(); + + asp->SetFont(aFont); + asp->SetColor(aColor); + asp->SetHeight(aHeight); // I am changing the myHeight value + + asp->SetHorizontalJustification(aHJustification); + asp->SetVerticalJustification(aVJustification); + asp->Aspect()->SetTextZoomable(aZoomable); + asp->Aspect()->SetTextAngle(aAngle); + asp->Aspect()->SetTextFontAspect(aFontAspect); + Prs3d_Text::Draw(aPresentation, asp, aText, aPosition); +}; +#endif // OCC_VERSION_LARGE > 0x06050300 + +bool isSame (double d1, double d2) +{ + return Abs(d1 - d2) <= Precision::Confusion(); +} + //================================================================================= // class : EntityGUI_3DSketcherDlg() // purpose : Constructs a EntityGUI_3DSketcherDlg which is a child of 'parent', with the @@ -111,7 +220,6 @@ EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, Q myLineWidth(lineWidth), myGeometryGUI(theGeometryGUI), myLengthIORedoList() -// myLastAngleNormal() { QPixmap image0(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); QPixmap image1(SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_UNDO"))); @@ -127,16 +235,23 @@ EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, Q mainFrame()->RadioButton2->close(); mainFrame()->RadioButton3->close(); - GroupType = new DlgRef_3Radio(centralWidget()); - GroupType->GroupBox1->setTitle(tr("GEOM_COORDINATES_TYPE")); + GroupType = new EntityGUI_Type(centralWidget()); + GroupType->GroupType2->setTitle(tr("GEOM_COORDINATES_TYPE")); + GroupType->GroupType1->setTitle(tr("GEOM_MODE")); GroupType->RadioButton1->setText(tr("GEOM_SKETCHER_ABS")); GroupType->RadioButton2->setText(tr("GEOM_SKETCHER_REL")); - GroupType->RadioButton3->setText(tr("Angles")); //TODO translation -// GroupType->RadioButton3->close(); - myTypeGroup = new QButtonGroup(this); - myTypeGroup->addButton(GroupType->RadioButton1, 0); - myTypeGroup->addButton(GroupType->RadioButton2, 1); - myTypeGroup->addButton(GroupType->RadioButton3, 2); + GroupType->RadioButton3->setText(tr("(X,Y,Z)")); + GroupType->RadioButton4->setText(tr("GEOM_ANGLES")); + + myTypeGroup1 = new QButtonGroup(this); + myTypeGroup1->setExclusive(true); + myTypeGroup1->addButton(GroupType->RadioButton1, 0); + myTypeGroup1->addButton(GroupType->RadioButton2, 1); + + myTypeGroup2 = new QButtonGroup(this); + myTypeGroup2->setExclusive(true); + myTypeGroup2->addButton(GroupType->RadioButton3, 0); + myTypeGroup2->addButton(GroupType->RadioButton4, 1); Group3Spin = new EntityGUI_3Spin(centralWidget()); Group3Spin->GroupBox1->setTitle(tr("GEOM_SKETCHER_VALUES")); @@ -151,13 +266,16 @@ EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, Q GroupAngles->buttonApply->setText(tr("GEOM_SKETCHER_APPLY")); GroupAngles->buttonUndo->setIcon(image1); GroupAngles->buttonRedo->setIcon(image2); - GroupAngles->checkBox->setText(tr("Angle 2")); //TODO translation + GroupAngles->TextLabel1->setText(tr("GEOM_LENGTH")); + GroupAngles->TextLabel2->setText(tr("GEOM_ANGLE")); + GroupAngles->checkBox ->setText(tr("GEOM_ANGLE_2")); + GroupAngles->checkBox_2->setText(tr("GEOM_HEIGHT")); GroupControls = new EntityGUI_Controls(centralWidget()); GroupControls->GroupBox1->setTitle(tr("GEOM_CONTROLS")); - GroupControls->CheckBox1->setText(tr("Show length dimensions")); //TODO translation - GroupControls->CheckBox2->setText(tr("Show angle dimensions")); //TODO translation - GroupControls->CheckBox3->setText(tr("Show start/end point coordinates")); //TODO translation + GroupControls->CheckBox1->setText(tr("GEOM_SHOW_LENGTH")); + GroupControls->CheckBox2->setText(tr("GEOM_SHOW_ANGLE")); + GroupControls->CheckBox3->setText(tr("GEOM_SHOW_POINTS_COORD")); GroupControls->lineEdit_1->setReadOnly(true); GroupControls->lineEdit_2->setReadOnly(true); GroupControls->lineEdit_3->setReadOnly(true); @@ -170,6 +288,8 @@ EntityGUI_3DSketcherDlg::EntityGUI_3DSketcherDlg (GeometryGUI* theGeometryGUI, Q GroupControls->label_4->setText(tr("X:")); GroupControls->label_5->setText(tr("Y:")); GroupControls->label_6->setText(tr("Z:")); + GroupControls->label_7->setText(tr("GEOM_START")); + GroupControls->label_8->setText(tr("GEOM_END")); buttonOk()->setText(tr("GEOM_BUT_END_SKETCH")); buttonApply()->setText(tr("GEOM_BUT_CLOSE_SKETCH")); @@ -204,16 +324,16 @@ void EntityGUI_3DSketcherDlg::Init() { myOK = false; myOrientation = OXY; - myPrsType = NONE; + myPrsType = prsType(); SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); myAnglePrs = dynamic_cast(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); myLengthPrs = dynamic_cast(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); +#if OCC_VERSION_LARGE > 0x06050300 + myTextPrs = dynamic_cast(((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); +#endif // OCC_VERSION_LARGE > 0x06050300 - //TEST localSelection(GEOM::GEOM_Object::_nil(), TopAbs_VERTEX); -// globalSelection(GEOM_PREVIEW); -// setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); /* Get setting of step value from file configuration */ double step = SUIT_Session::session()->resourceMgr()->doubleValue("Geometry", "SettingsGeomStep", 100.0); @@ -223,9 +343,10 @@ void EntityGUI_3DSketcherDlg::Init() initSpinBox(Group3Spin->SpinBox_DY, COORD_MIN, COORD_MAX, step, "length_precision"); initSpinBox(Group3Spin->SpinBox_DZ, COORD_MIN, COORD_MAX, step, "length_precision"); - initSpinBox(GroupAngles->SpinBox_DA , -180.0, 180.0, step, "angular_precision"); + initSpinBox(GroupAngles->SpinBox_DA , -360.0, 360.0, step, "angular_precision"); initSpinBox(GroupAngles->SpinBox_DA2, -90.0, 90.0, step, "angular_precision"); initSpinBox(GroupAngles->SpinBox_DL , COORD_MIN, COORD_MAX, step, "length_precision"); + initSpinBox(GroupAngles->SpinBox_DH , COORD_MIN, COORD_MAX, step, "length_precision"); Group3Spin->SpinBox_DX->setValue(0.0); Group3Spin->SpinBox_DY->setValue(0.0); @@ -234,10 +355,13 @@ void EntityGUI_3DSketcherDlg::Init() GroupAngles->SpinBox_DA->setValue(0.0); GroupAngles->SpinBox_DA2->setValue(0.0); GroupAngles->SpinBox_DL->setValue(0.0); + GroupAngles->SpinBox_DH->setValue(0.0); GroupAngles->radioButton_1->setChecked(true); GroupAngles->checkBox->setChecked(false); + GroupAngles->checkBox_2->setChecked(false); GroupAngles->SpinBox_DA2->setEnabled(false); + GroupAngles->SpinBox_DH->setEnabled(false); GroupControls->CheckBox1->setChecked(true); GroupControls->CheckBox2->setChecked(true); @@ -254,29 +378,32 @@ void EntityGUI_3DSketcherDlg::Init() connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument())); - connect(Group3Spin->buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnAddPoint())); - connect(Group3Spin->buttonUndo, SIGNAL(clicked()), this, SLOT(ClickOnUndo())); - connect(Group3Spin->buttonRedo, SIGNAL(clicked()), this, SLOT(ClickOnRedo())) ; + connect(Group3Spin->buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnAddPoint())); + connect(Group3Spin->buttonUndo, SIGNAL(clicked()), this, SLOT(ClickOnUndo())); + connect(Group3Spin->buttonRedo, SIGNAL(clicked()), this, SLOT(ClickOnRedo())) ; connect(GroupAngles->buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnAddPoint())); connect(GroupAngles->buttonUndo, SIGNAL(clicked()), this, SLOT(ClickOnUndo())); connect(GroupAngles->buttonRedo, SIGNAL(clicked()), this, SLOT(ClickOnRedo())) ; - connect(myTypeGroup, SIGNAL(buttonClicked(int)), this, SLOT(TypeClicked(int))); + connect(myTypeGroup1, SIGNAL(buttonClicked(int)), this, SLOT(TypeClicked(int))); + connect(myTypeGroup2, SIGNAL(buttonClicked(int)), this, SLOT(TypeClicked(int))); - connect(Group3Spin->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - connect(Group3Spin->SpinBox_DY, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - connect(Group3Spin->SpinBox_DZ, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(Group3Spin->SpinBox_DX, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(Group3Spin->SpinBox_DY, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(Group3Spin->SpinBox_DZ, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - connect(GroupAngles->SpinBox_DA, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - connect(GroupAngles->SpinBox_DA2, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); - connect(GroupAngles->SpinBox_DL, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(GroupAngles->SpinBox_DA, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(GroupAngles->SpinBox_DA2, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(GroupAngles->SpinBox_DL, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); + connect(GroupAngles->SpinBox_DH, SIGNAL(valueChanged(double)), this, SLOT(ValueChangedInSpinBox(double))); connect(GroupAngles->radioButton_1, SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ; connect(GroupAngles->radioButton_2, SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ; connect(GroupAngles->radioButton_3, SIGNAL(clicked (bool)), this, SLOT(ButtonClicked(bool))) ; connect(GroupAngles->checkBox, SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ; + connect(GroupAngles->checkBox_2, SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ; connect(GroupControls->CheckBox1, SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ; connect(GroupControls->CheckBox2, SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ; connect(GroupControls->CheckBox3, SIGNAL(clicked (bool)), this, SLOT(BoxChecked (bool))) ; @@ -291,6 +418,10 @@ void EntityGUI_3DSketcherDlg::Init() GroupControls->CheckBox3->click(); UpdateButtonsState(); + + myMode = 0; + myCoordType = 0; + GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth); } @@ -298,10 +429,24 @@ void EntityGUI_3DSketcherDlg::Init() // function : TypeClicked() // purpose : Radio button management //================================================================================= -void EntityGUI_3DSketcherDlg::TypeClicked (int mode) +void EntityGUI_3DSketcherDlg::TypeClicked (int id) { - if (mode == myMode) return; - + QButtonGroup* send = (QButtonGroup*) sender(); + + int coordType = myCoordType; + int mode = myMode; + + if (send == myTypeGroup1) + { + if(id == myMode) return; + mode = id; + } + else if (send == myTypeGroup2) + { + if (id == myCoordType) return; + coordType = id; + } + GroupAngles->hide(); Group3Spin->show(); @@ -317,31 +462,35 @@ void EntityGUI_3DSketcherDlg::TypeClicked (int mode) Group3Spin->SpinBox_DY->text().toDouble(&oky); Group3Spin->SpinBox_DZ->text().toDouble(&okz); - if (mode == 0) { // XYZ - Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_X2")); - Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_Y2")); - Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_Z2")); - if (myMode == 1) - { - if (okx) Group3Spin->SpinBox_DX->setValue(xyz.x + Group3Spin->SpinBox_DX->value()); - if (oky) Group3Spin->SpinBox_DY->setValue(xyz.y + Group3Spin->SpinBox_DY->value()); - if (okz) Group3Spin->SpinBox_DZ->setValue(xyz.z + Group3Spin->SpinBox_DZ->value()); + if (coordType == 0) // Cartesian coordinates + { + if (mode == 0) { // XYZ + Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_X2")); + Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_Y2")); + Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_Z2")); + if (myCoordType == 0 && myMode == 1) + { + if (okx) Group3Spin->SpinBox_DX->setValue(xyz.x + Group3Spin->SpinBox_DX->value()); + if (oky) Group3Spin->SpinBox_DY->setValue(xyz.y + Group3Spin->SpinBox_DY->value()); + if (okz) Group3Spin->SpinBox_DZ->setValue(xyz.z + Group3Spin->SpinBox_DZ->value()); + } + Group3Spin->buttonApply->setFocus(); } - Group3Spin->buttonApply->setFocus(); - } - else if (mode == 1) { // DXDYDZ - Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_DX2")); - Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_DY2")); - Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_DZ2")); - if (myMode == 0) - { - if (okx) Group3Spin->SpinBox_DX->setValue(Group3Spin->SpinBox_DX->value() - xyz.x); - if (oky) Group3Spin->SpinBox_DY->setValue(Group3Spin->SpinBox_DY->value() - xyz.y); - if (okz) Group3Spin->SpinBox_DZ->setValue(Group3Spin->SpinBox_DZ->value() - xyz.z); + else if (mode == 1) { // DXDYDZ + Group3Spin->TextLabel1->setText(tr("GEOM_SKETCHER_DX2")); + Group3Spin->TextLabel2->setText(tr("GEOM_SKETCHER_DY2")); + Group3Spin->TextLabel3->setText(tr("GEOM_SKETCHER_DZ2")); + if (myCoordType == 0 && myMode == 0) + { + if (okx) Group3Spin->SpinBox_DX->setValue(Group3Spin->SpinBox_DX->value() - xyz.x); + if (oky) Group3Spin->SpinBox_DY->setValue(Group3Spin->SpinBox_DY->value() - xyz.y); + if (okz) Group3Spin->SpinBox_DZ->setValue(Group3Spin->SpinBox_DZ->value() - xyz.z); + } + Group3Spin->buttonApply->setFocus(); } - Group3Spin->buttonApply->setFocus(); } - else if (mode == 2) { // Angles and Length + else if (coordType == 1) // Angles and Length + { Group3Spin->hide(); GroupAngles->show(); GroupAngles->buttonApply->setFocus(); @@ -352,6 +501,7 @@ void EntityGUI_3DSketcherDlg::TypeClicked (int mode) Group3Spin->SpinBox_DZ->blockSignals(blocked); myMode = mode; + myCoordType = coordType; updateGeometry(); resize(minimumSizeHint()); @@ -370,44 +520,25 @@ void EntityGUI_3DSketcherDlg::ClickOnAddPoint() showError(msg); return; } - - // Display and store angle dimensions interactive objects in Prs - if (GroupType->RadioButton3->isChecked()) // ANGLES - { - double anAngle2 = 0.0; - if (GroupAngles->checkBox->isChecked()) - anAngle2 = GroupAngles->SpinBox_DA2->value(); - - // Store angle dimensions - displayAngle(GroupAngles->SpinBox_DA->value(), anAngle2, - GroupAngles->SpinBox_DL->value(), myOrientation, /*store =*/true); - // Store length dimensions - displayLength(GroupAngles->SpinBox_DL->value(), /*store =*/true, /*type=*/myPrsType); - } - - // Display and store store length dimension interactive object in Prs - if (GroupType->RadioButton1->isChecked() || // ABSOLUTE or RELATIVE coordinates - GroupType->RadioButton2->isChecked()) - { - displayLength(-1, /*store=*/true); - } + + myPrsType = prsType(); + +// if(myMode == 1) + displayDimensions( /*store = */true); myPointsList.append(getCurrentPoint()); - myPrsTypeList.push_back(myPrsType); - - // Clean redo lists myRedoList.clear(); - myPrsTypeRedoList.clear(); myLengthIORedoList.Clear(); myAngleIORedoList.Clear(); + myTextIORedoList.Clear(); - if (myMode == 1) + if (myCoordType == 0 && myMode == 1) // RELATIVE CARTESIAN COORDINATES { Group3Spin->SpinBox_DX->setValue(0.0); Group3Spin->SpinBox_DY->setValue(0.0); Group3Spin->SpinBox_DZ->setValue(0.0); } - else if (myMode == 2) + else if (myCoordType == 1 && myMode == 1) // RELATIVE ANGULAR COORDINATES { GroupAngles->SpinBox_DA->setValue(0.0); GroupAngles->SpinBox_DL->setValue(0.0); @@ -426,9 +557,14 @@ void EntityGUI_3DSketcherDlg::ClickOnAddPoint() //================================================================================= void EntityGUI_3DSketcherDlg::UpdateButtonsState() { - if (myPointsList.count() == 0) GroupType->RadioButton1->click(); + if (myPointsList.count() == 0) + { + GroupType->RadioButton1->click(); + GroupType->RadioButton3->click(); + } GroupType->RadioButton2->setEnabled(myPointsList.count() > 0); - GroupType->RadioButton3->setEnabled(myPointsList.count() > 0); +// GroupType->RadioButton3->setEnabled(myPointsList.count() > 0); +// GroupType->RadioButton4->setEnabled(myPointsList.count() > 0); Group3Spin->buttonUndo->setEnabled(myPointsList.count() > 0); Group3Spin->buttonRedo->setEnabled(myRedoList.count() > 0); GroupAngles->buttonUndo->setEnabled(myPointsList.count() > 0); @@ -480,41 +616,28 @@ void EntityGUI_3DSketcherDlg::UpdatePointCoordinates() void EntityGUI_3DSketcherDlg::ClickOnUndo() { if (myPointsList.count() > 0) { - myRedoList.append(myPointsList.takeLast()); - UpdateButtonsState(); - GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth); + + myRedoList.append(myPointsList.last()); // Erase dimensions presentations SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true); ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true); - - if (myPrsTypeList.back() != NONE) - { - // Remove last prepended IO - removeLastIOFromPrs(TYPE_LENGTH); - } - if (myPrsTypeList.back() == TYPE_ANGLE || - myPrsTypeList.back() == TYPE_TWO_ANGLES) - { - // Remove first Angle IO from presentation - removeLastIOFromPrs(TYPE_ANGLE); - if (myPrsTypeList.back() == TYPE_TWO_ANGLES) - { - // Remove second Angle IO - removeLastIOFromPrs(TYPE_ANGLE); - } - } - - // Erase last action type and store it in redo list - myPrsTypeRedoList.push_back(myPrsTypeList.back()); - myPrsTypeList.pop_back(); + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true); + + removeLastIOFromPrs(); // Display modified presentation if (isLengthVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs); if (isAngleVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs); + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs); + + // Remove last point from list + myPointsList.removeLast(); + GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth); + UpdateButtonsState(); // Update of point coordinates in the control groupbox UpdatePointCoordinates(); @@ -530,39 +653,28 @@ void EntityGUI_3DSketcherDlg::ClickOnUndo() void EntityGUI_3DSketcherDlg::ClickOnRedo() { if (myRedoList.count() > 0) { - myPointsList.append(myRedoList.takeLast()); - UpdateButtonsState(); - GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth); + + myPointsList.append(myRedoList.last()); // Erase dimensions presentations SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myLengthPrs, true); ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true); - - if (myPrsTypeRedoList.back() != NONE) - restoreLastIOToPrs(TYPE_LENGTH); - - if (myPrsTypeRedoList.back() == TYPE_ANGLE || - myPrsTypeRedoList.back() == TYPE_TWO_ANGLES) - { - // Add a first IO from the Redo list - restoreLastIOToPrs(TYPE_ANGLE); - if (myPrsTypeRedoList.back() == TYPE_TWO_ANGLES) - { - // Add a second IO from the Redo list - restoreLastIOToPrs(TYPE_ANGLE); - } - } - - // Record last prs type - myPrsTypeList.push_back(myPrsTypeRedoList.back()); - myPrsTypeRedoList.pop_back(); + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true); + + restoreLastIOToPrs(); // Display modified presentation if (isLengthVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs); if (isAngleVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs); + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs); + + // Remove last point from redo list + myRedoList.removeLast(); + GEOMBase_Helper::displayPreview(true, false, true, true, myLineWidth); + UpdateButtonsState(); // Update of point coordinates in the control groupbox UpdatePointCoordinates(); @@ -575,40 +687,54 @@ void EntityGUI_3DSketcherDlg::ClickOnRedo() // function : removeLastIO() // purpose : //================================================================================= -void EntityGUI_3DSketcherDlg::removeLastIOFromPrs (int type) +void EntityGUI_3DSketcherDlg::removeLastIOFromPrs () { AIS_ListOfInteractive anIOList; - - if (type == TYPE_LENGTH) + XYZ Last = getLastPoint(); + + for (int l = 0; lGetObjects(anIOList); myLengthIORedoList.Prepend(anIOList.First()); // Store last prepended Length IO in redo list myLengthPrs->RemoveFirst(); // Remove it from myLengthPrs } - if (type == TYPE_ANGLE) + for (int a = 0; aGetObjects(anIOList); myAngleIORedoList.Prepend(anIOList.First()); // Store last prepended Angle IO in redo list myAnglePrs->RemoveFirst(); // Remove it from myAnglePrs } + for (int t = 0; tGetObjects(anIOList); + myTextIORedoList.Prepend(anIOList.First()); // Store last prepended Text IO in redo list + myTextPrs->RemoveFirst(); // Remove it from myTextPrs + } } //================================================================================= // function : restoreLastIO() // purpose : //================================================================================= -void EntityGUI_3DSketcherDlg::restoreLastIOToPrs (int type) +void EntityGUI_3DSketcherDlg::restoreLastIOToPrs () { - if (type == TYPE_LENGTH) + XYZ LastDeleted = myRedoList.last(); + + for (int l = 0; lPrependObject(myLengthIORedoList.First()); // Restore last removed IO myLengthIORedoList.RemoveFirst(); // Remove it from redo list - } - if (type == TYPE_ANGLE) + } + for (int a = 0; aPrependObject(myAngleIORedoList.First()); // Restore last removed IO myAngleIORedoList.RemoveFirst(); // Remove it from redo list } + for (int t = 0; tPrependObject(myTextIORedoList.First()); // Restore last removed IO + myTextIORedoList.RemoveFirst(); // Remove it from redo list + } } //================================================================================= @@ -720,7 +846,23 @@ void EntityGUI_3DSketcherDlg::BoxChecked (bool checked) SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); if (send == GroupAngles->checkBox) + { GroupAngles->SpinBox_DA2->setEnabled(checked); + if(checked) + { + GroupAngles->SpinBox_DH->setEnabled(false); + GroupAngles->checkBox_2->setChecked(false); + } + } + else if (send == GroupAngles->checkBox_2) + { + GroupAngles->SpinBox_DH->setEnabled(checked); + if(checked) + { + GroupAngles->SpinBox_DA2->setEnabled(false); + GroupAngles->checkBox->setChecked(false); + } + } else if (send == GroupControls->CheckBox1) { @@ -854,6 +996,7 @@ bool EntityGUI_3DSketcherDlg::execute (ObjectList& objects) aParameters << xyz.params; } +// MESSAGE("aCommands.last() = "<< aCommands.last().toStdString()); GEOM::GEOM_ICurvesOperations_var anOper = GEOM::GEOM_ICurvesOperations::_narrow(getOperation()); //GEOM::GEOM_Object_var anObj = anOper->Make3DSketcher(aCoordsArray); GEOM::GEOM_Object_var anObj = anOper->Make3DSketcherCommand(aCommands.join(":").toLatin1().constData()); @@ -875,9 +1018,10 @@ void EntityGUI_3DSketcherDlg::SetDoubleSpinBoxStep (double step) Group3Spin->SpinBox_DX->setSingleStep(step); Group3Spin->SpinBox_DY->setSingleStep(step); Group3Spin->SpinBox_DZ->setSingleStep(step); - GroupAngles->SpinBox_DA->setSingleStep(step); - GroupAngles->SpinBox_DL->setSingleStep(step); + GroupAngles->SpinBox_DA ->setSingleStep(step); GroupAngles->SpinBox_DA2->setSingleStep(step); + GroupAngles->SpinBox_DL->setSingleStep(step); + GroupAngles->SpinBox_DH->setSingleStep(step); } //================================================================================= @@ -947,60 +1091,110 @@ EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getCurrentPoint() const SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); int aPrecision = resMgr->integerValue("Geometry", "length_precision", 7); + + bool spherical = GroupAngles->checkBox->isChecked(); + bool cylindrical = GroupAngles->checkBox_2->isChecked(); - if (myMode == 2) { + if (myCoordType == 1) + { if (GroupAngles->radioButton_1->isChecked()) - xyz.command = "OXY "; + xyz.command = "OXY"; else if (GroupAngles->radioButton_2->isChecked()) - xyz.command = "OYZ "; + xyz.command = "OYZ"; else - xyz.command = "OXZ "; + xyz.command = "OXZ"; + + if (cylindrical) // Cylindrical coordinates (radius, angle, height) + xyz.command += "C"; + else + xyz.command += "S"; // Spherical coordinates (radius, angle1, angle2) --> polar if angle2 = 0 + + if (myMode == 0) // Absolute coordinates + xyz.command += "A "; + else if (myMode == 1) // Relative coordinates + xyz.command += "R "; + double anAngle = GroupAngles->SpinBox_DA->value(); double aLength = GroupAngles->SpinBox_DL->value(); double anAngle2 = 0.0; QString da2 = "0"; - if (GroupAngles->checkBox->isChecked()) { + if (spherical) { // Spherical coordinates (radius, angle1, angle2) anAngle2 = GroupAngles->SpinBox_DA2->value(); da2 = GroupAngles->SpinBox_DA2->text(); } + + double aHeight = 0.0; + QString dh = "0"; + if (cylindrical) { + aHeight = GroupAngles->SpinBox_DH->value(); + dh = GroupAngles->SpinBox_DH->text(); + } xyz.command += - QString::number(anAngle, 'g', aPrecision) + " " + - QString::number(anAngle2, 'g', aPrecision) + " " + - QString::number(aLength, 'g', aPrecision); + QString::number(anAngle, 'g', aPrecision) + " "; xyz.params = - GroupAngles->SpinBox_DA->text() + ":" + - da2 + ":" + + GroupAngles->SpinBox_DA->text() + ":"; + + if(cylindrical) + { + xyz.command += + QString::number(aHeight, 'g', aPrecision) + " "; + xyz.params += + dh + ":"; + } + else // Spherical or polar coordinates + { + xyz.command += + QString::number(anAngle2, 'g', aPrecision) + " "; + xyz.params += + dh + ":"; + } + + xyz.command += + QString::number(aLength, 'g', aPrecision); + xyz.params += GroupAngles->SpinBox_DL->text(); + // Calculate point coordinates for preview anAngle = anAngle * M_PI/180.0; anAngle2 = anAngle2 * M_PI/180.0; double aProjectedLength = aLength * cos(anAngle2); - + XYZ xyzP = getLastPoint(); + if (myMode == 0) + xyzP.x=xyzP.y=xyzP.z=0.0; if (GroupAngles->radioButton_1->isChecked()) // OXY { xyz.x = xyzP.x + aProjectedLength * cos(anAngle); xyz.y = xyzP.y + aProjectedLength * sin(anAngle); - xyz.z = xyzP.z + aLength * sin(anAngle2); + if (cylindrical) + xyz.z = xyzP.z + aHeight; + else + xyz.z = xyzP.z + aLength * sin(anAngle2); } else if (GroupAngles->radioButton_2->isChecked()) // OYZ { xyz.y = xyzP.y + aProjectedLength * cos(anAngle); xyz.z = xyzP.z + aProjectedLength * sin(anAngle); - xyz.x = xyzP.x + aLength * sin(anAngle2); + if (cylindrical) + xyz.x = xyzP.x + aHeight; + else + xyz.x = xyzP.x + aLength * sin(anAngle2); } else // OXZ { xyz.z = xyzP.z + aProjectedLength * sin(anAngle); xyz.x = xyzP.x + aProjectedLength * cos(anAngle); - xyz.y = xyzP.y + aLength * sin(anAngle2); + if (cylindrical) + xyz.y = xyzP.y + aHeight; + else + xyz.y = xyzP.y + aLength * sin(anAngle2); } } - else { + else if(myCoordType == 0) { if (myMode == 0) { // XYZ xyz.x = Group3Spin->SpinBox_DX->value(); xyz.y = Group3Spin->SpinBox_DY->value(); @@ -1028,9 +1222,92 @@ EntityGUI_3DSketcherDlg::XYZ EntityGUI_3DSketcherDlg::getCurrentPoint() const Group3Spin->SpinBox_DY->text() + ":" + Group3Spin->SpinBox_DZ->text(); } + // Update point presentation type + xyz.A = myPrsType.A; // Number of angle diomensions + xyz.L = myPrsType.L; // Number of length dimensions + xyz.T = myPrsType.T; // Number of text objects + return xyz; } + +//================================================================================= +// function : getPresentationPlane() +// purpose : returns the suitable plane for right +// relative positioning of dimension presentations +//================================================================================= +gp_Dir EntityGUI_3DSketcherDlg::getPresentationPlane() const +{ + bool withAngle = (myCoordType == 1); + bool twoAngles = GroupAngles->checkBox->isChecked(); + + XYZ Last = getLastPoint(); + XYZ Current = getCurrentPoint(); + XYZ Penultimate = getPenultimatePoint(); + + gp_Pnt P1 = gp_Pnt(Last.x,Last.y,Last.z); + if (myMode == 0) // Absolute coordinates + P1 = gp::Origin(); + + gp_Pnt P2 = gp_Pnt(Current.x,Current.y,Current.z); + gp_Pnt P3 = gp_Pnt(Penultimate.x,Penultimate.y,Penultimate.z); + + gp_Vec Vec1(P1,P2); + gp_Vec Vec2(P1,P3); + + gp_Dir aNormal; // Normal defining the plane of the presentation + + if (withAngle) // If one angle + { + // Transformation from the current coordinate system + // to the reference coordinate system + gp_Trsf aTransform = toReferenceSystem (P1); + gp_Dir N1 = gp::DZ(); + gp_Dir N2 = gp::DY(); + N1.Transform(aTransform); + N2.Transform(aTransform); + + if (Vec1.CrossMagnitude(N1) > Precision::Confusion()) + { + // The plane is orthogonal to the angle presentation plane + // and contains the current edge + aNormal = N1.Crossed(gp_Dir(Vec1)); + } + else + aNormal = N2; + + if (twoAngles) + { + gp_Vec V = Vec1.Transformed(aTransform.Inverted()); + gp_Vec Vec3(V.X(),V.Y(),0.0); + + // Express the coordinates in the refernce coordinate system (OXY) + Vec3.Transform(aTransform); + if(Abs(Vec1.CrossMagnitude(Vec3)) > Precision::Confusion()) + { + // set the normal as the cross product of the current edge with its projection + // it ensures that the dimension changes side when the angle becomes negative + aNormal = gp_Dir(Vec1.Crossed(Vec3)); + } + } + } + else + { + // Check colinearity + if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion()) + { + Vec2 = gp_Vec(gp::DX()); + if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion()) + { + Vec2 = gp_Vec(gp::DY()); + } + } + // If no angles, the plane is the one formed by the last edge and the current one + aNormal = gp_Dir(Vec1.Crossed(Vec2)); + } + return aNormal; +} + //================================================================ // Function : displayPreview // Purpose : Method for displaying preview of resulting shape @@ -1084,22 +1361,12 @@ void EntityGUI_3DSketcherDlg::displayPreview (GEOM::GEOM_Object_ptr object, getDisplayer()->SetColor(line_color); - // Display local trihedron if the mode is relatives coordinates or angles - if (myMode == 1 || myMode == 2) + // Display local trihedron if the mode is relative + if (myMode == 1) displayTrihedron(2); // Display preview of suitable dimension presentations - if (myMode == 2) // ANGLES - { - double anAngle2 = 0.0; - if (GroupAngles->checkBox->isChecked()) - anAngle2 = GroupAngles->SpinBox_DA2->value(); - - displayAngle(GroupAngles->SpinBox_DA->value(), anAngle2, GroupAngles->SpinBox_DL->value(), myOrientation); - displayLength(GroupAngles->SpinBox_DL->value(), /*store=*/false, /*type=*/myPrsType); - } - if (myMode == 0 || myMode == 1) // COORDINATES - displayLength(); + displayDimensions(false); getDisplayer()->UnsetName(); @@ -1131,257 +1398,184 @@ void EntityGUI_3DSketcherDlg::displayTrihedron (int selMode) } //================================================================ -// Function : displayAngle() -// Purpose : Method for displaying angle dimensions +// Function : displayDimensions( bool store ) +// Purpose : Method for displaying dimensions. If store = true +// the presentation is stored in a list //================================================================ -void EntityGUI_3DSketcherDlg::displayAngle (double theAngle1, double theAngle2, - double theLength, int theOrientation, bool store) +void EntityGUI_3DSketcherDlg::displayDimensions (bool store) { - if (Abs(theAngle2 - 90.0) < Precision::Angular() || - theLength < Precision::Confusion()) - return; - - SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); - + myPrsType = prsType(); XYZ Last = getLastPoint(); XYZ Current = getCurrentPoint(); gp_Pnt Last_Pnt(Last.x,Last.y,Last.z); + + gp_Pnt P0 = Last_Pnt; + gp_Pnt Origin = gp::Origin(); + if (myMode == 0) // Absolute coordinates + P0 = Origin; + gp_Pnt Current_Pnt(Current.x,Current.y,Current.z); gp_Pnt P1, P2; - - bool twoAngles = GroupAngles->checkBox->isChecked(); - - switch(theOrientation) + + // Check if last end current point are coincident + if (Last_Pnt.IsEqual(Current_Pnt, 1e-7)) + return; + + gp_Dir aNormal = getPresentationPlane(); + + if (myCoordType == 0) { - case OXY: + bool oneDimensionalMove = (isSame(Last_Pnt.X(), Current_Pnt.X()) && + isSame(Last_Pnt.Y(), Current_Pnt.Y()) ) || + (isSame(Last_Pnt.Y(), Current_Pnt.Y()) && + isSame(Last_Pnt.Z(), Current_Pnt.Z()) ) || + (isSame(Last_Pnt.X(), Current_Pnt.X()) && + isSame(Last_Pnt.Z(), Current_Pnt.Z()) ); + + if (myMode == 0) { - P1 = gp_Pnt(Last.x + theLength,Last.y,Last.z); // X direction - P2 = gp_Pnt(Last.x + theLength * cos(theAngle1 * M_PI / 180.), - Last.y + theLength * sin(theAngle1 * M_PI / 180.), - Last.z); - break; + std::string aCoordText = "( " + doubleToString(Current_Pnt.X()) + + ", " + doubleToString(Current_Pnt.Y()) + + ", " + doubleToString(Current_Pnt.Z()) + " )"; + displayText(aCoordText, Current_Pnt, store); } - case OYZ: - { - P1 = gp_Pnt(Last.x, Last.y + theLength,Last.z); // Y direction - P2 = gp_Pnt(Last.x, - Last.y + theLength * cos(theAngle1 * M_PI / 180.), - Last.z + theLength * sin(theAngle1 * M_PI / 180.)); - break; - } - case OXZ: - { - P1 = gp_Pnt(Last.x + theLength,Last.y,Last.z); // X direction - P2 = gp_Pnt(Last.x + theLength * cos(theAngle1 * M_PI / 180.) , - Last.y, - Last.z + theLength * sin(theAngle1 * M_PI / 180.)); - break; + else + { + if (oneDimensionalMove) + { + // For better colocation of dimensions if only one coordinate changes (aNormal is a better choice) + displayLength(P0, Current_Pnt, aNormal, store); + } + else + { + displayLength(gp_Pnt(P0.X(),Current.y,P0.Z()), gp_Pnt(Current.x,Current.y,P0.Z()), gp::DZ().Reversed(), store); + displayLength(gp_Pnt(Current.x,P0.Y(),P0.Z()), gp_Pnt(Current.x,Current.y,P0.Z()), gp::DZ(), store); + displayLength(gp_Pnt(Current.x,Current.y,P0.Z()), Current_Pnt, gp::DX(), store); + } } } + else if (myCoordType == 1) // ANGLES + { + bool spherical = GroupAngles->checkBox->isChecked(); + bool cylindrical = GroupAngles->checkBox_2->isChecked(); + + double anAngle1 = GroupAngles->SpinBox_DA->value(); + double aLength = GroupAngles->SpinBox_DL->value(); + + // Set the coordinates in the current coordinate system + P1.SetCoord( aLength, 0.0, 0.0); // X direction + P2.SetCoord( aLength * cos(anAngle1 * M_PI / 180. ), + aLength * sin(anAngle1 * M_PI / 180. ), + 0.0); + + // Express the coordinates in the refernce coordinate system (OXY) + gp_Trsf aTranform = toReferenceSystem(P0); + P1.Transform(aTranform); + P2.Transform(aTranform); + P1.Translate(Origin, P0); + P2.Translate(Origin, P0); + + if(myMode !=0 || !store) + displayAngle(anAngle1, P0, P1, P2, store); + else + { + std::string anAngleText = doubleToString(anAngle1) + " deg."; + displayText(anAngleText, Current_Pnt, store); + } + + if(spherical) + { + double anAngle2 = GroupAngles->SpinBox_DA2->value(); + displayAngle(anAngle2, P0, P2, Current_Pnt, store); + displayLength(P0, Current_Pnt, aNormal, store); + } + else + { + bool sameRadius = isSame ( radius(Last_Pnt), radius(Current_Pnt) ); + bool sameHeight = isSame ( height(Last_Pnt), height(Current_Pnt) ); + + gp_Vec aVec(P2, Current_Pnt); + + if (myMode == 0 && !sameRadius) + { + displayLength(P0.Translated(aVec), P2.Translated(aVec), aNormal, store); // Radius + } + else if (myMode == 1) + displayLength(P0, P2, aNormal, store); + + if ( cylindrical && + (myMode == 1 || !sameHeight) ) + displayLength(P2, Current_Pnt, aNormal.Reversed(), store); // Height + } + } +} - TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1); - TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2); - TopoDS_Vertex LastV = BRepBuilderAPI_MakeVertex(Last_Pnt); - TopoDS_Vertex CurV = BRepBuilderAPI_MakeVertex(Current_Pnt); - TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(LastV, V1); - TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(LastV, V2); - TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(LastV, CurV); - - gce_MakePln gce_MP (Last_Pnt, P1, P2); - Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value()); - - // Convert angles to string - std::string Angle1_str = doubleToString(theAngle1); - std::string Angle2_str = doubleToString(theAngle2); - - // Create interactive object - Handle(AIS_AngleDimension) anAngleIO = new AIS_AngleDimension - (anEdge1, anEdge2, aPlane, theAngle1 * M_PI / 180., - TCollection_ExtendedString(Angle1_str.c_str())); - anAngleIO->SetArrowSize((theAngle1 * M_PI / 180) * (theLength/20)); - - SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - int w = resMgr->integerValue("Geometry", "measures_line_width", 1); - - Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect(); - asp->LineAspect()->SetWidth(w); - anAngleIO->Attributes()->SetAngleAspect(asp); - - SOCC_Prs* aSPrs = dynamic_cast - (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); - +//================================================================ +// Function : displayAngle() +// Purpose : Method for displaying angle dimensions +//================================================================ +void EntityGUI_3DSketcherDlg::displayAngle (double theAngle, + gp_Pnt P0, + gp_Pnt P1, + gp_Pnt P2, + bool store) +{ + SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); + + // Creation of the AIS object + Handle(AIS_AngleDimension) anAngleIO = createAISAngleDimension(theAngle, + P0, + P1, + P2); + if (anAngleIO == NULL) + return; + if (store) { // Erase dimensions presentations ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true); myAnglePrs->PrependObject(anAngleIO); - + // Display modified presentation if (isAngleVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs); - } - else if (aSPrs) - { - aSPrs->AddObject(anAngleIO); - } - myPrsType = TYPE_ANGLE; // Overwrite type with ANGLE - - if (twoAngles) - { - gce_MakePln gce_MP2(Last_Pnt, P2, Current_Pnt); - Handle(Geom_Plane) aPlane2 = new Geom_Plane(gce_MP2.Value()); - - Handle(AIS_AngleDimension) anAngle2IO = - new AIS_AngleDimension(anEdge2, anEdge3, aPlane2, theAngle2 * M_PI / 180., - TCollection_ExtendedString(Angle2_str.c_str())); - anAngle2IO->SetArrowSize((theAngle2 * M_PI / 180) * (theLength/20)); - - anAngle2IO->Attributes()->SetAngleAspect(asp); - - if (store) - { - // Erase dimensions presentations - ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myAnglePrs, true); - myAnglePrs->PrependObject(anAngle2IO); - - // Display modified presentation - if (isAngleVisible) - ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myAnglePrs); - } - else if (aSPrs) - { - aSPrs->AddObject(anAngle2IO); - } - myPrsType = TYPE_TWO_ANGLES; // Overwrite type with TWO_ANGLES + // Update dimension presentation angle count for later undo / redo + myPrsType.A += 1; } - - if (!store && isAngleVisible) + else if ( isAngleVisible) { - GEOMBase_Helper::displayPreview(aSPrs, true, true); + SOCC_Prs* aSPrs = dynamic_cast + (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); + + if (aSPrs) + { + aSPrs->AddObject(anAngleIO); + GEOMBase_Helper::displayPreview(aSPrs, true, true); + } } } + //================================================================ // Function : displayLength() -// Purpose : Method for displaying length dimensions +// Purpose : Method for displaying length dimensions for a segment +// creation step //================================================================ -void EntityGUI_3DSketcherDlg::displayLength (double theLength, bool store, int type) +void EntityGUI_3DSketcherDlg::displayLength (gp_Pnt P1, + gp_Pnt P2, + gp_Dir theNormal, + bool store) { SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); - - XYZ Last = getLastPoint(); - XYZ Current = getCurrentPoint(); - XYZ Penultimate = getPenultimatePoint(); - bool withAngle = (type == TYPE_ANGLE || type == TYPE_TWO_ANGLES); - bool twoAngles = (type == TYPE_TWO_ANGLES); + double aLength = P1.Distance(P2); - double aLength = 0.0; - - if (theLength < 0) // Calculate length if not given - { - aLength = sqrt((Last.x - Current.x)*(Last.x - Current.x) + - (Last.y - Current.y)*(Last.y - Current.y) + - (Last.z - Current.z)*(Last.z - Current.z)); - } - else - aLength = theLength; - - if (aLength the plane is orthogonal to the angle presentation - // plane and contains the current edge - if (twoAngles) // If two angles - { - gp_XYZ Vec1_XY(Vec1.X(),Vec1.Y(),0.0);// --> define Vec3 as the projection of the current - Vec3 = gp_Vec(Vec1_XY); // edge on the plane chosen for the first angle - } - break; - } - case OYZ: - { - aNormal = gp::DX().Crossed(gp_Dir(Vec1)); - if (twoAngles) - { - gp_XYZ Vec1_YZ(0.0,Vec1.Y(),Vec1.Z()); - Vec3 = gp_Vec(Vec1_YZ); - } - break; - } - case OXZ: - { - aNormal = gp::DY().Crossed(gp_Dir(Vec1)); - if (twoAngles) - { - gp_XYZ Vec1_XZ(Vec1.X(),0.0,Vec1.Z()); - Vec3 = gp_Vec(Vec1_XZ); - } - break; - } - } - if(twoAngles // If two angles - && Abs(Vec1.CrossMagnitude(Vec3)) > Precision::Confusion()) - { - aNormal = gp_Dir(Vec1.Crossed(Vec3));// --> set the normal as the cross product of - } // the current edge with its projection - } // it ensures that the dimension changes - else - { - // Check colinearity - if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion()) - { - Vec2 = gp_Vec(gp::DX()); - if (Abs(Vec1.CrossMagnitude(Vec2)) < Precision::Confusion()) - { - Vec2 = gp_Vec(gp::DY()); - } - } - aNormal = gp_Dir(Vec1.Crossed(Vec2)); // If no angles --> the plane is the one formed by - } // the last edge and the current one - - // Plane construction - gce_MakePln gce_MP(P1, aNormal); - Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value()); - - Handle(AIS_LengthDimension) anIO = - new AIS_LengthDimension(aVert1, - aVert2, - aPlane, - aLength, - TCollection_ExtendedString(aLength_str.c_str())); - anIO->SetArrowSize(aLength/20); - - SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - int w = resMgr->integerValue("Geometry", "measures_line_width", 1); - Handle(Prs3d_LengthAspect) asp = new Prs3d_LengthAspect(); - asp->LineAspect()->SetWidth(w); - anIO->Attributes()->SetLengthAspect(asp); + + Handle(AIS_LengthDimension) anIO = createAISLengthDimension(aLength, P1, P2, theNormal); if (store) { @@ -1392,6 +1586,9 @@ void EntityGUI_3DSketcherDlg::displayLength (double theLength, bool store, int t // Display modified presentation if (isLengthVisible) ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myLengthPrs); + + // Update dimension presentation length count for later undo / redo + myPrsType.L += 1; } else if (isLengthVisible) { @@ -1403,8 +1600,129 @@ void EntityGUI_3DSketcherDlg::displayLength (double theLength, bool store, int t GEOMBase_Helper::displayPreview(aSPrs, true, true); } } +} + +//================================================================ +// Function : displayText() +// Purpose : Method for displaying length dimensions for a segment +// creation step +//================================================================ +void EntityGUI_3DSketcherDlg::displayText ( std::string theText, + gp_Pnt P, + bool store ) +{ +#if OCC_VERSION_LARGE > 0x06050300 + SUIT_ViewWindow* vw = SUIT_Session::session()->activeApplication()->desktop()->activeWindow(); + + Handle(AIS_Text) anIO = new AIS_Text(TCollection_ExtendedString(theText.c_str()), P); + + if (store) + { + // Erase length dimensions presentation + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Erase(myTextPrs, true); + myTextPrs->PrependObject(anIO); + + // Display modified presentation + ((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->Display(myTextPrs); + + // Update dimension presentation text count for later undo / redo + myPrsType.T += 1; + } + else + { + SOCC_Prs* aSPrs = dynamic_cast + (((SOCC_Viewer*)(vw->getViewManager()->getViewModel()))->CreatePrs(0)); + if (aSPrs) + { + aSPrs->PrependObject(anIO); + GEOMBase_Helper::displayPreview(aSPrs, true, true); + } + } +#endif // OCC_VERSION_LARGE > 0x06050300 +} + +//================================================================ +// Function : createAISLengthDimension() +// Purpose : Method for creation of a length dimension object +// Returns an Handle on the AIS_LengthDimension obect +//================================================================ +Handle(AIS_LengthDimension) EntityGUI_3DSketcherDlg::createAISLengthDimension(double theLength, + gp_Pnt P1, + gp_Pnt P2, + gp_Dir theNormal) +{ + // Convert length to string + std::string aLength_str = doubleToString(theLength); - myPrsType = TYPE_LENGTH; + // Plane construction + gce_MakePln gce_MP(P1, theNormal); + Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP.Value()); + + TopoDS_Vertex aVert1 = BRepBuilderAPI_MakeVertex(P1); + TopoDS_Vertex aVert2 = BRepBuilderAPI_MakeVertex(P2); + + Handle(AIS_LengthDimension) anIO = + new AIS_LengthDimension(aVert1, + aVert2, + aPlane, + theLength, + TCollection_ExtendedString(aLength_str.c_str())); + anIO->SetArrowSize(theLength/20); + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + int w = resMgr->integerValue("Geometry", "measures_line_width", 1); + Handle(Prs3d_LengthAspect) asp = new Prs3d_LengthAspect(); + asp->LineAspect()->SetWidth(w); + anIO->Attributes()->SetLengthAspect(asp); + + return anIO; +} + +//================================================================ +// Function : createAISAngleDimension() +// Purpose : Method for creation of an angle dimension object +// Returns an Handle on the AIS_AngleDimension obect +//================================================================ +Handle(AIS_AngleDimension) EntityGUI_3DSketcherDlg::createAISAngleDimension(double theAngle, + gp_Pnt P0, + gp_Pnt P1, + gp_Pnt P2) +{ + // Length of the built segment + double aLength = P0.Distance(P1); + + // Check input data + if (Abs(theAngle) < Precision::Angular() || + aLength < Precision::Confusion()) + return NULL; + + // Convert angles to string + std::string Angle_str = doubleToString(theAngle); + + // Construction of the plane + gce_MakePln gce_MP2(P0, P1, P2); + Handle(Geom_Plane) aPlane = new Geom_Plane(gce_MP2.Value()); + + TopoDS_Vertex V0 = BRepBuilderAPI_MakeVertex(P0); + TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(P1); + TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(P2); + + TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(V0, V1); + TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(V0, V2); + + Handle(AIS_AngleDimension) anIO = + new AIS_AngleDimension(anEdge1, anEdge2, aPlane, theAngle * M_PI / 180., + TCollection_ExtendedString(Angle_str.c_str())); + + anIO->SetArrowSize((theAngle * M_PI / 180) * (aLength/20)); + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + int w = resMgr->integerValue("Geometry", "measures_line_width", 1); + Handle(Prs3d_AngleAspect) asp = new Prs3d_AngleAspect(); + asp->LineAspect()->SetWidth(w); + anIO->Attributes()->SetAngleAspect(asp); + + return anIO; } //================================================================ @@ -1496,3 +1814,69 @@ std::string EntityGUI_3DSketcherDlg::doubleToString (double num) return QString::number(num, format, digNum).toStdString(); } + +//================================================================ +// Function : toReferenceSystem () +// Purpose : +//================================================================ +gp_Trsf EntityGUI_3DSketcherDlg::toReferenceSystem(gp_Pnt origin) const +{ + gp_Trsf T; // Identity transformation + gp_Ax3 reference_system; // OXY + reference_system.SetLocation(origin); + + gp_Ax3 current_system = reference_system; + switch (myOrientation) + { + case OYZ: + { + current_system = gp_Ax3(origin, gp::DX(), gp::DY()); + break; + } + case OXZ: + { + current_system = gp_Ax3(origin, gp::DY().Reversed(), gp::DX()); + break; + } + } + + T.SetTransformation( current_system, reference_system ); + + return T; +} + +//================================================================ +// Function : toCurrentSystem () +// Purpose : +//================================================================ +gp_Trsf EntityGUI_3DSketcherDlg::toCurrentSystem(gp_Pnt origin) const +{ + return toReferenceSystem(origin).Inverted(); +} + +//================================================================ +// Function : radius (gp_Pnt) const +// Purpose : +//================================================================ +double EntityGUI_3DSketcherDlg::radius (gp_Pnt thePnt) const +{ + // Get the point coordinates in the current coordinates system + gp_Trsf aTrsf = toCurrentSystem(gp::Origin()); + gp_Pnt aPnt = thePnt.Transformed(aTrsf); + + double radius = sqrt(aPnt.X()*aPnt.X() + aPnt.Y()*aPnt.Y()); + return radius; +} + +//================================================================ +// Function : height (gp_Pnt) const +// Purpose : +//================================================================ +double EntityGUI_3DSketcherDlg::height (gp_Pnt thePnt) const +{ + // Get the point coordinates in the current coordinates system + gp_Trsf aTrsf = toCurrentSystem(gp::Origin()); + gp_Pnt aPnt = thePnt.Transformed(aTrsf); + + return aPnt.Z(); +} diff --git a/src/EntityGUI/EntityGUI_3DSketcherDlg.h b/src/EntityGUI/EntityGUI_3DSketcherDlg.h index 8888cf065..a4b4d98af 100755 --- a/src/EntityGUI/EntityGUI_3DSketcherDlg.h +++ b/src/EntityGUI/EntityGUI_3DSketcherDlg.h @@ -28,12 +28,15 @@ class QButtonGroup; class QDoubleSpinBox; class EntityGUI_3Spin; +class EntityGUI_Type; class EntityGUI_Angles; class EntityGUI_Controls; -class DlgRef_3Radio; class SOCC_Prs; +class gp_Dir; #include +#include +#include #ifndef COORD_MIN # define COORD_MIN -1e+15 @@ -42,6 +45,9 @@ class SOCC_Prs; # define DBL_DIGITS_DISPLAY 16 #endif // COORD_MIN +// For convenience +bool isSame (double d1, double d2); + //================================================================================= // class : EntityGUI_Dlg // purpose : @@ -52,11 +58,21 @@ class EntityGUI_3DSketcherDlg : public GEOMBase_Skeleton struct XYZ { - XYZ() { x = y = z = 0.0; command = params = ""; } + XYZ() { x = y = z = 0.0; command = params = ""; L=A=T=0; } double x, y, z; // for preview only + int L, A, T; // for preview only QString command; QString params; }; + + struct prsType + { + prsType(){L=A=T=0;} + int L; + int A; + int T; + }; + typedef QList XYZList; public: @@ -82,10 +98,34 @@ private: const int = -1, const int = -1); + Handle(AIS_LengthDimension) createAISLengthDimension(double theLength, + gp_Pnt P1, + gp_Pnt P2, + gp_Dir theNormal); + + Handle(AIS_AngleDimension) createAISAngleDimension(double theAngle, + gp_Pnt P0, + gp_Pnt P1, + gp_Pnt P2); + + void displayAngle(double theAngle, + gp_Pnt P0, + gp_Pnt P1, + gp_Pnt P2, + bool store = false); + + void displayLength(gp_Pnt P1, + gp_Pnt P2, + gp_Dir theNormal, + bool store = false); + + void displayText(std::string theText, + gp_Pnt P, + bool store = false); + void displayTrihedron( int ); - void displayAngle( double, double, double, int, bool store = false ); - void displayLength( double theLength = -1.0, bool store = false, int type = 1); + void displayDimensions(bool store = false); bool createShapes( GEOM::GEOM_Object_ptr, TopoDS_Shape&, @@ -95,27 +135,38 @@ private: XYZ getPenultimatePoint() const; XYZ getCurrentPoint() const; + gp_Dir getPresentationPlane() const; + std::string doubleToString( double ); - void removeLastIOFromPrs( int ); - void restoreLastIOToPrs( int ); + gp_Trsf toReferenceSystem(gp_Pnt origin) const; + gp_Trsf toCurrentSystem(gp_Pnt origin) const; + + void removeLastIOFromPrs(); + void restoreLastIOToPrs(); + + double radius(gp_Pnt) const; + double height(gp_Pnt) const; + double longitude(gp_Pnt) const; + double latitude(gp_Pnt) const; private: XYZList myPointsList; XYZList myRedoList; AIS_ListOfInteractive myLengthIORedoList; AIS_ListOfInteractive myAngleIORedoList; - int myPrsType; - std::list myPrsTypeList; - std::list myPrsTypeRedoList; + AIS_ListOfInteractive myTextIORedoList; + prsType myPrsType; EntityGUI_3Spin* Group3Spin; EntityGUI_Angles* GroupAngles; EntityGUI_Controls* GroupControls; - DlgRef_3Radio* GroupType; - QButtonGroup* myTypeGroup; + EntityGUI_Type* GroupType; + QButtonGroup* myTypeGroup1; + QButtonGroup* myTypeGroup2; int myMode; + int myCoordType; int myOrientation; bool myOK; bool isLengthVisible; @@ -125,6 +176,7 @@ private: GeometryGUI* myGeometryGUI; SOCC_Prs* myAnglePrs; SOCC_Prs* myLengthPrs; + SOCC_Prs* myTextPrs; private slots: void ClickOnOk(); diff --git a/src/EntityGUI/EntityGUI_Angles_QTD.ui b/src/EntityGUI/EntityGUI_Angles_QTD.ui index 41199563b..a5c4aa5fb 100644 --- a/src/EntityGUI/EntityGUI_Angles_QTD.ui +++ b/src/EntityGUI/EntityGUI_Angles_QTD.ui @@ -6,8 +6,8 @@ 0 0 - 351 - 148 + 488 + 172 @@ -27,7 +27,7 @@ - + 0 @@ -42,10 +42,10 @@ - + - + Create @@ -53,7 +53,7 @@ - + 0 @@ -68,10 +68,10 @@ - + - + 0 @@ -95,7 +95,27 @@ - + + + + CheckBox + + + + + + + + + + CheckBox + + + + + + + @@ -120,16 +140,6 @@ - - - - CheckBox - - - - - - diff --git a/src/EntityGUI/EntityGUI_Controls_QTD.ui b/src/EntityGUI/EntityGUI_Controls_QTD.ui index b58621ea5..7d8c71b74 100644 --- a/src/EntityGUI/EntityGUI_Controls_QTD.ui +++ b/src/EntityGUI/EntityGUI_Controls_QTD.ui @@ -45,7 +45,7 @@ - + @@ -56,13 +56,6 @@ - - - - Start: - - - @@ -93,13 +86,6 @@ - - - - End: - - - @@ -130,6 +116,20 @@ + + + + Start : + + + + + + + End : + + + diff --git a/src/EntityGUI/EntityGUI_Type_QTD.ui b/src/EntityGUI/EntityGUI_Type_QTD.ui new file mode 100644 index 000000000..987571944 --- /dev/null +++ b/src/EntityGUI/EntityGUI_Type_QTD.ui @@ -0,0 +1,87 @@ + + + EntityGUI_Type_QTD + + + + 0 + 0 + 271 + 92 + + + + + + + + 0 + + + + + GroupBox + + + + + + RadioButton3 + + + false + + + + + + + RadioButton4 + + + false + + + + + + + + + + GroupBox + + + + + + RadioButton1 + + + false + + + + + + + RadioButton2 + + + false + + + + + + + + + + qPixmapFromMimeSource + + RadioButton3 + + + + diff --git a/src/EntityGUI/EntityGUI_Widgets.cxx b/src/EntityGUI/EntityGUI_Widgets.cxx index ddaa42e3d..0c59c7345 100644 --- a/src/EntityGUI/EntityGUI_Widgets.cxx +++ b/src/EntityGUI/EntityGUI_Widgets.cxx @@ -210,6 +210,20 @@ EntityGUI_Point::~EntityGUI_Point() { } +////////////////////////////////////////// +// EntityGUI_Type +////////////////////////////////////////// + +EntityGUI_Type::EntityGUI_Type( QWidget* parent, Qt::WindowFlags f ) +: QWidget( parent, f ) +{ + setupUi( this ); +} + +EntityGUI_Type::~EntityGUI_Type() +{ +} + ////////////////////////////////////////// // EntityGUI_Angles ////////////////////////////////////////// diff --git a/src/EntityGUI/EntityGUI_Widgets.h b/src/EntityGUI/EntityGUI_Widgets.h index 7e8f14e47..2668b91a8 100644 --- a/src/EntityGUI/EntityGUI_Widgets.h +++ b/src/EntityGUI/EntityGUI_Widgets.h @@ -222,6 +222,22 @@ public: QButtonGroup* ButtonGroup; }; +////////////////////////////////////////// +// EntityGUI_Type +////////////////////////////////////////// + +#include "ui_EntityGUI_Type_QTD.h" + +class EntityGUI_Type : public QWidget, + public Ui::EntityGUI_Type_QTD +{ + Q_OBJECT + +public: + EntityGUI_Type( QWidget* = 0, Qt::WindowFlags = 0 ); + ~EntityGUI_Type(); +}; + ////////////////////////////////////////// // EntityGUI_Angles ////////////////////////////////////////// diff --git a/src/EntityGUI/Makefile.am b/src/EntityGUI/Makefile.am index aece4f4a5..e6082ead5 100644 --- a/src/EntityGUI/Makefile.am +++ b/src/EntityGUI/Makefile.am @@ -85,6 +85,7 @@ UIC_FILES = \ ui_EntityGUI_Dir2_QTD.h \ ui_EntityGUI_Point_QTD.h \ ui_EntityGUI_Skeleton_QTD.h \ + ui_EntityGUI_Type_QTD.h \ ui_EntityGUI_Angles_QTD.h \ ui_EntityGUI_Controls_QTD.h diff --git a/src/GEOM/GEOM_Engine.cxx b/src/GEOM/GEOM_Engine.cxx index 32d3e97c2..501909d7a 100644 --- a/src/GEOM/GEOM_Engine.cxx +++ b/src/GEOM/GEOM_Engine.cxx @@ -1101,10 +1101,19 @@ bool ProcessFunction(Handle(GEOM_Function)& theFunction, else if (aCMDpref == "WW") { aNewDescr += "sk.close()"; } - else { - aNewDescr += "sk.addPointAnglesLength(\""; - aNewDescr += aCMDpref + "\", " + - aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + aStrVals.Value(4) + ")"; + else if (aCMDpref.Value(1) == 'O'){ + TCollection_AsciiString aCMDtrunc = aStrVals.Value(1); + aCMDtrunc.Trunc(3); + if (aCMDpref.Value(4) == 'C') + aNewDescr += "sk.addPointRadiusAngleH"; + else + aNewDescr += "sk.addPointRadiusAngles"; + if (aCMDpref.Value(5) == 'A') + aNewDescr += "Absolute("; + else + aNewDescr += "Relative("; + aNewDescr += aStrVals.Value(4) + ", " + + aStrVals.Value(2) + ", " + aStrVals.Value(3) + ", " + "\""+aCMDtrunc+"\"" + ")"; } } aNewDescr += "\n\t"; diff --git a/src/GEOMAlgo/BlockFix_SphereSpaceModifier.cxx b/src/GEOMAlgo/BlockFix_SphereSpaceModifier.cxx index 9e2db755a..2abc08316 100644 --- a/src/GEOMAlgo/BlockFix_SphereSpaceModifier.cxx +++ b/src/GEOMAlgo/BlockFix_SphereSpaceModifier.cxx @@ -40,6 +40,8 @@ #include #include #include +#include +#include //======================================================================= @@ -88,6 +90,16 @@ static Standard_Boolean ModifySurface(const TopoDS_Face& aFace, if(Vmax > PI2 - Precision::PConfusion() || Vmin < -PI2+::Precision::PConfusion()) { Handle(Geom_SphericalSurface) aSphere = Handle(Geom_SphericalSurface)::DownCast(S); gp_Sphere sp = aSphere->Sphere(); + //modified by jgv, 12.11.2012 for issue 21777// + Standard_Real Radius = sp.Radius(); + Standard_Real HalfArea = 2.*M_PI*Radius*Radius; + GProp_GProps Properties; + BRepGProp::SurfaceProperties(aFace, Properties); + Standard_Real anArea = Properties.Mass(); + Standard_Real AreaTol = Radius*Radius*1.e-6; + if (anArea > HalfArea - AreaTol) //no chance to avoid singularity + return Standard_False; + /////////////////////////////////////////////// gp_Ax3 ax3 = sp.Position(); if(Abs(Vmax-Vmin) < PI2) { gp_Ax3 axnew3(ax3.Axis().Location(), ax3.Direction()^ax3.XDirection(),ax3.XDirection()); diff --git a/src/GEOMAlgo/GEOMAlgo_Builder_2.cxx b/src/GEOMAlgo/GEOMAlgo_Builder_2.cxx index 09809f8cd..0272529f9 100755 --- a/src/GEOMAlgo/GEOMAlgo_Builder_2.cxx +++ b/src/GEOMAlgo/GEOMAlgo_Builder_2.cxx @@ -101,11 +101,10 @@ static const Standard_Integer , NMTTools_IndexedDataMapOfIndexedMapOfInteger& ); -//modified by NIZNHY-PKV Thu Feb 16 12:24:52 2012f static Standard_Boolean IsClosed(const TopoDS_Edge& , - const TopoDS_Face& ); -//modified by NIZNHY-PKV Thu Feb 16 12:24:56 2012t + const TopoDS_Face&, + Standard_Boolean& ); //======================================================================= //function : FillImagesFaces @@ -216,6 +215,7 @@ void GEOMAlgo_Builder::BuildSplitFaces() const Handle(IntTools_Context)& aCtx= pPF->Context(); // Standard_Boolean bToReverse, bIsClosed, bIsDegenerated; + Standard_Boolean bFlagClosed; Standard_Integer i, aNb, aNbF, nF; TopTools_MapOfShape aMFence; TColStd_IndexedMapOfInteger aMFP; @@ -312,10 +312,7 @@ void GEOMAlgo_Builder::BuildSplitFaces() } // bIsDegenerated=BRep_Tool::Degenerated(aE); - //modified by NIZNHY-PKV Wed Mar 07 07:46:09 2012f - bIsClosed=IsClosed(aE, aF); - //bIsClosed=BRep_Tool::IsClosed(aE, aF); - //modified by NIZNHY-PKV Wed Mar 07 07:46:13 2012t + bIsClosed=IsClosed(aE, aF, bFlagClosed); // const TopTools_ListOfShape& aLIE=myImages.Image(aE); aIt.Initialize(aLIE); @@ -349,7 +346,16 @@ void GEOMAlgo_Builder::BuildSplitFaces() aWES.AddStartElement(aSp); } continue; - }// if (aMFence.Add(aSp)) + }// if (bIsClosed){ + // + //modified by NIZNHY-PKV Wed Nov 28 13:50:34 2012f + if (!bIsClosed && bFlagClosed) { + if (!BRep_Tool::IsClosed(aSp, aF)){ + BOPTools_Tools3D::DoSplitSEAMOnFace(aSp, aF); + } + } + //modified by NIZNHY-PKV Wed Nov 28 13:50:36 2012t + // // aSp.Orientation(anOriE); bToReverse=BOPTools_Tools3D::IsSplitToReverse1(aSp, aE, aCtx); @@ -942,11 +948,13 @@ void UpdateCandidates(const Standard_Integer theNF, //purpose : //======================================================================= Standard_Boolean IsClosed(const TopoDS_Edge& aE, - const TopoDS_Face& aF) + const TopoDS_Face& aF, + Standard_Boolean& bFlag) { Standard_Boolean bRet; // bRet=BRep_Tool::IsClosed(aE, aF); + bFlag=bRet; if (bRet) { Standard_Integer iCnt; TopoDS_Shape aE1; diff --git a/src/GEOMAlgo/GEOMAlgo_FinderShapeOn2.cxx b/src/GEOMAlgo/GEOMAlgo_FinderShapeOn2.cxx index 020703409..5f3641cf3 100644 --- a/src/GEOMAlgo/GEOMAlgo_FinderShapeOn2.cxx +++ b/src/GEOMAlgo/GEOMAlgo_FinderShapeOn2.cxx @@ -78,12 +78,25 @@ #include #include #include +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //======================================================================= //function : GEOMAlgo_FinderShapeOn1 //purpose : //======================================================================= - GEOMAlgo_FinderShapeOn2::GEOMAlgo_FinderShapeOn2() +GEOMAlgo_FinderShapeOn2::GEOMAlgo_FinderShapeOn2() : GEOMAlgo_ShapeAlgo() { @@ -97,14 +110,14 @@ //function : ~ //purpose : //======================================================================= - GEOMAlgo_FinderShapeOn2::~GEOMAlgo_FinderShapeOn2() +GEOMAlgo_FinderShapeOn2::~GEOMAlgo_FinderShapeOn2() { } //======================================================================= //function : SetClsf //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::SetClsf(const Handle(GEOMAlgo_Clsf)& aClsf) +void GEOMAlgo_FinderShapeOn2::SetClsf(const Handle(GEOMAlgo_Clsf)& aClsf) { myClsf=aClsf; } @@ -112,7 +125,7 @@ //function : Clsf //purpose : //======================================================================= - const Handle(GEOMAlgo_Clsf)& GEOMAlgo_FinderShapeOn2::Clsf() const +const Handle(GEOMAlgo_Clsf)& GEOMAlgo_FinderShapeOn2::Clsf() const { return myClsf; } @@ -120,7 +133,7 @@ //function : SetShapeType //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::SetShapeType(const TopAbs_ShapeEnum aType) +void GEOMAlgo_FinderShapeOn2::SetShapeType(const TopAbs_ShapeEnum aType) { myShapeType=aType; } @@ -128,7 +141,7 @@ //function : ShapeType //purpose : //======================================================================= - TopAbs_ShapeEnum GEOMAlgo_FinderShapeOn2::ShapeType()const +TopAbs_ShapeEnum GEOMAlgo_FinderShapeOn2::ShapeType()const { return myShapeType; } @@ -136,7 +149,7 @@ //function : SetState //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::SetState(const GEOMAlgo_State aState) +void GEOMAlgo_FinderShapeOn2::SetState(const GEOMAlgo_State aState) { myState=aState; } @@ -144,7 +157,7 @@ //function : State //purpose : //======================================================================= - GEOMAlgo_State GEOMAlgo_FinderShapeOn2::State() const +GEOMAlgo_State GEOMAlgo_FinderShapeOn2::State() const { return myState; } @@ -152,7 +165,7 @@ //function : SetNbPntsMin //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::SetNbPntsMin(const Standard_Integer aNb) +void GEOMAlgo_FinderShapeOn2::SetNbPntsMin(const Standard_Integer aNb) { myNbPntsMin=aNb; } @@ -160,7 +173,7 @@ //function : NbPntsMin //purpose : //======================================================================= - Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMin()const +Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMin()const { return myNbPntsMin; } @@ -168,7 +181,7 @@ //function : SetNbPntsMax //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::SetNbPntsMax(const Standard_Integer aNb) +void GEOMAlgo_FinderShapeOn2::SetNbPntsMax(const Standard_Integer aNb) { myNbPntsMax=aNb; } @@ -176,7 +189,7 @@ //function : NbPntsMax //purpose : //======================================================================= - Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMax()const +Standard_Integer GEOMAlgo_FinderShapeOn2::NbPntsMax()const { return myNbPntsMax; } @@ -192,7 +205,7 @@ // function: Shapes // purpose: //======================================================================= - const TopTools_ListOfShape& GEOMAlgo_FinderShapeOn2::Shapes() const +const TopTools_ListOfShape& GEOMAlgo_FinderShapeOn2::Shapes() const { Standard_Integer i, aNb; TopTools_ListOfShape* pL; @@ -213,7 +226,7 @@ //function : Perform //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::Perform() +void GEOMAlgo_FinderShapeOn2::Perform() { myErrorStatus=0; myWarningStatus=0; @@ -265,7 +278,7 @@ //function : CheckData //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::CheckData() +void GEOMAlgo_FinderShapeOn2::CheckData() { Standard_Integer iErr; // @@ -306,7 +319,7 @@ //function : ProcessVertices //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::ProcessVertices() +void GEOMAlgo_FinderShapeOn2::ProcessVertices() { myErrorStatus=0; // @@ -347,7 +360,7 @@ //function : ProcessEdges //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::ProcessEdges() +void GEOMAlgo_FinderShapeOn2::ProcessEdges() { myErrorStatus=0; // @@ -450,7 +463,7 @@ //function : ProcessFaces //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::ProcessFaces() +void GEOMAlgo_FinderShapeOn2::ProcessFaces() { myErrorStatus=0; // @@ -545,7 +558,7 @@ //function : ProcessSolids //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::ProcessSolids() +void GEOMAlgo_FinderShapeOn2::ProcessSolids() { myErrorStatus=0; // @@ -592,11 +605,9 @@ //function : InnerPoints //purpose : //======================================================================= - void GEOMAlgo_FinderShapeOn2::InnerPoints(const TopoDS_Face& aF, +void GEOMAlgo_FinderShapeOn2::InnerPoints(const TopoDS_Face& aF, GEOMAlgo_ListOfPnt& aLP) { - myErrorStatus=0; - // Standard_Integer j, j1, j2, k, n[4], aNbLinks, aNx, aNb, iCnt;//, aNbMax, *pIds; TopLoc_Location aLoc; Handle(Poly_Triangulation) aTRF; @@ -604,6 +615,8 @@ GEOMAlgo_DataMapOfPassKeyInteger aMPKI; GEOMAlgo_DataMapIteratorOfDataMapOfPassKeyInteger aIt; gp_Pnt aP, aP1, aP2; + // + myErrorStatus=0; // aLP.Clear(); // @@ -648,20 +661,11 @@ iCnt=aIt.Value(); if (iCnt==1) { const GEOMAlgo_PassKey& aPK=aIt.Key(); - //qf - /* - aNbMax=aPK.NbMax(); - pIds=(Standard_Integer*)aPK.Key(); - for (k=1; k<3; ++k) { - aNx=*(pIds+aNbMax-k); - aMBN.Add(aNx); - } - */ aNx=(Standard_Integer)aPK.Id(1); aMBN.Add(aNx); aNx=(Standard_Integer)aPK.Id(2); aMBN.Add(aNx); - //qt + } } // @@ -677,74 +681,76 @@ // aNb=aLP.Extent(); // - if (!aNb && myNbPntsMin) { - // try to fill it yourself - Standard_Boolean bIsDone; - Standard_Integer aN1, aN2; + //modified by NIZNHY-PKV Mon Sep 24 08:42:32 2012f + if (!aNb && myNbPntsMin) { // A + Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint; + Standard_Integer i, aNb, aIx, iErr, aNbDomains; + Standard_Real aUMin, aUMax, aVMin, aVMax, dU, aUx, aVx, aV1, aV2; + gp_Pnt aPx; + gp_Dir2d aD2D (0., 1.); + gp_Pnt2d aP2D; + Handle(Geom2d_Line) aL2D; Handle(Geom_Surface) aS; - GeomAdaptor_Surface aGAS; - GeomAbs_SurfaceType aType; + TopoDS_Face aFF; // - aS=BRep_Tool::Surface(aF); - aGAS.Load(aS); - aType=aGAS.GetType(); - if (aType==GeomAbs_Plane || aType==GeomAbs_Cylinder) { - // inner links - aNbLinks=aMPKI.Extent(); - aIt.Initialize(aMPKI); - for (; aIt.More(); aIt.Next()) { - iCnt=aIt.Value(); - if (iCnt>1) { - // take the first having occured inner link - // and discretize it - const GEOMAlgo_PassKey& aPK=aIt.Key(); - //qf - /* - aNbMax=aPK.NbMax(); - pIds=(Standard_Integer*)aPK.Key(); - aN1=*(pIds+aNbMax-1); - aN2=*(pIds+aNbMax-2); - */ - // - aN1=(Standard_Integer)aPK.Id(1); - aN2=(Standard_Integer)aPK.Id(2); - //qt - aP1=aNodes(aN1).Transformed(aTrsf); - aP2=aNodes(aN2).Transformed(aTrsf); - // - if (aType==GeomAbs_Cylinder) { - Standard_Real aTolSM; - gp_Cylinder aCyl; - // - aTolSM=1.523e-6;//~1.-cos(0.1 deg) - aCyl=aGAS.Cylinder(); - if (!GEOMAlgo_SurfaceTools::IsCoaxial(aP1, aP2, aCyl, aTolSM)) { - continue; - } - } - // - BRepLib_MakeEdge aBME(aP1, aP2); - bIsDone=aBME.IsDone(); - if (!bIsDone) { - myErrorStatus=30; //can not obtain the line fron the link - return; - } - // - const TopoDS_Shape& aSx=aBME.Shape(); - const TopoDS_Edge& aE=TopoDS::Edge(aSx); - // - InnerPoints(aE, myNbPntsMin, aLP); - break; - }// if (iCnt>1) - }// for (; aIt.More(); aIt.Next()) - }// if (aType==GeomAbs_Plane || aType==GeomAbs_Cylinder) + aFF=aF; + aFF.Orientation (TopAbs_FORWARD); + // + Geom2dHatch_Hatcher& aHatcher=myContext->Hatcher(aFF); + // + aS=BRep_Tool::Surface(aFF); + BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax); + // + aNb=myNbPntsMin+1; + dU=(aUMax-aUMin)/aNb; + for (i=1; iD0(aUx, aVx, aPx); + aLP.Append(aPx); + break; + } + }// for (i=1; i1) { + // take the first having occured inner link + // and discretize it + const GEOMAlgo_PassKey& aPK=aIt.Key(); + // + aN1=(Standard_Integer)aPK.Id(1); + aN2=(Standard_Integer)aPK.Id(2); + // + aP1=aNodes(aN1).Transformed(aTrsf); + aP2=aNodes(aN2).Transformed(aTrsf); + // + if (aType==GeomAbs_Cylinder) { + Standard_Real aTolSM; + gp_Cylinder aCyl; + // + aTolSM=1.523e-6;//~1.-cos(0.1 deg) + aCyl=aGAS.Cylinder(); + if (!GEOMAlgo_SurfaceTools::IsCoaxial(aP1, aP2, aCyl, aTolSM)) { + continue; + } + } + // + BRepLib_MakeEdge aBME(aP1, aP2); + bIsDone=aBME.IsDone(); + if (!bIsDone) { + myErrorStatus=30; //can not obtain the line fron the link + return; + } + // + const TopoDS_Shape& aSx=aBME.Shape(); + const TopoDS_Edge& aE=TopoDS::Edge(aSx); + // + InnerPoints(aE, myNbPntsMin, aLP); + break; + }// if (iCnt>1) + }// for (; aIt.More(); aIt.Next()) + }// if (aType==GeomAbs_Plane || aType==GeomAbs_Cylinder) + }// if (!aNb && myNbPntsMin) { +*/ diff --git a/src/GEOMAlgo/GEOMAlgo_FinderShapeOnQuad.cxx b/src/GEOMAlgo/GEOMAlgo_FinderShapeOnQuad.cxx index 2c4d0afea..c8b331334 100644 --- a/src/GEOMAlgo/GEOMAlgo_FinderShapeOnQuad.cxx +++ b/src/GEOMAlgo/GEOMAlgo_FinderShapeOnQuad.cxx @@ -110,7 +110,7 @@ TopAbs_State GEOMAlgo_FinderShapeOnQuad::GetPointState(const gp_Pnt& aP) // In the case of concave quadrangle, return IN if // aP is OUT of only one concave side double nbIn = 0.; - for ( int i = 0; i < myPlanes.size(); ++i ) + for ( size_t i = 0; i < myPlanes.size(); ++i ) { TopAbs_State aSt; GEOMAlgo_SurfaceTools::GetState(aP, myPlanes[i], myTolerance, aSt); diff --git a/src/GEOMAlgo/GEOMAlgo_GetInPlace_3.cxx b/src/GEOMAlgo/GEOMAlgo_GetInPlace_3.cxx index 3cc870da4..f409c17fc 100644 --- a/src/GEOMAlgo/GEOMAlgo_GetInPlace_3.cxx +++ b/src/GEOMAlgo/GEOMAlgo_GetInPlace_3.cxx @@ -125,7 +125,7 @@ const NMTTools_CoupleOfShape& GEOMAlgo_GetInPlaceIterator::Value()const Standard_Integer TypeToInteger(const TopAbs_ShapeEnum aType1, const TopAbs_ShapeEnum aType2) { - Standard_Integer iRet, iT1, iT2, iX; + Standard_Integer iRet; // iRet=-1; // diff --git a/src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx b/src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx index fb8d5dfdc..14a7ed5d5 100644 --- a/src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx +++ b/src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx @@ -511,8 +511,7 @@ void GEOMAlgo_GlueDetector::CheckDetected const TopTools_IndexedDataMapOfShapeListOfShape& aMVE, const TopTools_IndexedDataMapOfShapeListOfShape& aMEV) { - Standard_Integer i, aNbVSD, aNbA, iRet; - TopAbs_ShapeEnum aTypeS, aTypeA[2]; + Standard_Integer aNbVSD, iRet; TopExp_Explorer aExp, aExpA; TopTools_MapOfShape aMFence, aMVSD; TopTools_ListOfShape aLV; diff --git a/src/GEOMAlgo/GEOMAlgo_Gluer2_1.cxx b/src/GEOMAlgo/GEOMAlgo_Gluer2_1.cxx index 400613da7..bcc94c5fd 100644 --- a/src/GEOMAlgo/GEOMAlgo_Gluer2_1.cxx +++ b/src/GEOMAlgo/GEOMAlgo_Gluer2_1.cxx @@ -100,7 +100,6 @@ void GEOMAlgo_Gluer2::MakeFace(const TopoDS_Face& theF, Standard_Boolean bIsToReverse, bIsUPeriodic; Standard_Integer iRet; Standard_Real aTol, aUMin, aUMax, aVMin, aVMax; - TopAbs_Orientation aOrE; Handle(Geom_Surface) aS; TopLoc_Location aLoc; TopoDS_Shape aW, aWr; diff --git a/src/GEOMGUI/GEOM_Displayer.cxx b/src/GEOMGUI/GEOM_Displayer.cxx index 7edbae5b2..1718d7d0b 100644 --- a/src/GEOMGUI/GEOM_Displayer.cxx +++ b/src/GEOMGUI/GEOM_Displayer.cxx @@ -116,10 +116,10 @@ // If the next macro is defined, autocolor feature works for all sub-shapes; // if it is undefined, autocolor feature works for groups only -//#define GENERAL_AUTOCOLOR +#define GENERAL_AUTOCOLOR // Below macro, when uncommented, switches on simplified (more performant) algorithm // of auto-color picking up -//#define SIMPLE_AUTOCOLOR +#define SIMPLE_AUTOCOLOR //================================================================ // Function : getActiveStudy @@ -1835,19 +1835,15 @@ SALOMEDS::Color GEOM_Displayer::getPredefinedUniqueColor() static QList colors; if ( colors.isEmpty() ) { - const int rfactor = 4; // red color component split factor, must be > 0 - const int gfactor = 4; // green color component split factor, must be > 0 - const int bfactor = 3; // blue color component split factor, must be > 0 - // - - // total number of pre-defined colors is defined as - // nbcolors = rfactor * gfactor * bfactor - // NB: all three factors should not have same values - // otherwise all colors will be greyish - - for ( int g = 0; g < gfactor; g++ ) { - for ( int r = 0; r < rfactor; r++ ) { - for ( int b = 0; b < bfactor; b++ ) - colors.append( QColor( qRgb( r * 255 / (rfactor-1), g * 255 / (gfactor-1), b * 255 / (bfactor-1) ) ) ); + + for (int s = 0; s < 2 ; s++) + { + for (int v = 100; v >= 40; v = v - 20) + { + for (int h = 0; h < 359 ; h = h + 60) + { + colors.append(QColor::fromHsv(h, 255 - s * 127, v * 255 / 100)); + } } } } diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 96b164f7b..9cd7e615e 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -363,6 +363,10 @@ ICON_DLG_PARTITION_PLANE partitionplane.png + + ICON_DLG_PIPE_PATH + pipe.png + ICON_DLG_PIPE pipe.png @@ -995,6 +999,10 @@ ICO_PIPE pipe.png + + ICO_PIPE_PATH + pipe.png + ICO_PLANE plane.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index d0ec111bb..ed57921e0 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -113,6 +113,14 @@ Please, select face, shell or solid and try again GEOM_ANGLE Angle : + + GEOM_ANGLES + Angles + + + GEOM_ANGLE_2 + Angle 2 : + GEOM_ANGLE_1 Angle @@ -1078,6 +1086,10 @@ Please, select face, shell or solid and try again GEOM_MIRROR_TITLE Mirror An Object + + GEOM_MODE + Mode + GEOM_MULTIROTATION Multi-Rotation @@ -1266,6 +1278,26 @@ Please, select face, shell or solid and try again GEOM_PIPE_TITLE Pipe Construction + + GEOM_PIPE_PATH + Path + + + GEOM_PIPE_PATH_TITLE + Restore Path + + + GEOM_PIPE_LIKE_SHAPE + Pipe-like shell or solid + + + GEOM_PIPE_BASE1_OBJECT + First base face/wire/edges + + + GEOM_PIPE_BASE2_OBJECT + Last base face/wire/edges + GEOM_PROFILE Profile @@ -1638,6 +1670,18 @@ Please, select face, shell or solid and try again GEOM_SHELL_TITLE Shell Construction + + GEOM_SHOW_LENGTH + Show length dimensions + + + GEOM_SHOW_ANGLE + Show angle dimensions + + + GEOM_SHOW_POINTS_COORD + Show start/end point coordinates + GEOM_SKETCH Sketch @@ -1848,7 +1892,7 @@ Please, select face, shell or solid and try again GEOM_CONTROLS - Dimensions + Controls GEOM_SOLID @@ -1886,6 +1930,14 @@ Please, select face, shell or solid and try again GEOM_SQUARE Square + + GEOM_START + Start : + + + GEOM_END + End : + GEOM_START_LCS Start LCS @@ -2682,6 +2734,10 @@ Please, select face, shell or solid and try again MEN_PIPE Extrusion Along Path + + MEN_PIPE_PATH + Restore Path + MEN_PLANE Plane @@ -3462,6 +3518,10 @@ Please, select face, shell or solid and try again STB_PIPE Create a shape by extrusion along a path + + STB_PIPE_PATH + Restore path from a pipe-like shape + STB_PLANE Create a plane @@ -3746,6 +3806,10 @@ Please, select face, shell or solid and try again TOOL_BASIC Basic + + TOOL_BLOCKS + Blocks + TOOL_BOOLEAN Boolean operations @@ -4082,6 +4146,10 @@ Please, select face, shell or solid and try again TOP_PIPE Extrusion along path + + TOP_PIPE_PATH + Restore path + TOP_PLANE Create a plane @@ -4687,8 +4755,9 @@ shells and solids on the other hand. GEOM_SCALE_DIMENSIONS - Would you like to take into account the units? -Otherwise the dimensions will be kept without modifications. + Take into account the units (%1) embedded to the file? +Ignoring units will cause model scaling (as dimensions are supposed to +be specified in meters). GEOM_ADVANCED diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 75db6a8ae..81d5072c6 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -7,6 +7,10 @@ BRep_API: command not done Erreur: impossible de construire l'objet + + PAL_NOT_DONE_ERROR + Opération annulée + CHANGE_ORIENTATION_NEW_OBJ_NAME Inverser @@ -109,6 +113,14 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_ANGLE Angle : + + GEOM_ANGLES + Angles + + + GEOM_ANGLE_2 + Angle 2 : + GEOM_ANGLE_1 Angle @@ -357,6 +369,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_CHECK_BLOCKS_COMPOUND_SUBSHAPES Sous-objets incriminés + + GEOM_GETNONBLOCKS_TITLE + Récupérer les solides non-hexahédres et les faces non-quadrangles + + + GEOM_GETNONBLOCKS + Récupérer les solides non blocs + + + GEOM_NONBLOCKS + GroupeSolidesNonBlocs + GEOM_CHECK_INFOS Objet et son information topologique @@ -710,6 +734,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_FILLET_1D Congé 1D + + GEOM_FILLET_1D_IGNORE_SECANT + Fusionner les arêtes collinéaires pour permettre des rayons plus grands + GEOM_FILLET_ABORT Il n'est pas possible de calculer un congé avec le rayon %1 @@ -836,7 +864,7 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_HEIGHT - Hauteur: + Hauteur : GEOM_HEXAGON @@ -1058,6 +1086,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_MIRROR_TITLE Refléter un objet + + GEOM_MODE + Mode + GEOM_MULTIROTATION Multi-rotation @@ -1246,6 +1278,26 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_PIPE_TITLE Construction d'un tuyau + + GEOM_PIPE_PATH + Chemin + + + GEOM_PIPE_PATH_TITLE + Récupérer le chemin + + + GEOM_PIPE_LIKE_SHAPE + Coque ou solide de type tuyau + + + GEOM_PIPE_BASE1_OBJECT + Premier(ère) face/contour/arête de base + + + GEOM_PIPE_BASE2_OBJECT + Dernier(ère) face/contour/arête de base + GEOM_PROFILE Profile @@ -1618,6 +1670,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_SHELL_TITLE Construction d'une coque + + GEOM_SHOW_LENGTH + Afficher les cotes de longueur + + + GEOM_SHOW_ANGLE + Afficher les cotes d'angle + + + GEOM_SHOW_POINTS_COORD + Afficher les points de départ/arrivée + GEOM_SKETCH Esquisse @@ -1826,6 +1890,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_COORDINATES_TYPE Type de coordonnées + + GEOM_CONTROLS + Eléments de contrôle + GEOM_SOLID Solide @@ -1862,6 +1930,14 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_SQUARE Carré + + GEOM_START + Départ : + + + GEOM_END + Arrivée : + GEOM_START_LCS SCL du Début @@ -2306,6 +2382,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_CHECK_COMPOUND Contrôler un assemblage de blocs + + MEN_GET_NON_BLOCKS + Récupérer les solides non blocs + MEN_CHECK_SELF_INTERSECTIONS Détections des auto-intersections @@ -2418,6 +2498,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_DISPLAY_ONLY Afficher uniquement + + MEN_SHOW_ONLY_CHILDREN + Afficher uniquement les enfants + MEN_BRING_TO_FRONT Afficher au premier plan @@ -2546,6 +2630,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_GROUP_EDIT Editer + + MEN_GROUP_UNION + Union de groupes + + + MEN_GROUP_INTERSECT + Intersection de groupes + + + MEN_GROUP_CUT + Découpe de groupes + MEN_RELOAD_IMPORTED Recharger à partir du disque @@ -2638,6 +2734,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau MEN_PIPE Extrusion suivant un chemin + + MEN_PIPE_PATH + Retrouver le chemin + MEN_PLANE Plan @@ -3014,6 +3114,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau PREF_TOPLEVEL_COLOR Couleur des objets mis au premier plan + + PREF_TOPLEVEL_DM + Mode d'affichage des objets mis au premier plan + + + MEN_KEEP_CURRENT_DM + Conserver le mode d'affichage en cours + + + MEN_SHOW_ADD_WACTOR + Afficher un contour en plus + PREF_LINE_COLOR Couleur des arêtes, vecteurs, contours @@ -3138,6 +3250,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_CHECK_COMPOUND Contrôler un assemblage de blocs + + STB_GET_NON_BLOCKS + Récupérer les solides non-blocs + STB_CHECK_SELF_INTERSECTIONS Détecte les auto-intersections @@ -3218,6 +3334,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_DISPLAY_ONLY Afficher uniquement + + STB_SHOW_ONLY_CHILDREN + Afficher uniquement les enfants + STB_EDGE Créer une arête @@ -3306,6 +3426,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_GROUP_EDIT Editer un groupe + + STB_GROUP_UNION + Union de groupes + + + STB_GROUP_INTERSECT + Intersection de groupes + + + STB_GROUP_CUT + Découpe de groupes + STB_RELOAD_IMPORTED Recharger l'objet importé depuis le disque @@ -3386,6 +3518,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_PIPE Créer un objet par extrusion suivant un chemin + + STB_PIPE_PATH + Retrouver le chemin à partir d'un objet de type tuyau + STB_PLANE Créer un plan @@ -3410,10 +3546,6 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_POP_CREATE_GROUP Créer un groupe - - STB_POP_SHOW_CHILDREN - Monter les objets fils - STB_POP_UNPUBLISH_OBJ Dépublier l'objet @@ -3423,7 +3555,11 @@ Choisissez une face, une coque ou un solide et essayez de nouveau Publier l'objet - STB_POP_HIDE_CHILDREN + STB_POP_DISCLOSE_CHILDREN + Afficher les objets fils + + + STB_POP_CONCEAL_CHILDREN Cacher les objets fils @@ -3670,6 +3806,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOOL_BASIC Objets de base + + TOOL_BLOCKS + Blocs + TOOL_BOOLEAN Opérations booléennes @@ -3746,6 +3886,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_CHECK_COMPOUND Valider l'assemblage de blocs + + TOP_GET_NON_BLOCKS + Récupérer les solides non-blocs + TOP_CHECK_SELF_INTERSECTIONS Détection des auto-intersections @@ -3822,6 +3966,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_DISPLAY_ONLY Afficher uniquement + + TOP_SHOW_ONLY_CHILDREN + Afficher uniquement les enfants + TOP_EDGE Construire une arête @@ -3902,6 +4050,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_GROUP_EDIT Editer un groupe + + TOP_GROUP_UNION + Union de groupes + + + TOP_GROUP_INTERSECT + Intersection de groupes + + + TOP_GROUP_CUT + Découpe de groupes + TOP_HEX_SOLID Solide hexaédrique @@ -3986,6 +4146,10 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_PIPE Extrusion suivant un chemin + + TOP_PIPE_PATH + Retrouver le chemin + TOP_PLANE Créer un plan @@ -4010,10 +4174,6 @@ Choisissez une face, une coque ou un solide et essayez de nouveau TOP_POP_CREATE_GROUP Créer un groupe - - TOP_POP_SHOW_CHILDREN - Montrer les enfants - TOP_POP_UNPUBLISH_OBJ Dépublier l'objet @@ -4023,8 +4183,12 @@ Choisissez une face, une coque ou un solide et essayez de nouveau Publier l'objet - TOP_POP_HIDE_CHILDREN - Cacher les enfants + TOP_POP_DISCLOSE_CHILDREN + Afficher les objets fils + + + TOP_POP_CONCEAL_CHILDREN + Cacher les objets fils TOP_POP_ISOS @@ -4294,6 +4458,30 @@ Choisissez une face, une coque ou un solide et essayez de nouveau STB_REMOVE_EXTRA_EDGES Supprimer les arêtes inutiles + + GEOM_FUSE_EDGES_TITLE + Fusionner les arêtes collinéaires au sein d'un contour + + + GEOM_FUSE_EDGES + Fusionner les arêtes + + + FUSE_EDGES_NEW_OBJ_NAME + FusionArêtes + + + TOP_FUSE_EDGES + Fusionner les arêtes collinéaires au sein d'un contour + + + MEN_FUSE_EDGES + Fusionner les arêtes collinéaires au sein d'un contour + + + STB_FUSE_EDGES + Fusionner les arêtes collinéaires au sein d'un contour + TOP_NORMALE Vecteur normal à une face @@ -4568,7 +4756,7 @@ les coques et solides d'un autre. GEOM_SCALE_DIMENSIONS Voulez-vous prendre les unités en considération? -Sinon les dimensions seront préservées sans modifications. +Sinon le modèle sera mis à l'échèlle GEOM (unités interprétées comme des mètres). GEOM_ADVANCED @@ -4997,6 +5185,45 @@ Le nombre de points n'est pas suffisant Choisissez un groupe à éditer + + GroupGUI_BooleanDlg + + GEOM_UNION + Union + + + GEOM_UNION_TITLE + Union de groupes + + + GEOM_INTERSECT + Intersection + + + GEOM_INTERSECT_TITLE + Intersection de groupes + + + GEOM_CUT + Découpe + + + GEOM_CUT_TITLE + Découpe de groupes + + + GEOM_GROUPS + Groupes + + + GEOM_MAIN_GROUPS + Groupes principaux + + + GEOM_TOOL_GROUPS + Groups outils + + GroupGUI_GroupDlg diff --git a/src/GEOMGUI/GeometryGUI.cxx b/src/GEOMGUI/GeometryGUI.cxx index cfb646deb..d13a0fd99 100644 --- a/src/GEOMGUI/GeometryGUI.cxx +++ b/src/GEOMGUI/GeometryGUI.cxx @@ -107,7 +107,6 @@ #include - #include "GEOMImpl_Types.hxx" extern "C" { @@ -135,7 +134,7 @@ GEOM::GEOM_Gen_var GeometryGUI::GetGeomGen() bool GeometryGUI::InitGeomGen() { GeometryGUI aGG; - if( CORBA::is_nil( myComponentGeom ) ) return false; + if ( CORBA::is_nil( myComponentGeom ) ) return false; return true; } @@ -173,12 +172,12 @@ SALOMEDS::Study_var GeometryGUI::ClientStudyToStudy (_PTR(Study) theStudy) return aDSStudy._retn(); } -void GeometryGUI::Modified( bool theIsUpdateActions ) +void GeometryGUI::Modified (bool theIsUpdateActions) { - if( SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) { - if( SalomeApp_Study* appStudy = dynamic_cast( app->activeStudy() ) ) { + if ( SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ) ) { + if ( SalomeApp_Study* appStudy = dynamic_cast( app->activeStudy() ) ) { appStudy->Modified(); - if( theIsUpdateActions ) + if ( theIsUpdateActions ) app->updateActions(); } } @@ -281,17 +280,17 @@ void GeometryGUI::ActiveWorkingPlane() bool ViewOCC = ( window && window->getViewManager()->getType() == OCCViewer_Viewer::Type() ); bool ViewVTK = ( window && window->getViewManager()->getType() == SVTK_Viewer::Type() ); - if( ViewOCC ) { + if ( ViewOCC ) { OCCViewer_ViewWindow* vw = dynamic_cast( window ); if ( vw ) { Handle(V3d_View) view3d = vw->getViewPort()->getView(); view3d->SetProj(DZ.X(), DZ.Y(), DZ.Z()); view3d->SetUp(DY.X(), DY.Y(), DY.Z()); - vw->onViewFitAll(); + vw->onViewFitAll(); } } - else if( ViewVTK ) { + else if ( ViewVTK ) { SVTK_ViewWindow* vw = dynamic_cast( window ); if ( vw ) { vtkCamera* camera = vw->getRenderer()->GetActiveCamera(); @@ -473,6 +472,7 @@ void GeometryGUI::OnGUIEvent( int id ) case GEOMOp::OpRevolution: // MENU GENERATION - REVOLUTION case GEOMOp::OpFilling: // MENU GENERATION - FILLING case GEOMOp::OpPipe: // MENU GENERATION - PIPE + case GEOMOp::OpPipePath: // MENU GENERATION - RESTORE PATH libName = "GenerationGUI"; break; case GEOMOp::Op2dSketcher: // MENU ENTITY - SKETCHER @@ -596,15 +596,15 @@ void GeometryGUI::OnGUIEvent( int id ) // call method of corresponding GUI library if ( library ) { library->OnGUIEvent( id, desk ); - + // Update a list of materials for "Preferences" dialog if ( id == GEOMOp::OpMaterialProperties ) { LightApp_Preferences* pref = preferences(); if ( pref ) { - Material_ResourceMgr aMatResMgr; - setPreferenceProperty( pref->rootItem()->findItem( tr( "PREF_MATERIAL" ), true )->id(), - "strings", - aMatResMgr.materials() ); + Material_ResourceMgr aMatResMgr; + setPreferenceProperty( pref->rootItem()->findItem( tr( "PREF_MATERIAL" ), true )->id(), + "strings", + aMatResMgr.materials() ); } } } @@ -689,11 +689,11 @@ void GeometryGUI::createGeomAction( const int id, const QString& label, const QS void GeometryGUI::createOriginAndBaseVectors() { SalomeApp_Study* appStudy = dynamic_cast( application()->activeStudy() ); - if( appStudy ) { + if ( appStudy ) { _PTR(Study) studyDS = appStudy->studyDS(); - if( studyDS && !CORBA::is_nil( GetGeomGen() ) ) { + if ( studyDS && !CORBA::is_nil( GetGeomGen() ) ) { GEOM::GEOM_IBasicOperations_var aBasicOperations = GetGeomGen()->GetIBasicOperations( studyDS->StudyId() ); - if( !aBasicOperations->_is_nil() ) { + if ( !aBasicOperations->_is_nil() ) { SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr(); double aLength = aResourceMgr->doubleValue( "Geometry", "base_vectors_length", 1.0 ); GEOM::GEOM_Object_var anOrigin = aBasicOperations->MakePointXYZ( 0.0, 0.0, 0.0 ); @@ -751,6 +751,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createGeomAction( GEOMOp::OpRevolution, "REVOLUTION" ); createGeomAction( GEOMOp::OpFilling, "FILLING" ); createGeomAction( GEOMOp::OpPipe, "PIPE" ); + createGeomAction( GEOMOp::OpPipePath, "PIPE_PATH" ); createGeomAction( GEOMOp::OpGroupCreate, "GROUP_CREATE" ); createGeomAction( GEOMOp::OpGroupEdit, "GROUP_EDIT" ); @@ -950,6 +951,9 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpRevolution, genId, -1 ); createMenu( GEOMOp::OpFilling, genId, -1 ); createMenu( GEOMOp::OpPipe, genId, -1 ); +#if OCC_VERSION_LARGE > 0x06050300 + createMenu( GEOMOp::OpPipePath, genId, -1 ); +#endif // int advId = createMenu( tr( "MEN_ADVANCED" ), newEntId, -1 ); @@ -983,9 +987,9 @@ void GeometryGUI::initialize( CAM_Application* app ) createMenu( GEOMOp::OpShell, buildId, -1 ); createMenu( GEOMOp::OpSolid, buildId, -1 ); createMenu( GEOMOp::OpCompound, buildId, -1 ); - + createMenu( separator(), newEntId, -1 ); - + createMenu( GEOMOp::OpPictureImport, newEntId, -1 ); #ifdef WITH_OPENCV createMenu( GEOMOp::OpFeatureDetect, newEntId, -1 ); @@ -1110,7 +1114,7 @@ void GeometryGUI::initialize( CAM_Application* app ) */ // ---- create toolbars -------------------------- - + int basicTbId = createTool( tr( "TOOL_BASIC" ) ); createTool( GEOMOp::OpPoint, basicTbId ); createTool( GEOMOp::OpLine, basicTbId ); @@ -1124,11 +1128,11 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpPlane, basicTbId ); createTool( GEOMOp::OpLCS, basicTbId ); createTool( GEOMOp::OpOriginAndVectors, basicTbId ); - + // int sketchTbId = createTool( tr( "TOOL_SKETCH" ) ); // createTool( GEOMOp::Op2dSketcher, sketchTbId ); // createTool( GEOMOp::Op3dSketcher, sketchTbId ); - + int primTbId = createTool( tr( "TOOL_PRIMITIVES" ) ); createTool( GEOMOp::OpBox, primTbId ); createTool( GEOMOp::OpCylinder, primTbId ); @@ -1138,26 +1142,29 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpRectangle, primTbId ); createTool( GEOMOp::OpDisk, primTbId ); createTool( GEOMOp::OpPipeTShape, primTbId ); //rnc - + int blocksTbId = createTool( tr( "TOOL_BLOCKS" ) ); createTool( GEOMOp::OpDividedDisk, blocksTbId ); createTool( GEOMOp::OpDividedCylinder, blocksTbId ); - + // int advancedTbId = createTool( tr( "TOOL_ADVANCED" ) ); //rnc // createTool( GEOMOp::OpPipeTShape, advancedTbId ); - + int boolTbId = createTool( tr( "TOOL_BOOLEAN" ) ); createTool( GEOMOp::OpFuse, boolTbId ); createTool( GEOMOp::OpCommon, boolTbId ); createTool( GEOMOp::OpCut, boolTbId ); createTool( GEOMOp::OpSection, boolTbId ); - - int genTbId = createTool( tr( "TOOL_GENERATION" ) ); + + int genTbId = createTool( tr( "TOOL_GENERATION" ) ); createTool( GEOMOp::OpPrism, genTbId ); createTool( GEOMOp::OpRevolution, genTbId ); createTool( GEOMOp::OpFilling, genTbId ); createTool( GEOMOp::OpPipe, genTbId ); - +#if OCC_VERSION_LARGE > 0x06050300 + createTool( GEOMOp::OpPipePath, genTbId ); +#endif + int transTbId = createTool( tr( "TOOL_TRANSFORMATION" ) ); createTool( GEOMOp::OpTranslate, transTbId ); createTool( GEOMOp::OpRotate, transTbId ); @@ -1169,14 +1176,14 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( separator(), transTbId ); createTool( GEOMOp::OpMultiTranslate, transTbId ); createTool( GEOMOp::OpMultiRotate, transTbId ); - + int operTbId = createTool( tr( "TOOL_OPERATIONS" ) ); createTool( GEOMOp::OpExplode, operTbId ); createTool( GEOMOp::OpPartition, operTbId ); createTool( GEOMOp::OpArchimede, operTbId ); createTool( GEOMOp::OpShapesOnShape, operTbId ); createTool( GEOMOp::OpSharedShapes, operTbId ); - + int featTbId = createTool( tr( "TOOL_FEATURES" ) ); createTool( GEOMOp::OpFillet1d, featTbId ); createTool( GEOMOp::OpFillet2d, featTbId ); @@ -1184,7 +1191,7 @@ void GeometryGUI::initialize( CAM_Application* app ) createTool( GEOMOp::OpChamfer, featTbId ); createTool( GEOMOp::OpExtrudedBoss, featTbId ); createTool( GEOMOp::OpExtrudedCut, featTbId ); - + int buildTbId = createTool( tr( "TOOL_BUILD" ) ); createTool( GEOMOp::OpEdge, buildTbId ); createTool( GEOMOp::OpWire, buildTbId ); @@ -1219,7 +1226,7 @@ void GeometryGUI::initialize( CAM_Application* app ) #ifdef WITH_OPENCV createTool( GEOMOp::OpFeatureDetect, picturesTbId ); #endif - + // int advancedTbId = createTool( tr( "TOOL_ADVANCED" ) ); //@@ insert new functions before this line @@ do not remove this line @@ do not remove this line @@ do not remove this line @@ do not remove this line @@// @@ -1261,7 +1268,7 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->setRule(action(GEOMOp::OpBringToFront), bringRule, QtxPopupMgr::VisibleRule ); mgr->setRule(action(GEOMOp::OpBringToFront), "topLevel=true", QtxPopupMgr::ToggleRule ); mgr->insert( action(GEOMOp::OpClsBringToFront ), -1, -1 ); // clear bring to front - mgr->setRule( action(GEOMOp::OpClsBringToFront ), clientOCC, QtxPopupMgr::VisibleRule ); + mgr->setRule( action(GEOMOp::OpClsBringToFront ), clientOCC, QtxPopupMgr::VisibleRule ); #endif mgr->insert( separator(), -1, -1 ); // ----------- dispmodeId = mgr->insert( tr( "MEN_DISPLAY_MODE" ), -1, -1 ); // display mode menu @@ -1293,7 +1300,7 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action( GEOMOp::OpPointMarker ), -1, -1 ); // point marker //mgr->setRule( action( GEOMOp::OpPointMarker ), QString( "selcount>0 and $typeid in {%1}" ).arg(GEOM_POINT ), QtxPopupMgr::VisibleRule ); mgr->setRule( action( GEOMOp::OpPointMarker ), QString( "selcount>0 and ( $typeid in {%1} or compoundOfVertices=true ) " ).arg(GEOM::VERTEX).arg(GEOM::COMPOUND), QtxPopupMgr::VisibleRule ); - mgr->insert( action( GEOMOp::OpMaterialProperties ), -1, -1 ); // material properties + mgr->insert( action( GEOMOp::OpMaterialProperties ), -1, -1 ); // material properties mgr->setRule( action( GEOMOp::OpMaterialProperties ), clientOCCorVTK_AndSomeVisible + " and ($component={'GEOM'}) and selcount>0 and isVisible", QtxPopupMgr::VisibleRule ); mgr->insert( action( GEOMOp::OpSetTexture ), -1, -1 ); // texture mgr->setRule( action( GEOMOp::OpSetTexture ), clientOCCorOB_AndSomeVisible + " and ($component={'GEOM'})", QtxPopupMgr::VisibleRule ); @@ -1304,7 +1311,7 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action( GEOMOp::OpIsosWidth ), lineW, -1 ); // isos width mgr->setRule( action( GEOMOp::OpIsosWidth ), clientOCCorVTK_AndSomeVisible, QtxPopupMgr::VisibleRule ); - + mgr->insert( separator(), -1, -1 ); // ----------- mgr->insert( action( GEOMOp::OpAutoColor ), -1, -1 ); // auto color mgr->setRule( action( GEOMOp::OpAutoColor ), autoColorPrefix + " and isAutoColor=false", QtxPopupMgr::VisibleRule ); @@ -1363,7 +1370,6 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->insert( action( GEOMOp::OpUnpublishObject ), -1, -1 ); // Unpublish object mgr->setRule( action( GEOMOp::OpUnpublishObject ), QString("client='ObjectBrowser' and $type in {'Shape' 'Group'} and selcount>0"), QtxPopupMgr::VisibleRule ); - mgr->insert( action( GEOMOp::OpPublishObject ), -1, -1 ); // Publish object mgr->setRule( action( GEOMOp::OpPublishObject ), QString("client='ObjectBrowser' and isComponent=true"), QtxPopupMgr::VisibleRule ); @@ -1372,9 +1378,8 @@ void GeometryGUI::initialize( CAM_Application* app ) mgr->hide( mgr->actionId( action( myEraseAll ) ) ); - SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - if(resMgr) { + if (resMgr) { GEOM_AISShape::setTopLevelDisplayMode((GEOM_AISShape::TopLevelDispMode)resMgr->integerValue("Geometry", "toplevel_dm", 0)); QColor c = resMgr->colorValue( "Geometry", "toplevel_color", QColor( 170, 85, 0 ) ); GEOM_AISShape::setTopLevelColor(SalomeApp_Tools::color(c)); @@ -1399,16 +1404,18 @@ bool GeometryGUI::activateModule( SUIT_Study* study ) // import Python module that manages GEOM plugins (need to be here because SalomePyQt API uses active module) PyGILState_STATE gstate = PyGILState_Ensure(); - PyObject* pluginsmanager=PyImport_ImportModuleNoBlock((char*)"salome_pluginsmanager"); - if(pluginsmanager==NULL) + PyObject* pluginsmanager = PyImport_ImportModuleNoBlock((char*)"salome_pluginsmanager"); + if (pluginsmanager == NULL) PyErr_Print(); - else - { - PyObject* result=PyObject_CallMethod( pluginsmanager, (char*)"initialize", (char*)"isss",1,"geom",tr("MEN_NEW_ENTITY").toStdString().c_str(),tr("GEOM_PLUGINS_OTHER").toStdString().c_str()); - if(result==NULL) - PyErr_Print(); - Py_XDECREF(result); - } + else { + PyObject* result = + PyObject_CallMethod(pluginsmanager, (char*)"initialize", (char*)"isss", 1, "geom", + tr("MEN_NEW_ENTITY").toStdString().c_str(), + tr("GEOM_PLUGINS_OTHER").toStdString().c_str()); + if (result == NULL) + PyErr_Print(); + Py_XDECREF(result); + } PyGILState_Release(gstate); // end of GEOM plugins loading @@ -1466,13 +1473,13 @@ bool GeometryGUI::activateModule( SUIT_Study* study ) // 0020836 (Basic vectors and origin) SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr(); - if( aResourceMgr->booleanValue( "Geometry", "auto_create_base_objects", false ) ) { + if ( aResourceMgr->booleanValue( "Geometry", "auto_create_base_objects", false ) ) { SalomeApp_Study* appStudy = dynamic_cast( application()->activeStudy() ); - if( appStudy ) { + if ( appStudy ) { _PTR(Study) studyDS = appStudy->studyDS(); - if( studyDS ) { + if ( studyDS ) { _PTR(SComponent) aSComponent = studyDS->FindComponent("GEOM"); - if( !aSComponent ) // create objects automatically only if there is no GEOM component + if ( !aSComponent ) // create objects automatically only if there is no GEOM component createOriginAndBaseVectors(); } } @@ -1481,7 +1488,6 @@ bool GeometryGUI::activateModule( SUIT_Study* study ) return true; } - //======================================================================= // function : GeometryGUI::deactivateModule() // purpose : Called when GEOM module is deactivated @@ -1571,7 +1577,7 @@ void GeometryGUI::onViewManagerAdded( SUIT_ViewManager* vm ) this, SLOT( OnMouseMove( SUIT_ViewWindow*, QMouseEvent* ) ) ); connect( vm, SIGNAL( mouseRelease ( SUIT_ViewWindow*, QMouseEvent* ) ), this, SLOT( OnMouseRelease( SUIT_ViewWindow*, QMouseEvent* ) ) ); - + LightApp_SelectionMgr* sm = getApp()->selectionMgr(); myOCCSelectors.append( new GEOMGUI_OCCSelector( ((OCCViewer_ViewManager*)vm)->getOCCViewer(), sm ) ); @@ -1741,31 +1747,30 @@ void GeometryGUI::createPreferences() LightApp_Preferences::DblSpin, "Geometry", "deflection_coeff" ); int material = addPreference( tr( "PREF_MATERIAL" ), genGroup, - LightApp_Preferences::Selector, - "Geometry", "material" ); - + LightApp_Preferences::Selector, + "Geometry", "material" ); + const int nb = 4; int wd[nb]; int iter=0; wd[iter++] = addPreference( tr( "PREF_EDGE_WIDTH" ), genGroup, - LightApp_Preferences::IntSpin, "Geometry", "edge_width" ); + LightApp_Preferences::IntSpin, "Geometry", "edge_width" ); wd[iter++] = addPreference( tr( "PREF_ISOLINES_WIDTH" ), genGroup, - LightApp_Preferences::IntSpin, "Geometry", "isolines_width" ); + LightApp_Preferences::IntSpin, "Geometry", "isolines_width" ); wd[iter++] = addPreference( tr( "PREF_PREVIEW_EDGE_WIDTH" ), genGroup, - LightApp_Preferences::IntSpin, "Geometry", "preview_edge_width" ); - - wd[iter++] = addPreference( tr( "PREF_MEASURES_LINE_WIDTH" ), genGroup, - LightApp_Preferences::IntSpin, "Geometry", "measures_line_width" ); + LightApp_Preferences::IntSpin, "Geometry", "preview_edge_width" ); - for(int i = 0; i < nb; i++) { - setPreferenceProperty( wd[i], "min", 1 ); + wd[iter++] = addPreference( tr( "PREF_MEASURES_LINE_WIDTH" ), genGroup, + LightApp_Preferences::IntSpin, "Geometry", "measures_line_width" ); + + for (int i = 0; i < nb; i++) { + setPreferenceProperty( wd[i], "min", 1 ); setPreferenceProperty( wd[i], "max", 5 ); } - // Quantities with individual precision settings int precGroup = addPreference( tr( "GEOM_PREF_GROUP_PRECISION" ), tabId ); setPreferenceProperty( precGroup, "columns", 2 ); @@ -1819,7 +1824,6 @@ void GeometryGUI::createPreferences() setPreferenceProperty( dispmode, "strings", aModesList ); setPreferenceProperty( dispmode, "indexes", anIndexesList ); - // Set property for top level display mode QStringList aTopModesList; aTopModesList.append( tr("MEN_SHOW_ADD_WACTOR") ); @@ -1891,7 +1895,6 @@ void GeometryGUI::createPreferences() addPreference( tr( "PREF_AUTO_CREATE" ), originGroup, LightApp_Preferences::Bool, "Geometry", "auto_create_base_objects" ); - int operationsGroup = addPreference( tr( "PREF_GROUP_OPERATIONS" ), tabId ); setPreferenceProperty( operationsGroup, "columns", 2 ); @@ -1906,18 +1909,20 @@ void GeometryGUI::preferencesChanged( const QString& section, const QString& par if (param == QString("SettingsGeomStep")) { double spin_step = aResourceMgr->doubleValue(section, param, 100.); EmitSignalDefaultStepValueChanged(spin_step); - } else if(param == QString("toplevel_color")) { + } + else if (param == QString("toplevel_color")) { QColor c = aResourceMgr->colorValue( "Geometry", "toplevel_color", QColor( 170, 85, 0 ) ); GEOM_AISShape::setTopLevelColor(SalomeApp_Tools::color(c)); - } else if(param == QString("toplevel_dm")) { + } + else if (param == QString("toplevel_dm")) { GEOM_AISShape::setTopLevelDisplayMode((GEOM_AISShape::TopLevelDispMode)aResourceMgr->integerValue("Geometry", "toplevel_dm", 0)); } - } + } } LightApp_Displayer* GeometryGUI::displayer() { - if( !myDisplayer ) + if ( !myDisplayer ) myDisplayer = new GEOM_Displayer( dynamic_cast( getApp()->activeStudy() ) ); return myDisplayer; } @@ -1926,6 +1931,7 @@ void GeometryGUI::setLocalSelectionMode(const int mode) { myLocalSelectionMode = mode; } + int GeometryGUI::getLocalSelectionMode() const { return myLocalSelectionMode; @@ -1986,7 +1992,7 @@ void GeometryGUI::storeVisualParameters (int savePoint) std::string entry = ip->encodeEntry(o_it.key().toLatin1().data(), componentName); _PTR(GenericAttribute) anAttr; - if( !obj->FindAttribute(anAttr, "AttributeIOR")) + if (!obj->FindAttribute(anAttr, "AttributeIOR")) continue; std::string param,occParam = vType.toLatin1().data(); @@ -1994,17 +2000,17 @@ void GeometryGUI::storeVisualParameters (int savePoint) occParam += QString::number(aMgrId).toLatin1().data(); occParam += NAME_SEPARATOR; - if(aProps.contains(VISIBILITY_PROP)) { + if (aProps.contains(VISIBILITY_PROP)) { param = occParam + VISIBILITY_PROP; ip->setParameter(entry, param, aProps.value(VISIBILITY_PROP).toInt() == 1 ? "On" : "Off"); } - if(aProps.contains(DISPLAY_MODE_PROP)) { + if (aProps.contains(DISPLAY_MODE_PROP)) { param = occParam + DISPLAY_MODE_PROP; ip->setParameter(entry, param, QString::number(aProps.value(DISPLAY_MODE_PROP).toInt()).toLatin1().data()); } - if(aProps.contains(COLOR_PROP)) { + if (aProps.contains(COLOR_PROP)) { QColor c = aProps.value(COLOR_PROP).value(); QString colorStr = QString::number(c.red()/255.); colorStr += DIGIT_SEPARATOR; colorStr += QString::number(c.green()/255.); @@ -2013,59 +2019,59 @@ void GeometryGUI::storeVisualParameters (int savePoint) ip->setParameter(entry, param, colorStr.toLatin1().data()); } - if(vType == SVTK_Viewer::Type()) { - if(aProps.contains(OPACITY_PROP)) { + if (vType == SVTK_Viewer::Type()) { + if (aProps.contains(OPACITY_PROP)) { param = occParam + OPACITY_PROP; ip->setParameter(entry, param, QString::number(1. - aProps.value(TRANSPARENCY_PROP).toDouble()).toLatin1().data()); } } else if (vType == SOCC_Viewer::Type()) { - if(aProps.contains(TRANSPARENCY_PROP)) { + if (aProps.contains(TRANSPARENCY_PROP)) { param = occParam + TRANSPARENCY_PROP; ip->setParameter(entry, param, QString::number(aProps.value(TRANSPARENCY_PROP).toDouble()).toLatin1().data()); } - if(aProps.contains(TOP_LEVEL_PROP)) { + if (aProps.contains(TOP_LEVEL_PROP)) { param = occParam + TOP_LEVEL_PROP; - Standard_Boolean val = aProps.value(TOP_LEVEL_PROP).value(); - if (val == Standard_True) - ip->setParameter(entry, param, "1"); - } + Standard_Boolean val = aProps.value(TOP_LEVEL_PROP).value(); + if (val == Standard_True) + ip->setParameter(entry, param, "1"); + } } - if(aProps.contains(ISOS_PROP)) { + if (aProps.contains(ISOS_PROP)) { param = occParam + ISOS_PROP; ip->setParameter(entry, param, aProps.value(ISOS_PROP).toString().toLatin1().data()); } - if(aProps.contains(VECTOR_MODE_PROP)) { + if (aProps.contains(VECTOR_MODE_PROP)) { param = occParam + VECTOR_MODE_PROP; ip->setParameter(entry, param, QString::number(aProps.value(VECTOR_MODE_PROP).toInt()).toLatin1().data()); } - if(aProps.contains(DEFLECTION_COEFF_PROP)) { + if (aProps.contains(DEFLECTION_COEFF_PROP)) { param = occParam + DEFLECTION_COEFF_PROP; ip->setParameter(entry, param, QString::number(aProps.value(DEFLECTION_COEFF_PROP).toDouble()).toLatin1().data()); } //Marker type of the vertex - ONLY for the "Vertex" and "Compound of the Vertex" - if(aProps.contains(MARKER_TYPE_PROP)) { + if (aProps.contains(MARKER_TYPE_PROP)) { param = occParam + MARKER_TYPE_PROP; ip->setParameter(entry, param, aProps.value(MARKER_TYPE_PROP).toString().toLatin1().data()); } - if(aProps.contains(MATERIAL_PROP)) { + if (aProps.contains(MATERIAL_PROP)) { param = occParam + MATERIAL_PROP; ip->setParameter(entry, param, aProps.value(MATERIAL_PROP).toString().toLatin1().data()); } - if(aProps.contains( EDGE_WIDTH_PROP )) { + if (aProps.contains(EDGE_WIDTH_PROP)) { param = occParam + EDGE_WIDTH_PROP; - ip->setParameter(entry, param, aProps.value(EDGE_WIDTH_PROP).toString().toLatin1().data()); + ip->setParameter(entry, param, aProps.value(EDGE_WIDTH_PROP).toString().toLatin1().data()); } - - if(aProps.contains( ISOS_WIDTH_PROP )) { - param = occParam + ISOS_WIDTH_PROP; - ip->setParameter(entry, param, aProps.value(ISOS_WIDTH_PROP).toString().toLatin1().data()); + + if (aProps.contains(ISOS_WIDTH_PROP)) { + param = occParam + ISOS_WIDTH_PROP; + ip->setParameter(entry, param, aProps.value(ISOS_WIDTH_PROP).toString().toLatin1().data()); } } // object iterator } // for (views) @@ -2141,52 +2147,42 @@ void GeometryGUI::restoreVisualParameters (int savePoint) if (!ok) // bad conversion of view index to integer continue; - if((viewIndex + 1) > aListOfMap.count()) { + if ((viewIndex + 1) > aListOfMap.count()) { aListOfMap.resize(viewIndex + 1); } QString val((*valuesIt).c_str()); - if(paramNameStr == VISIBILITY_PROP){ + if (paramNameStr == VISIBILITY_PROP) { aListOfMap[viewIndex].insert(VISIBILITY_PROP, val == "On" ? 1 : 0); - - } else if(paramNameStr == OPACITY_PROP) { + } else if (paramNameStr == OPACITY_PROP) { aListOfMap[viewIndex].insert(TRANSPARENCY_PROP, 1. - val.toDouble()); - - } else if(paramNameStr == TRANSPARENCY_PROP) { + } else if (paramNameStr == TRANSPARENCY_PROP) { aListOfMap[viewIndex].insert( TRANSPARENCY_PROP, val.toDouble() ); - - } else if(paramNameStr == TOP_LEVEL_PROP) { - aListOfMap[viewIndex].insert( TRANSPARENCY_PROP, val == "1" ? Standard_True : Standard_False ); - - } else if(paramNameStr == DISPLAY_MODE_PROP) { + } else if (paramNameStr == TOP_LEVEL_PROP) { + aListOfMap[viewIndex].insert( TRANSPARENCY_PROP, val == "1" ? Standard_True : Standard_False ); + } else if (paramNameStr == DISPLAY_MODE_PROP) { aListOfMap[viewIndex].insert( DISPLAY_MODE_PROP, val.toInt()); - - } else if(paramNameStr == ISOS_PROP) { + } else if (paramNameStr == ISOS_PROP) { aListOfMap[viewIndex].insert( ISOS_PROP, val); - - } else if(paramNameStr == COLOR_PROP) { + } else if (paramNameStr == COLOR_PROP) { QStringList rgb = val.split(DIGIT_SEPARATOR); - if(rgb.count() == 3) { + if (rgb.count() == 3) { QColor c(int(rgb[0].toDouble()*255), int(rgb[1].toDouble()*255), int(rgb[2].toDouble()*255)); aListOfMap[viewIndex].insert( COLOR_PROP, c); } - } else if(paramNameStr == VECTOR_MODE_PROP) { + } else if (paramNameStr == VECTOR_MODE_PROP) { aListOfMap[viewIndex].insert( VECTOR_MODE_PROP, val.toInt()); - - } else if(paramNameStr == DEFLECTION_COEFF_PROP) { + } else if (paramNameStr == DEFLECTION_COEFF_PROP) { aListOfMap[viewIndex].insert( DEFLECTION_COEFF_PROP, val.toDouble()); - } else if(paramNameStr == MARKER_TYPE_PROP) { + } else if (paramNameStr == MARKER_TYPE_PROP) { aListOfMap[viewIndex].insert( MARKER_TYPE_PROP, val); - } else if(paramNameStr == MATERIAL_PROP) { + } else if (paramNameStr == MATERIAL_PROP) { aListOfMap[viewIndex].insert( MATERIAL_PROP, val); - } else if(paramNameStr == EDGE_WIDTH_PROP) { - aListOfMap[viewIndex].insert( EDGE_WIDTH_PROP , val); - } else if(paramNameStr == ISOS_WIDTH_PROP) { - aListOfMap[viewIndex].insert( ISOS_WIDTH_PROP , val); + } else if (paramNameStr == EDGE_WIDTH_PROP) { + aListOfMap[viewIndex].insert( EDGE_WIDTH_PROP, val); + } else if (paramNameStr == ISOS_WIDTH_PROP) { + aListOfMap[viewIndex].insert( ISOS_WIDTH_PROP, val); } - - - } // for names/parameters iterator QList lst = getApp()->viewManagers(); @@ -2202,7 +2198,6 @@ void GeometryGUI::restoreVisualParameters (int savePoint) displayer()->Display(entry, true, dynamic_cast(vmodel)); } } - } // for entries iterator // update all VTK and OCC views @@ -2243,7 +2238,7 @@ void GeometryGUI::onViewAboutToShow() /*! \brief Return action by id \param id identifier of the action - \return action + \return action */ QAction* GeometryGUI::getAction(const int id) { return action(id); @@ -2261,32 +2256,32 @@ QAction* GeometryGUI::getAction(const int id) { bool GeometryGUI::renameAllowed( const QString& entry) const { SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication() ); - SalomeApp_Study* appStudy = app ? dynamic_cast( app->activeStudy() ) : 0; + SalomeApp_Study* appStudy = app ? dynamic_cast( app->activeStudy() ) : 0; SalomeApp_DataObject* obj = appStudy ? dynamic_cast(appStudy->findObjectByEntry(entry)) : 0; - + return (app && appStudy && obj && !appStudy->isComponent(entry) && !obj->isReference()); } - /*! Rename object by entry. \param entry entry of the object \param name new name of the object \brief Return \c true if rename operation finished successfully, \c false otherwise. */ -bool GeometryGUI::renameObject( const QString& entry, const QString& name) { - +bool GeometryGUI::renameObject( const QString& entry, const QString& name) +{ bool result = false; - - SalomeApp_Application* app = dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication()); + + SalomeApp_Application* app = + dynamic_cast< SalomeApp_Application* >( SUIT_Session::session()->activeApplication()); SalomeApp_Study* appStudy = app ? dynamic_cast( app->activeStudy() ) : 0; - - if(!appStudy) + + if (!appStudy) return result; - + _PTR(Study) aStudy = appStudy->studyDS(); - - if(!aStudy) + + if (!aStudy) return result; bool aLocked = (_PTR(AttributeStudyProperties)(appStudy->studyDS()->GetProperties()))->IsLocked(); @@ -2311,4 +2306,3 @@ bool GeometryGUI::renameObject( const QString& entry, const QString& name) { } return result; } - diff --git a/src/GEOMGUI/GeometryGUI_Operations.h b/src/GEOMGUI/GeometryGUI_Operations.h index 75e45e43f..e17172e49 100644 --- a/src/GEOMGUI/GeometryGUI_Operations.h +++ b/src/GEOMGUI/GeometryGUI_Operations.h @@ -98,6 +98,7 @@ namespace GEOMOp { OpRevolution = 3201, // MENU NEW ENTITY - GENERATION - REVOLUTION OpFilling = 3202, // MENU NEW ENTITY - GENERATION - FILLING OpPipe = 3203, // MENU NEW ENTITY - GENERATION - EXTRUSION ALONG PATH + OpPipePath = 3204, // MENU NEW ENTITY - GENERATION - RESTORE PATH // EntityGUI -------------------//-------------------------------- Op2dSketcher = 3300, // MENU NEW ENTITY - SKETCHER Op3dSketcher = 3301, // MENU NEW ENTITY - 3D SKETCHER diff --git a/src/GEOMImpl/GEOMImpl_3DSketcherDriver.cxx b/src/GEOMImpl/GEOMImpl_3DSketcherDriver.cxx index d50aec791..3b2255a1f 100755 --- a/src/GEOMImpl/GEOMImpl_3DSketcherDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_3DSketcherDriver.cxx @@ -39,6 +39,8 @@ #include +#include + //======================================================================= //function : GetID //purpose : @@ -214,9 +216,19 @@ Standard_Integer GEOMImpl_3DSketcherDriver::Execute(TFunction_Logbook& log) cons if (aStrVals.Length() != 4) Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command."); + char type = aStrVals.Value(1).Value(4); + char mode = aStrVals.Value(1).Value(5); + double anAngle = aStrVals.Value(2).RealValue() * M_PI/180.0; - double anAngle2 = aStrVals.Value(3).RealValue() * M_PI/180.0; + double anAngle2 = aStrVals.Value(3).RealValue() * M_PI/180.0; double aLength = aStrVals.Value(4).RealValue(); + + double aHeight = aLength * sin(anAngle2); + if (type == 'C') + { + aHeight = aStrVals.Value(3).RealValue(); + anAngle2 = 0.0; + } double aProjectedLength = aLength * cos(anAngle2); @@ -224,21 +236,28 @@ Standard_Integer GEOMImpl_3DSketcherDriver::Execute(TFunction_Logbook& log) cons vp.SetX(aStrVals.Value(2).RealValue()); vp.SetY(aStrVals.Value(3).RealValue()); vp.SetZ(aStrVals.Value(4).RealValue()); - - if (aStrVals.Value(1) == "OXY") { - vp.SetX(p.X() + aProjectedLength * cos(anAngle)); - vp.SetY(p.Y() + aProjectedLength * sin(anAngle)); - vp.SetZ(p.Z() + aLength * sin(anAngle2)); + + gp_XYZ pref = gp::Origin().XYZ(); + if(mode == 'R') + pref = p; + + TCollection_AsciiString aTruncatedCommand = aStrVals.Value(1); + aTruncatedCommand.Trunc(3); + + if (aTruncatedCommand == "OXY") { + vp.SetX(pref.X() + aProjectedLength * cos(anAngle)); + vp.SetY(pref.Y() + aProjectedLength * sin(anAngle)); + vp.SetZ(pref.Z() + aHeight); } - else if (aStrVals.Value(1) == "OYZ") { - vp.SetX(p.X() + aLength * sin(anAngle2)); - vp.SetY(p.Y() + aProjectedLength * cos(anAngle)); - vp.SetZ(p.Z() + aProjectedLength * sin(anAngle)); + else if (aTruncatedCommand == "OYZ") { + vp.SetX(pref.X() + aHeight); + vp.SetY(pref.Y() + aProjectedLength * cos(anAngle)); + vp.SetZ(pref.Z() + aProjectedLength * sin(anAngle)); } - else if (aStrVals.Value(1) == "OXZ") { - vp.SetX(p.X() + aProjectedLength * cos(anAngle)); - vp.SetY(p.Y() + aLength * sin(anAngle2)); - vp.SetZ(p.Z() + aProjectedLength * sin(anAngle)); + else if (aTruncatedCommand == "OXZ") { + vp.SetX(pref.X() + aProjectedLength * cos(anAngle)); + vp.SetY(pref.Y() + aHeight); + vp.SetZ(pref.Z() + aProjectedLength * sin(anAngle)); } else Standard_ConstructionError::Raise("3D Sketcher error: Bad format of command."); @@ -295,7 +314,7 @@ Standard_Integer GEOMImpl_3DSketcherDriver::Execute(TFunction_Logbook& log) cons } else { } - + if (aShape.IsNull()) return 0; aFunction->SetValue(aShape); diff --git a/src/GEOMImpl/GEOMImpl_Gen.cxx b/src/GEOMImpl/GEOMImpl_Gen.cxx index 884da5cb1..f8f02247d 100644 --- a/src/GEOMImpl/GEOMImpl_Gen.cxx +++ b/src/GEOMImpl/GEOMImpl_Gen.cxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #ifdef WNT #pragma warning( disable:4786 ) @@ -54,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -122,6 +122,7 @@ GEOMImpl_Gen::GEOMImpl_Gen() TFunction_DriverTable::Get()->AddDriver(GEOMImpl_CylinderDriver::GetID(), new GEOMImpl_CylinderDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PrismDriver::GetID(), new GEOMImpl_PrismDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PipeDriver::GetID(), new GEOMImpl_PipeDriver()); + TFunction_DriverTable::Get()->AddDriver(GEOMImpl_PipePathDriver::GetID(), new GEOMImpl_PipePathDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_ThruSectionsDriver::GetID(), new GEOMImpl_ThruSectionsDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_RevolutionDriver::GetID(), new GEOMImpl_RevolutionDriver()); TFunction_DriverTable::Get()->AddDriver(GEOMImpl_SphereDriver::GetID(), new GEOMImpl_SphereDriver()); diff --git a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx index dc2ab3599..ffe04f377 100644 --- a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.cxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #include @@ -49,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +69,7 @@ #include #include #include +#include #include @@ -2176,7 +2177,6 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeShellsWithoutPath( } - //============================================================================= /*! * MakePipeBiNormalAlongVector @@ -2236,3 +2236,173 @@ Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::MakePipeBiNormalAlongVector (Han SetErrorCode(OK); return aPipe; } + +//============================================================================= +/*! + * RestorePath + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::RestorePath (Handle(GEOM_Object) theShape, + Handle(GEOM_Object) theBase1, + Handle(GEOM_Object) theBase2) +{ + SetErrorCode(KO); + + if (theShape.IsNull() || theBase1.IsNull() || theBase2.IsNull()) return NULL; + + // Add a new Path object + Handle(GEOM_Object) aPath = GetEngine()->AddObject(GetDocID(), GEOM_PIPE_PATH); + + // Add a new Path function + Handle(GEOM_Function) aFunction = + aPath->AddFunction(GEOMImpl_PipePathDriver::GetID(), PIPE_PATH_TWO_BASES); + if (aFunction.IsNull()) return NULL; + + // Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PipePathDriver::GetID()) return NULL; + + GEOMImpl_IPipePath aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + Handle(GEOM_Function) aRefBase1 = theBase1->GetLastFunction(); + Handle(GEOM_Function) aRefBase2 = theBase2->GetLastFunction(); + + if (aRefShape.IsNull() || aRefBase1.IsNull() || aRefBase2.IsNull()) return NULL; + + aCI.SetShape(aRefShape); + aCI.SetBase1(aRefBase1); + aCI.SetBase2(aRefBase2); + + // Compute the Path value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("PipePath driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode("RestorePath: inappropriate arguments given"); + return NULL; + } + + // Make a Python command + GEOM::TPythonDump(aFunction) << aPath << " = geompy.RestorePath(" + << theShape << ", " << theBase1 << ", " << theBase2 << ")"; + + SetErrorCode(OK); + return aPath; +} + +//============================================================================= +/*! + * RestorePath + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_I3DPrimOperations::RestorePath + (Handle(GEOM_Object) theShape, + const Handle(TColStd_HSequenceOfTransient)& theBase1, + const Handle(TColStd_HSequenceOfTransient)& theBase2) +{ + SetErrorCode(KO); + + if (theShape.IsNull() || theBase1.IsNull() || theBase2.IsNull()) return NULL; + + Standard_Integer nbBases1 = theBase1->Length(); + Standard_Integer nbBases2 = theBase2->Length(); + + if (!nbBases1 || !nbBases2) + return NULL; + + // Add a new Path object + Handle(GEOM_Object) aPath = GetEngine()->AddObject(GetDocID(), GEOM_PIPE_PATH); + + // Add a new Path function + Handle(GEOM_Function) aFunction = + aPath->AddFunction(GEOMImpl_PipePathDriver::GetID(), PIPE_PATH_TWO_SEQS); + if (aFunction.IsNull()) return NULL; + + // Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PipePathDriver::GetID()) return NULL; + + GEOMImpl_IPipePath aCI (aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + Handle(TColStd_HSequenceOfTransient) aSeqBases1 = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqBases2 = new TColStd_HSequenceOfTransient; + + Standard_Integer i; + for (i = 1; i <= nbBases1; i++) { + Handle(Standard_Transient) anItem = theBase1->Value(i); + if (!anItem.IsNull()) { + Handle(GEOM_Object) aBase = Handle(GEOM_Object)::DownCast(anItem); + if (!aBase.IsNull()) { + Handle(GEOM_Function) aRefBase = aBase->GetLastFunction(); + if (!aRefBase.IsNull()) + aSeqBases1->Append(aRefBase); + } + } + } + for (i = 1; i <= nbBases2; i++) { + Handle(Standard_Transient) anItem = theBase2->Value(i); + if (!anItem.IsNull()) { + Handle(GEOM_Object) aBase = Handle(GEOM_Object)::DownCast(anItem); + if (!aBase.IsNull()) { + Handle(GEOM_Function) aRefBase = aBase->GetLastFunction(); + if (!aRefBase.IsNull()) + aSeqBases2->Append(aRefBase); + } + } + } + if (!aSeqBases1->Length() || !aSeqBases2->Length()) return NULL; + + aCI.SetShape(aRefShape); + aCI.SetBaseSeq1(aSeqBases1); + aCI.SetBaseSeq2(aSeqBases2); + + // Compute the Path value + try { +#if OCC_VERSION_LARGE > 0x06010000 + OCC_CATCH_SIGNALS; +#endif + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("PipePath driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode("RestorePath: inappropriate arguments given"); + return NULL; + } + + // Make a Python command + GEOM::TPythonDump pyDump (aFunction); + pyDump << aPath << " = geompy.RestorePathEdges(" << theShape << ", ["; + for (i = 1; i <= nbBases1; i++) { + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theBase1->Value(i)); + if (!anObj.IsNull()) { + pyDump << anObj; + if (i < nbBases1) + pyDump << ", "; + } + } + pyDump<< "], ["; + for (i = 1; i <= nbBases2; i++) { + Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theBase2->Value(i)); + if (!anObj.IsNull()) { + pyDump << anObj; + if (i < nbBases2) + pyDump << ", "; + } + } + pyDump << "])"; + + SetErrorCode(OK); + return aPath; +} diff --git a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx index c567d0333..6cd2dd25d 100644 --- a/src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_I3DPrimOperations.hxx @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #ifndef _GEOMImpl_I3DPrimOperations_HXX_ #define _GEOMImpl_I3DPrimOperations_HXX_ @@ -131,14 +130,21 @@ class GEOMImpl_I3DPrimOperations : public GEOM_IOperations { bool theWithContact, bool theWithCorrections); - Standard_EXPORT Handle(GEOM_Object) MakePipeShellsWithoutPath( - const Handle(TColStd_HSequenceOfTransient)& theBases, - const Handle(TColStd_HSequenceOfTransient)& theLocations); + Standard_EXPORT Handle(GEOM_Object) MakePipeShellsWithoutPath + (const Handle(TColStd_HSequenceOfTransient)& theBases, + const Handle(TColStd_HSequenceOfTransient)& theLocations); Standard_EXPORT Handle(GEOM_Object) MakePipeBiNormalAlongVector (Handle(GEOM_Object) theBase, Handle(GEOM_Object) thePath, Handle(GEOM_Object) theVec); + Standard_EXPORT Handle(GEOM_Object) RestorePath (Handle(GEOM_Object) theShape, + Handle(GEOM_Object) theBase1, + Handle(GEOM_Object) theBase2); + + Standard_EXPORT Handle(GEOM_Object) RestorePath (Handle(GEOM_Object) theShape, + const Handle(TColStd_HSequenceOfTransient)& theBase1, + const Handle(TColStd_HSequenceOfTransient)& theBase2); }; #endif diff --git a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx index 7fc3b43bc..9b982e735 100644 --- a/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IAdvancedOperations.cxx @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,7 @@ #include #include #include +#include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC @@ -1138,6 +1140,11 @@ bool GEOMImpl_IAdvancedOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Objec return false; } + // Copy source shape + TopoDS_Shape aShapeCopy; + TColStd_IndexedDataMapOfTransientTransient aMapTShapes; + TNaming_CopyShape::CopyTool(Te7->GetValue(), aMapTShapes, aShapeCopy); + Handle(GEOM_Object) Te8 = myShapesOperations->MakeGlueFaces(Te7, 1e-7, true); if (Te8.IsNull()) { SetErrorCode("Impossible to glue faces of TShape"); @@ -1145,6 +1152,34 @@ bool GEOMImpl_IAdvancedOperations::MakePipeTShapeMirrorAndGlue(Handle(GEOM_Objec } TopoDS_Shape aShape = Te8->GetValue(); + BRepCheck_Analyzer anAna (aShape, Standard_True); + + if (!anAna.IsValid()) { + // Try to do gluing with the tolerance equal to maximal + // tolerance of vertices of the source shape. + Standard_Real aTolMax = -RealLast(); + + for (TopExp_Explorer ExV (aShapeCopy, TopAbs_VERTEX); ExV.More(); ExV.Next()) { + TopoDS_Vertex aVertex = TopoDS::Vertex(ExV.Current()); + Standard_Real aTol = BRep_Tool::Tolerance(aVertex); + + if (aTol > aTolMax) { + aTolMax = aTol; + } + } + + // Perform gluing + Te7->GetLastFunction()->SetValue(aShapeCopy); + Te8 = myShapesOperations->MakeGlueFaces(Te7, aTolMax, true); + + if (Te8.IsNull()) { + SetErrorCode("Impossible to glue faces of TShape"); + return false; + } + + aShape = Te8->GetValue(); + } + theShape->GetLastFunction()->SetValue(aShape); @@ -2252,7 +2287,14 @@ Handle(GEOM_Object) GEOMImpl_IAdvancedOperations::MakeDividedDisk (double theR, int theOrientation, int thePattern) { SetErrorCode(KO); - + + if (theOrientation != 1 && + theOrientation != 2 && + theOrientation != 3) + { + SetErrorCode("theOrientation must be 1(=OXY), 2(=OYZ) or 3(=OZX)"); + return NULL; + } //Add a new object Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_DIVIDEDDISK); diff --git a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx index f4508d35b..22237b786 100644 --- a/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_ICurvesOperations.cxx @@ -975,15 +975,17 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakeCurveParametric return NULL; } - Handle(TColStd_HArray1OfReal) aCoordsArray = new TColStd_HArray1OfReal (1, PyList_Size( coords ) * 3); + int lsize = PyList_Size( coords ); - if(PyList_Size( coords ) <= 0) { + if(lsize <= 0) { SetErrorCode("Empty list of the points, please check input parameters !!!"); return NULL; } + Handle(TColStd_HArray1OfReal) aCoordsArray = new TColStd_HArray1OfReal (1, lsize * 3); + int k=1; - for ( Py_ssize_t i = 0; i< PyList_Size( coords ); ++i ) { + for ( Py_ssize_t i = 0; i < lsize; ++i ) { PyObject* coord = PyList_GetItem( coords, i ); if (coord != NULL) { for ( Py_ssize_t j = 0; j < PyList_Size(coord); ++j) { @@ -1016,7 +1018,7 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakeCurveParametric GEOMImpl_IPolyline aCI (aFunction); - aCI.SetLength(PyList_Size( coords )); + aCI.SetLength(lsize); aCI.SetConstructorType(COORD_CONSTRUCTOR); aCI.SetIsClosed(false); aCI.SetCoordinates(aCoordsArray); @@ -1036,7 +1038,7 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakeCurveParametric GEOMImpl_ISpline aCI (aFunction); - aCI.SetLength(PyList_Size( coords )); + aCI.SetLength(lsize); aCI.SetConstructorType(COORD_CONSTRUCTOR); aCI.SetIsClosed(false); aCI.SetCoordinates(aCoordsArray); @@ -1056,7 +1058,7 @@ Handle(GEOM_Object) GEOMImpl_ICurvesOperations::MakeCurveParametric GEOMImpl_ISpline aCI (aFunction); aCI.SetConstructorType(COORD_CONSTRUCTOR); - aCI.SetLength(PyList_Size( coords )); + aCI.SetLength(lsize); aCI.SetIsClosed(false); aCI.SetDoReordering(false); aCI.SetCoordinates(aCoordsArray); diff --git a/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx b/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx index d806a4a2d..afd889529 100644 --- a/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IInsertOperations.cxx @@ -246,9 +246,22 @@ Handle(GEOM_Object) GEOMImpl_IInsertOperations::Import } //Make a Python command - if( theFormatName != "IGES_UNIT" ) { - GEOM::TPythonDump(aFunction) << result << " = geompy.ImportFile(\"" - << theFileName.ToCString() << "\", \"" << theFormatName.ToCString() << "\")"; + if (theFormatName != "IGES_UNIT") { + GEOM::TPythonDump pd (aFunction); + if (theFormatName == "BREP") + pd << result << " = geompy.ImportBREP(\"" << theFileName.ToCString() << "\")"; + else if (theFormatName == "IGES") + pd << result << " = geompy.ImportIGES(\"" << theFileName.ToCString() << "\")"; + else if (theFormatName == "IGES_SCALE") + pd << result << " = geompy.ImportIGES(\"" << theFileName.ToCString() << "\", True)"; + else if (theFormatName == "STEP") + pd << result << " = geompy.ImportSTEP(\"" << theFileName.ToCString() << "\")"; + else if (theFormatName == "STEP_SCALE") + pd << result << " = geompy.ImportSTEP(\"" << theFileName.ToCString() << "\", True)"; + else { + pd << result << " = geompy.ImportFile(\"" + << theFileName.ToCString() << "\", \"" << theFormatName.ToCString() << "\")"; + } } SetErrorCode(OK); @@ -260,9 +273,9 @@ Handle(GEOM_Object) GEOMImpl_IInsertOperations::Import gp_Pnt P = BRep_Tool::Pnt(V); double scale = P.X(); TCollection_AsciiString aUnitName = "UNIT_M"; - if( fabs(scale-0.01) < 1.e-6 ) + if (fabs(scale-0.01) < 1.e-6) aUnitName = "UNIT_CM"; - else if( fabs(scale-0.001) < 1.e-6 ) + else if (fabs(scale-0.001) < 1.e-6) aUnitName = "UNIT_MM"; //cout<<"IIO: aUnitName = "<SetReference(PIPE_PATH_SHAPE, theShape); } + void SetBase1 (Handle(GEOM_Function) theBase1) { _func->SetReference(PIPE_PATH_BASE1, theBase1); } + void SetBase2 (Handle(GEOM_Function) theBase2) { _func->SetReference(PIPE_PATH_BASE2, theBase2); } + void SetBaseSeq1 (const Handle(TColStd_HSequenceOfTransient)& theBase1) + { _func->SetReferenceList(PIPE_PATH_SEQ1, theBase1); } + void SetBaseSeq2 (const Handle(TColStd_HSequenceOfTransient)& theBase2) + { _func->SetReferenceList(PIPE_PATH_SEQ2, theBase2); } + + Handle(GEOM_Function) GetShape() { return _func->GetReference(PIPE_PATH_SHAPE); } + Handle(GEOM_Function) GetBase1() { return _func->GetReference(PIPE_PATH_BASE1); } + Handle(GEOM_Function) GetBase2() { return _func->GetReference(PIPE_PATH_BASE2); } + Handle(TColStd_HSequenceOfTransient) GetBaseSeq1 () + { return _func->GetReferenceList(PIPE_PATH_SEQ1); } + Handle(TColStd_HSequenceOfTransient) GetBaseSeq2 () + { return _func->GetReferenceList(PIPE_PATH_SEQ2); } + + protected: + + Handle(GEOM_Function) _func; +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx b/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx index 703735b22..72c03e5bb 100644 --- a/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PartitionDriver.cxx @@ -147,15 +147,10 @@ Standard_Integer GEOMImpl_PartitionDriver::Execute(TFunction_Logbook& log) const if (aShape_i.IsNull()) { Standard_NullObject::Raise("In Partition a shape is null"); } - // - //BRepBuilderAPI_Copy aCopyTool (aShape_i); + TopoDS_Shape aShape_i_copy; TNaming_CopyShape::CopyTool(aShape_i, aMapTShapes, aShape_i_copy); - //if (aCopyTool.IsDone()) - // aShape_i_copy = aCopyTool.Shape(); - //else - // Standard_NullObject::Raise("Bad shape detected"); - // + // fill aCopyMap for history TopTools_IndexedMapOfShape aShape_i_inds; TopTools_IndexedMapOfShape aShape_i_copy_inds; @@ -384,11 +379,17 @@ Standard_Integer GEOMImpl_PartitionDriver::Execute(TFunction_Logbook& log) const } aShape = PS.Shape(); - if (aShape.IsNull()) return 0; + if (aShape.IsNull()) { + // Mantis issue 22009 + if (PS.ErrorStatus() == 10 && PS.Tools().Extent() == 0 && PS.Shapes().Extent() == 1) + aShape = PS.Shapes().First(); + else + return 0; + } //Alternative case to check not valid partition IPAL21418 TopoDS_Iterator It (aShape, Standard_True, Standard_True); - int nbSubshapes=0; + int nbSubshapes = 0; for (; It.More(); It.Next()) nbSubshapes++; if (!nbSubshapes) diff --git a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx index 21475ee42..400c2a03c 100644 --- a/src/GEOMImpl/GEOMImpl_PipeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_PipeDriver.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -41,15 +42,14 @@ #include #include +#include +#include #include #include #include +#include #include #include -#include -#include -#include -#include #include #include @@ -68,6 +68,8 @@ #include #include +#include + #include #include #include @@ -88,6 +90,7 @@ #include #include + #include #include #include @@ -100,7 +103,7 @@ //======================================================================= const Standard_GUID& GEOMImpl_PipeDriver::GetID() { - static Standard_GUID aPipeDriver("FF1BBB19-5D14-4df2-980B-3A668264EA16"); + static Standard_GUID aPipeDriver ("FF1BBB19-5D14-4df2-980B-3A668264EA16"); return aPipeDriver; } @@ -2277,23 +2280,23 @@ static TopoDS_Shape CreatePipeBiNormalAlongVector(const TopoDS_Wire& aWirePath, //function : Execute //purpose : //======================================================================= -Standard_Integer GEOMImpl_PipeDriver::Execute(TFunction_Logbook& log) const +Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const { - //cout<<"PipeDriver::Execute"<GetType(); + + GEOMImpl_IPipe* aCI = 0; if (aType == PIPE_BASE_PATH) - aCI = new GEOMImpl_IPipe(aFunction); + aCI = new GEOMImpl_IPipe (aFunction); else if (aType == PIPE_DIFFERENT_SECTIONS) - aCI = new GEOMImpl_IPipeDiffSect(aFunction); + aCI = new GEOMImpl_IPipeDiffSect (aFunction); else if (aType == PIPE_SHELL_SECTIONS) - aCI = new GEOMImpl_IPipeShellSect(aFunction); + aCI = new GEOMImpl_IPipeShellSect (aFunction); else if (aType == PIPE_SHELLS_WITHOUT_PATH) - aCI = new GEOMImpl_IPipeShellSect(aFunction); + aCI = new GEOMImpl_IPipeShellSect (aFunction); else if (aType == PIPE_BI_NORMAL_ALONG_VECTOR) - aCI = new GEOMImpl_IPipeBiNormal(aFunction); + aCI = new GEOMImpl_IPipeBiNormal (aFunction); else return 0; diff --git a/src/GEOMImpl/GEOMImpl_PipePathDriver.cxx b/src/GEOMImpl/GEOMImpl_PipePathDriver.cxx new file mode 100644 index 000000000..5acf28f12 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PipePathDriver.cxx @@ -0,0 +1,242 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if OCC_VERSION_LARGE > 0x06050300 +#include +#endif + +#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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "utilities.h" + +//======================================================================= +//function : GetID +//purpose : +//======================================================================= +const Standard_GUID& GEOMImpl_PipePathDriver::GetID() +{ + static Standard_GUID aPipePathDriver ("FF1BBB19-5D14-4df2-980B-3A668264EA17"); + return aPipePathDriver; +} + +//======================================================================= +//function : GEOMImpl_PipePathDriver +//purpose : +//======================================================================= +GEOMImpl_PipePathDriver::GEOMImpl_PipePathDriver() +{ +} + +//======================================================================= +//function : Execute +//purpose : +//======================================================================= +Standard_Integer GEOMImpl_PipePathDriver::Execute (TFunction_Logbook& log) const +{ + if (Label().IsNull()) return 0; + Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); + Standard_Integer aType = aFunction->GetType(); + + TopoDS_Shape aRes; + + // RestorePath + if (aType == PIPE_PATH_TWO_BASES) { + GEOMImpl_IPipePath aPI (aFunction); + + Handle(GEOM_Function) aRefShape = aPI.GetShape(); + Handle(GEOM_Function) aRefBase1 = aPI.GetBase1(); + Handle(GEOM_Function) aRefBase2 = aPI.GetBase2(); + + TopoDS_Shape aShape = aRefShape->GetValue(); + TopoDS_Shape aBase1 = aRefBase1->GetValue(); + TopoDS_Shape aBase2 = aRefBase2->GetValue(); + + if (aShape.IsNull() || aBase1.IsNull() || aBase2.IsNull()) + Standard_NullObject::Raise("RestorePath aborted : null argument"); + +#if OCC_VERSION_LARGE > 0x06050300 + BRepOffsetAPI_MiddlePath aMPB (aShape, aBase1, aBase2); + aMPB.Build(); + if (aMPB.IsDone()) { + aRes = aMPB.Shape(); + } +#else + Standard_NullObject::Raise("RestorePath is not implemented in used OCCT version"); +#endif + } + else if (aType == PIPE_PATH_TWO_SEQS) { + GEOMImpl_IPipePath aPI (aFunction); + + Handle(GEOM_Function) aRefShape = aPI.GetShape(); + TopoDS_Shape aShape = aRefShape->GetValue(); + + Handle(TColStd_HSequenceOfTransient) aBaseSeq1 = aPI.GetBaseSeq1(); + Handle(TColStd_HSequenceOfTransient) aBaseSeq2 = aPI.GetBaseSeq2(); + + TopoDS_Shape aBase1; + TopoDS_Shape aBase2; + + if (aBaseSeq1->Length() == 1 && aBaseSeq2->Length() == 1) { + Handle(GEOM_Function) aRefShape1 = Handle(GEOM_Function)::DownCast(aBaseSeq1->Value(1)); + Handle(GEOM_Function) aRefShape2 = Handle(GEOM_Function)::DownCast(aBaseSeq2->Value(1)); + aBase1 = aRefShape1->GetValue(); + aBase2 = aRefShape2->GetValue(); + } + else { + aBase1 = GEOMImpl_ShapeDriver::MakeWireFromEdges(aBaseSeq1, Precision::Confusion()); + aBase2 = GEOMImpl_ShapeDriver::MakeWireFromEdges(aBaseSeq2, Precision::Confusion()); + } + + if (aShape.IsNull() || aBase1.IsNull() || aBase2.IsNull()) + Standard_NullObject::Raise("RestorePath aborted : null argument"); + +#if OCC_VERSION_LARGE > 0x06050300 + BRepOffsetAPI_MiddlePath aMPB (aShape, aBase1, aBase2); + aMPB.Build(); + if (aMPB.IsDone()) { + aRes = aMPB.Shape(); + } +#else + Standard_NullObject::Raise("RestorePath is not implemented in used OCCT version"); +#endif + } + else { + } + + if (aRes.IsNull()) return 0; + + aFunction->SetValue(aRes); + log.SetTouched(Label()); + + return 1; +} + +//======================================================================= +//function : GEOMImpl_PipePathDriver_Type_ +//purpose : +//======================================================================= +Standard_EXPORT Handle_Standard_Type& GEOMImpl_PipePathDriver_Type_() +{ + static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver); + if (aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver); + static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared); + if (aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared); + static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient); + if (aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient); + + static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL}; + static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_PipePathDriver", + sizeof(GEOMImpl_PipePathDriver), + 1, + (Standard_Address)_Ancestors, + (Standard_Address)NULL); + + return _aType; +} + +//======================================================================= +//function : DownCast +//purpose : +//======================================================================= +const Handle(GEOMImpl_PipePathDriver) Handle(GEOMImpl_PipePathDriver)::DownCast(const Handle(Standard_Transient)& AnObject) +{ + Handle(GEOMImpl_PipePathDriver) _anOtherObject; + + if (!AnObject.IsNull()) { + if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_PipePathDriver))) { + _anOtherObject = Handle(GEOMImpl_PipePathDriver)((Handle(GEOMImpl_PipePathDriver)&)AnObject); + } + } + + return _anOtherObject; +} diff --git a/src/GEOMImpl/GEOMImpl_PipePathDriver.hxx b/src/GEOMImpl/GEOMImpl_PipePathDriver.hxx new file mode 100644 index 000000000..36bf36314 --- /dev/null +++ b/src/GEOMImpl/GEOMImpl_PipePathDriver.hxx @@ -0,0 +1,167 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// File : GEOMImpl_PipePathDriver.ixx +// Module : GEOMImpl + +#ifndef _GEOMImpl_PipePathDriver_HeaderFile +#define _GEOMImpl_PipePathDriver_HeaderFile + +#ifndef _TColStd_SequenceOfExtendedString_HeaderFile +#include +#endif +#ifndef _Standard_TypeMismatch_HeaderFile +#include +#endif + +#ifndef _Standard_HeaderFile +#include +#endif + +#ifndef _Standard_Macro_HeaderFile +#include +#endif +#ifndef _Standard_HeaderFile +#include +#endif +#ifndef _Standard_GUID_HeaderFile +#include +#endif + +#ifndef _Handle_TFunction_Driver_HeaderFile +#include +#endif + + +class Standard_Transient; +class Handle_Standard_Type; +class Handle(TFunction_Driver); +class GEOMImpl_PipePathDriver; + +Standard_EXPORT Handle_Standard_Type& STANDARD_TYPE(GEOMImpl_PipePathDriver); + +class Handle(GEOMImpl_PipePathDriver) : public Handle(TFunction_Driver) { + public: + inline void* operator new(size_t,void* anAddress) + { + return anAddress; + } + inline void* operator new(size_t size) + { + return Standard::Allocate(size); + } + inline void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + Handle(GEOMImpl_PipePathDriver)():Handle(TFunction_Driver)() {} + Handle(GEOMImpl_PipePathDriver)(const Handle(GEOMImpl_PipePathDriver)& aHandle) : Handle(TFunction_Driver)(aHandle) + { + } + + Handle(GEOMImpl_PipePathDriver)(const GEOMImpl_PipePathDriver* anItem) : Handle(TFunction_Driver)((TFunction_Driver *)anItem) + { + } + + Handle(GEOMImpl_PipePathDriver)& operator=(const Handle(GEOMImpl_PipePathDriver)& aHandle) + { + Assign(aHandle.Access()); + return *this; + } + + Handle(GEOMImpl_PipePathDriver)& operator=(const GEOMImpl_PipePathDriver* anItem) + { + Assign((Standard_Transient *)anItem); + return *this; + } + + GEOMImpl_PipePathDriver* operator->() + { + return (GEOMImpl_PipePathDriver *)ControlAccess(); + } + + GEOMImpl_PipePathDriver* operator->() const + { + return (GEOMImpl_PipePathDriver *)ControlAccess(); + } + + Standard_EXPORT ~Handle(GEOMImpl_PipePathDriver)() {}; + + Standard_EXPORT static const Handle(GEOMImpl_PipePathDriver) DownCast(const Handle(Standard_Transient)& AnObject); +}; + +#ifndef _TFunction_Driver_HeaderFile +#include +#endif +#ifndef _TFunction_Logbook_HeaderFile +#include +#endif +#ifndef _Standard_CString_HeaderFile +#include +#endif + +#include +#include +#include + +class TColStd_SequenceOfExtendedString; + + +class GEOMImpl_PipePathDriver : public TFunction_Driver { + +public: + + inline void* operator new(size_t,void* anAddress) + { + return anAddress; + } + inline void* operator new(size_t size) + { + return Standard::Allocate(size); + } + inline void operator delete(void *anAddress) + { + if (anAddress) Standard::Free((Standard_Address&)anAddress); + } + + // Methods PUBLIC + // + Standard_EXPORT GEOMImpl_PipePathDriver(); + Standard_EXPORT virtual Standard_Integer Execute(TFunction_Logbook& log) const; + Standard_EXPORT virtual void Validate(TFunction_Logbook&) const {} + Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const + { return Standard_True; } + Standard_EXPORT static const Standard_GUID& GetID(); + Standard_EXPORT ~GEOMImpl_PipePathDriver() {}; + + // Type management + // + Standard_EXPORT friend Handle_Standard_Type& GEOMImpl_PipePathDriver_Type_(); + Standard_EXPORT const Handle(Standard_Type)& DynamicType() const + { return STANDARD_TYPE(GEOMImpl_PipePathDriver) ; } + Standard_EXPORT Standard_Boolean IsKind(const Handle(Standard_Type)& AType) const + { return (STANDARD_TYPE(GEOMImpl_PipePathDriver) == AType || + TFunction_Driver::IsKind(AType)); } + +}; + +#endif diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx index 9f2ec8081..12962ffc7 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.cxx @@ -133,66 +133,12 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const if (aType == WIRE_EDGES) { Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes(); - TopoDS_Wire aWire; - B.MakeWire(aWire); - // add edges - for (unsigned int ind = 1; ind <= aShapes->Length(); ind++) { - Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind)); - TopoDS_Shape aShape_i = aRefShape->GetValue(); - if (aShape_i.IsNull()) { - Standard_NullObject::Raise("Shape for wire construction is null"); - } - if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) { - TopExp_Explorer exp (aShape_i, TopAbs_EDGE); - for (; exp.More(); exp.Next()) - B.Add(aWire, TopoDS::Edge(exp.Current())); - } else { - Standard_TypeMismatch::Raise - ("Shape for wire construction is neither an edge nor a wire"); - } - } - - // fix edges order - Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire; - aFW->Load(aWire); - aFW->FixReorder(); - - if (aFW->StatusReorder(ShapeExtend_FAIL1)) { - Standard_ConstructionError::Raise("Wire construction failed: several loops detected"); - } else if (aFW->StatusReorder(ShapeExtend_FAIL)) { - Standard_ConstructionError::Raise("Wire construction failed"); - } else { - } - - // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance Standard_Real aTolerance = aCI.GetTolerance(); if (aTolerance < Precision::Confusion()) aTolerance = Precision::Confusion(); - aFW->ClosedWireMode() = Standard_False; - aFW->FixConnected(aTolerance); - if (aFW->StatusConnected(ShapeExtend_FAIL)) { - Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire"); - } - // IMP 0019766 - if (aFW->StatusConnected(ShapeExtend_DONE3)) { - // Confused with but not Analyzer.Precision(), set the same - aFW->FixGapsByRangesMode() = Standard_True; - if (aFW->FixGaps3d()) { - Handle(ShapeExtend_WireData) sbwd = aFW->WireData(); - Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge; - for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) { - TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge)); - aFe->FixVertexTolerance(aEdge); - aFe->FixSameParameter(aEdge); - } - } - else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) { - Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps"); - } - } - aShape = aFW->WireAPIMake(); + aShape = MakeWireFromEdges(aShapes, aTolerance); } else if (aType == FACE_WIRE) { Handle(GEOM_Function) aRefBase = aCI.GetBase(); @@ -594,6 +540,10 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const BRepCheck_Analyzer ana (aShape, false); if (!ana.IsValid()) { //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result"); + // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles + Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape); + aSfs->Perform(); + aShape = aSfs->Shape(); } aFunction->SetValue(aShape); @@ -606,6 +556,73 @@ Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const return 1; } +TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs, + const Standard_Real theTolerance) +{ + BRep_Builder B; + + TopoDS_Wire aWire; + B.MakeWire(aWire); + + // add edges + for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) { + Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind)); + TopoDS_Shape aShape_i = aRefShape->GetValue(); + if (aShape_i.IsNull()) { + Standard_NullObject::Raise("Shape for wire construction is null"); + } + if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) { + TopExp_Explorer exp (aShape_i, TopAbs_EDGE); + for (; exp.More(); exp.Next()) + B.Add(aWire, TopoDS::Edge(exp.Current())); + } else { + Standard_TypeMismatch::Raise + ("Shape for wire construction is neither an edge nor a wire"); + } + } + + // fix edges order + Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire; + aFW->Load(aWire); + aFW->FixReorder(); + + if (aFW->StatusReorder(ShapeExtend_FAIL1)) { + Standard_ConstructionError::Raise("Wire construction failed: several loops detected"); + } + else if (aFW->StatusReorder(ShapeExtend_FAIL)) { + Standard_ConstructionError::Raise("Wire construction failed"); + } + else { + } + + // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance + aFW->ClosedWireMode() = Standard_False; + aFW->FixConnected(theTolerance); + if (aFW->StatusConnected(ShapeExtend_FAIL)) { + Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire"); + } + // IMP 0019766 + if (aFW->StatusConnected(ShapeExtend_DONE3)) { + // Confused with but not Analyzer.Precision(), set the same + aFW->FixGapsByRangesMode() = Standard_True; + if (aFW->FixGaps3d()) { + Handle(ShapeExtend_WireData) sbwd = aFW->WireData(); + Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge; + for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) { + TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge)); + aFe->FixVertexTolerance(aEdge); + aFe->FixSameParameter(aEdge); + } + } + else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) { + Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps"); + } + } + aWire = aFW->WireAPIMake(); + + return aWire; +} + TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire, const Standard_Real LinTol, const Standard_Real AngTol) diff --git a/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx b/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx index 653ad7e13..87c55c501 100644 --- a/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx +++ b/src/GEOMImpl/GEOMImpl_ShapeDriver.hxx @@ -120,6 +120,8 @@ class Handle(GEOMImpl_ShapeDriver) : public Handle(TFunction_Driver) { #include #include +#include +#include class TColStd_SequenceOfExtendedString; @@ -151,9 +153,13 @@ public: Standard_EXPORT Standard_Boolean MustExecute(const TFunction_Logbook&) const { return Standard_True; } Standard_EXPORT static const Standard_GUID& GetID(); - Standard_EXPORT static TopoDS_Edge MakeEdgeFromWire(const TopoDS_Shape& aWire, - const Standard_Real LinTol, - const Standard_Real AngTol); + Standard_EXPORT static TopoDS_Edge MakeEdgeFromWire (const TopoDS_Shape& aWire, + const Standard_Real LinTol, + const Standard_Real AngTol); + + Standard_EXPORT static TopoDS_Wire MakeWireFromEdges + (const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs, + const Standard_Real theTolerance); // Type management // diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index 5182f8cdc..4aeed6398 100755 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -100,6 +100,8 @@ #define GEOM_EXTRUDED_BOSS 47 +#define GEOM_PIPE_PATH 48 + //GEOM_Function types #define COPY_WITH_REF 1 @@ -214,6 +216,10 @@ #define PIPE_SHELLS_WITHOUT_PATH 4 #define PIPE_BI_NORMAL_ALONG_VECTOR 5 +// RestorePath +#define PIPE_PATH_TWO_BASES 1 +#define PIPE_PATH_TWO_SEQS 2 + #define THRUSECTIONS_RULED 1 #define THRUSECTIONS_SMOOTHED 2 diff --git a/src/GEOMImpl/Makefile.am b/src/GEOMImpl/Makefile.am index 69cda82da..8ce12ca2e 100644 --- a/src/GEOMImpl/Makefile.am +++ b/src/GEOMImpl/Makefile.am @@ -83,6 +83,7 @@ salomeinclude_HEADERS = \ GEOMImpl_ITorus.hxx \ GEOMImpl_IPrism.hxx \ GEOMImpl_IPipe.hxx \ + GEOMImpl_IPipePath.hxx \ GEOMImpl_IRevolution.hxx \ GEOMImpl_IMeasure.hxx \ GEOMImpl_IShapes.hxx \ @@ -111,6 +112,7 @@ salomeinclude_HEADERS = \ GEOMImpl_TorusDriver.hxx \ GEOMImpl_PrismDriver.hxx \ GEOMImpl_PipeDriver.hxx \ + GEOMImpl_PipePathDriver.hxx \ GEOMImpl_ThruSectionsDriver.hxx \ GEOMImpl_RevolutionDriver.hxx \ GEOMImpl_ShapeDriver.hxx \ @@ -185,6 +187,7 @@ dist_libGEOMimpl_la_SOURCES = \ GEOMImpl_TorusDriver.cxx \ GEOMImpl_PrismDriver.cxx \ GEOMImpl_PipeDriver.cxx \ + GEOMImpl_PipePathDriver.cxx \ GEOMImpl_ThruSectionsDriver.cxx \ GEOMImpl_RevolutionDriver.cxx \ GEOMImpl_ShapeDriver.cxx \ diff --git a/src/GEOMToolsGUI/GEOMToolsGUI.cxx b/src/GEOMToolsGUI/GEOMToolsGUI.cxx index e83523ea4..01f2c182f 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI.cxx @@ -649,9 +649,9 @@ bool GEOMToolsGUI::Import() // jfa 21.08.2012 for mantis issue 21511 (STEP file units) CORBA::String_var aUnits = aInsOp->ReadValue(fileN, fileT, "LEN_UNITS"); - TCollection_AsciiString aUnitsStr (aUnits.in()); + QString aUnitsStr (aUnits.in()); bool needConvert = true; - if (aUnitsStr.IsEmpty() || aUnitsStr == "UNIT_M") + if (aUnitsStr.isEmpty() || aUnitsStr == "M" || aUnitsStr.toLower() == "metre") needConvert = false; if (needConvert) { @@ -664,7 +664,7 @@ bool GEOMToolsGUI::Import() if (i < fileNames.count() - 1) btns = btns | SUIT_MessageBox::YesToAll | SUIT_MessageBox::NoToAll; igesAnswer = SUIT_MessageBox::question(app->desktop(), "Question",//tr("WRN_WARNING"), - tr("GEOM_SCALE_DIMENSIONS"), + tr("GEOM_SCALE_DIMENSIONS").arg(aUnitsStr), btns | SUIT_MessageBox::Cancel, SUIT_MessageBox::No); switch (igesAnswer) { diff --git a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx index c73767ca2..526a9b1e4 100644 --- a/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx +++ b/src/GEOMToolsGUI/GEOMToolsGUI_1.cxx @@ -111,10 +111,10 @@ // If the next macro is defined, autocolor feature works for all sub-shapes; // if it is undefined, autocolor feature works for groups only -//#define GENERAL_AUTOCOLOR +#define GENERAL_AUTOCOLOR // Below macro, when uncommented, switches on simplified (more performant) algorithm // of auto-color picking up -//#define SIMPLE_AUTOCOLOR +#define SIMPLE_AUTOCOLOR void GEOMToolsGUI::OnCheckGeometry() { diff --git a/src/GEOM_I/GEOM_Gen_i.cc b/src/GEOM_I/GEOM_Gen_i.cc index fe877f791..3dec74459 100644 --- a/src/GEOM_I/GEOM_Gen_i.cc +++ b/src/GEOM_I/GEOM_Gen_i.cc @@ -28,6 +28,7 @@ #include "GEOM_Gen_i.hh" #include "GEOM_Object_i.hh" +#include "GEOM_version.h" #include #include @@ -2551,6 +2552,16 @@ char* GEOM_Gen_i::getObjectInfo(CORBA::Long studyId, const char* entry) return ret; } +// Version information +char* GEOM_Gen_i::getVersion() +{ +#if GEOM_DEVELOPMENT + return CORBA::string_dup(GEOM_VERSION_STR"dev"); +#else + return CORBA::string_dup(GEOM_VERSION_STR); +#endif +} + //===================================================================================== // EXPORTED METHODS //===================================================================================== diff --git a/src/GEOM_I/GEOM_Gen_i.hh b/src/GEOM_I/GEOM_Gen_i.hh index 9e65dea0c..021ce1bcb 100644 --- a/src/GEOM_I/GEOM_Gen_i.hh +++ b/src/GEOM_I/GEOM_Gen_i.hh @@ -264,6 +264,9 @@ class GEOM_I_EXPORT GEOM_Gen_i: virtual public POA_GEOM::GEOM_Gen, virtual publi virtual bool hasObjectInfo(); virtual char* getObjectInfo(CORBA::Long studyId, const char* entry); + // Version information + virtual char* getVersion(); + //-----------------------------------------------------------------------// // Internal methods // //-----------------------------------------------------------------------// diff --git a/src/GEOM_I/GEOM_I3DPrimOperations_i.cc b/src/GEOM_I/GEOM_I3DPrimOperations_i.cc index 76febf836..95948ed24 100644 --- a/src/GEOM_I/GEOM_I3DPrimOperations_i.cc +++ b/src/GEOM_I/GEOM_I3DPrimOperations_i.cc @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #include @@ -1096,7 +1095,6 @@ GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeShellsWithoutPath return GetObject(anObject); } - //============================================================================= /*! * MakePipeBiNormalAlongVector @@ -1127,3 +1125,81 @@ GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::MakePipeBiNormalAlongVector return GetObject(anObject); } + +//============================================================================= +/*! + * RestorePath + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::RestorePath + (GEOM::GEOM_Object_ptr theShape, + GEOM::GEOM_Object_ptr theBase1, + GEOM::GEOM_Object_ptr theBase2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + // Set a not done flag + GetOperations()->SetNotDone(); + + // Get the reference objects + Handle(GEOM_Object) aShape = GetObjectImpl(theShape); + Handle(GEOM_Object) aBase1 = GetObjectImpl(theBase1); + Handle(GEOM_Object) aBase2 = GetObjectImpl(theBase2); + + if (aShape.IsNull() || aBase1.IsNull() || aBase2.IsNull()) return aGEOMObject._retn(); + + // Create the Path + Handle(GEOM_Object) anObject = GetOperations()->RestorePath(aShape, aBase1, aBase2); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + +//============================================================================= +/*! + * RestorePathEdges + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_I3DPrimOperations_i::RestorePathEdges + (GEOM::GEOM_Object_ptr theShape, + const GEOM::ListOfGO& theBase1, + const GEOM::ListOfGO& theBase2) +{ + GEOM::GEOM_Object_var aGEOMObject; + + // Set a not done flag + GetOperations()->SetNotDone(); + + // Get the reference objects + Handle(GEOM_Object) aShape = GetObjectImpl(theShape); + if (aShape.IsNull()) return aGEOMObject._retn(); + + Handle(TColStd_HSequenceOfTransient) aSeqBases1 = new TColStd_HSequenceOfTransient; + Handle(TColStd_HSequenceOfTransient) aSeqBases2 = new TColStd_HSequenceOfTransient; + + int ind; + int aNbBases1 = theBase1.length(); + int aNbBases2 = theBase2.length(); + + for (ind = 0; ind < aNbBases1; ind++) { + Handle(GEOM_Object) aBase = GetObjectImpl(theBase1[ind]); + if (!aBase.IsNull()) + aSeqBases1->Append(aBase); + } + for (ind = 0; ind < aNbBases2; ind++) { + Handle(GEOM_Object) aBase = GetObjectImpl(theBase2[ind]); + if (!aBase.IsNull()) + aSeqBases2->Append(aBase); + } + + if (!aSeqBases1->Length() || !aSeqBases2->Length()) + return aGEOMObject._retn(); + + // Create the Path + Handle(GEOM_Object) anObject = GetOperations()->RestorePath(aShape, aSeqBases1, aSeqBases2); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} diff --git a/src/GEOM_I/GEOM_I3DPrimOperations_i.hh b/src/GEOM_I/GEOM_I3DPrimOperations_i.hh index 05a748932..5b274671b 100644 --- a/src/GEOM_I/GEOM_I3DPrimOperations_i.hh +++ b/src/GEOM_I/GEOM_I3DPrimOperations_i.hh @@ -18,7 +18,6 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// #ifndef _GEOM_I3DPrimOperations_i_HeaderFile #define _GEOM_I3DPrimOperations_i_HeaderFile @@ -188,6 +187,13 @@ class GEOM_I_EXPORT GEOM_I3DPrimOperations_i : GEOM::GEOM_Object_ptr thePath, GEOM::GEOM_Object_ptr theVec); + GEOM::GEOM_Object_ptr RestorePath (GEOM::GEOM_Object_ptr theShape, + GEOM::GEOM_Object_ptr theBase1, + GEOM::GEOM_Object_ptr theBase2); + GEOM::GEOM_Object_ptr RestorePathEdges (GEOM::GEOM_Object_ptr theShape, + const GEOM::ListOfGO& theBase1, + const GEOM::ListOfGO& theBase2); + ::GEOMImpl_I3DPrimOperations* GetOperations() { return (::GEOMImpl_I3DPrimOperations*)GetImpl(); } }; diff --git a/src/GEOM_I/Makefile.am b/src/GEOM_I/Makefile.am index dfdba30a5..b5cd51165 100644 --- a/src/GEOM_I/Makefile.am +++ b/src/GEOM_I/Makefile.am @@ -81,7 +81,8 @@ libGEOMEngine_la_CPPFLAGS = \ -I$(srcdir)/../GEOMImpl \ -I$(srcdir)/../GEOMAlgo \ -I$(srcdir)/../GEOM \ - -I$(top_builddir)/idl + -I$(top_builddir)/idl \ + -I$(top_builddir) libGEOMEngine_la_LDFLAGS = \ diff --git a/src/GEOM_PY/structelem/__init__.py b/src/GEOM_PY/structelem/__init__.py index 8f90c0002..be6557887 100644 --- a/src/GEOM_PY/structelem/__init__.py +++ b/src/GEOM_PY/structelem/__init__.py @@ -147,7 +147,13 @@ class StructuralElementManager: (meshGroupList, newparams) = self._extractMeshGroups(command) for meshGroup in meshGroupList: # Get the geometrical primitive object - groupSObj = self._studyEditor.study.FindObject(meshGroup) + if meshGroup.startswith('/'): + groupSObj = self._studyEditor.study.FindObjectByPath(meshGroup) + meshGroup = meshGroup.split('/')[-1] + pass + else: + groupSObj = self._studyEditor.study.FindObject(meshGroup) + pass groupGeomObj = None if groupSObj is not None: groupGeomObj = \ diff --git a/src/GEOM_PY/structelem/orientation.py b/src/GEOM_PY/structelem/orientation.py index 7ecae7789..bbedb37e3 100644 --- a/src/GEOM_PY/structelem/orientation.py +++ b/src/GEOM_PY/structelem/orientation.py @@ -27,7 +27,7 @@ import math from salome.kernel.logger import Logger from salome.kernel import termcolor -logger = Logger("__PAL_GEOM__.structelem.orientation", color = termcolor.RED) +logger = Logger("salome.geom.structelem.orientation", color = termcolor.RED) class Orientation1D: @@ -57,25 +57,24 @@ class Orientation1D: coordinate system. The parameters can be specified several times. In this case, only the - first "VECT_Y" is taken into account, and the values of "ANGL_VRIL" - are added to obtain the total rotation angle. + last "VECT_Y" or "ANGL_VRIL" is taken into account. """ + if self._vectorYCoords is not None or self._angle != 0.0: + logger.warning('Orientation parameters are specified several ' + 'times for the same mesh group, only the last ' + 'parameter will be used') mydict = params.copy() if mydict.has_key("VECT_Y"): newVecCoords = mydict.pop("VECT_Y") - if self._vectorYCoords is None: - logger.debug("Setting orientation vector Y to %s" % + logger.debug("Setting orientation vector Y to %s" % str(newVecCoords)) - self._vectorYCoords = newVecCoords - else: - logger.warning('Orientation parameter "VECT_Y" is specified ' - 'several times for the same mesh group, vector' - ' %s will be used' % str(self._vectorYCoords)) + self._vectorYCoords = newVecCoords + self._angle = 0.0 if mydict.has_key("ANGL_VRIL"): newAngle = mydict.pop("ANGL_VRIL") - self._angle += newAngle - logger.debug("Adding angle %f to orientation, new angle is %f." % - (newAngle, self._angle)) + logger.debug("Setting orientation angle to %f" % newAngle) + self._angle = newAngle + self._vectorYCoords = None if len(mydict) > 0: logger.warning("Invalid orientation parameter(s) (ignored): %s" % str(mydict)) diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index b74b80816..3b9381772 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -109,8 +109,12 @@ def TestAll (geompy, math): sk = geompy.Sketcher3D() sk.addPointsAbsolute(0,0,0, 70,0,0) sk.addPointsRelative(0, 0, 130) - sk.addPointAnglesLength("OXY", 50, 0, 100) - sk.addPointAnglesLength("OXZ", 30, 80, 130) + sk.addPointRadiusAnglesRelative(100, 50, 0,"OXY") + sk.addPointRadiusAnglesRelative(130, 30, 80, "OXZ") + sk.addPointRadiusAnglesAbsolute(500, 60, 30,"OXY") + sk.addPointRadiusAngleHRelative(100, 50, 0,"OXY") + sk.addPointRadiusAngleHRelative(130, 30, 40, "OXZ") + sk.addPointRadiusAngleHAbsolute(800, 60, 30,"OXY") sk.close() Sketcher3d_1 = sk.wire() @@ -204,7 +208,7 @@ def TestAll (geompy, math): Line3 = geompy.MakeLineTwoFaces(prism1_faces[0], prism1_faces[1]) #(2 GEOM_Object)->GEOM_Object #Create advanced objects - Copy = geompy.MakeCopy(Box) #(GEOM_Object)->GEOM_Object + Copy = geompy.MakeCopy(Box) #(GEOM_Object)->GEOM_Object Prism = geompy.MakePrismVecH(Face, vz, 100.0) #(2 GEOM_Object, Double)->GEOM_Object Prism2Ways = geompy.MakePrismVecH2Ways(Face, vz, 10.0) #(2 GEOM_Object, Double)->GEOM_Object PrismTwoPnt = geompy.MakePrism(Face2, p0, pxyz) #(3 GEOM_Object)->GEOM_Object @@ -214,9 +218,9 @@ def TestAll (geompy, math): Revolution = geompy.MakeRevolution(Face, vz, angle2) # Revolution2Ways = geompy.MakeRevolution(Face, vz, angle1) # Filling = geompy.MakeFilling(Compound, mindeg, maxdeg, - tol2d, tol3d, nbiter) #(GEOM_Object, 4 Doubles, Short)->GEOM_Object - Pipe = geompy.MakePipe(Wire, Edge) #(2 GEOM_Object)->GEOM_Object - Sewing = geompy.MakeSewing([Face, S], precision) #(List Of GEOM_Object, Double)->GEOM_Object + tol2d, tol3d, nbiter) #(GEOM_Object, 4 Doubles, Short)->GEOM_Object + Pipe = geompy.MakePipe(Wire, Edge) #(2 GEOM_Object)->GEOM_Object + Sewing = geompy.MakeSewing([Face, S], precision) #(List Of GEOM_Object, Double)->GEOM_Object #Transform objects Translation = geompy.MakeTranslationTwoPoints(Box, px, pz) #(3 GEOM_Object)->GEOM_Object @@ -408,6 +412,28 @@ def TestAll (geompy, math): id_Pipe = geompy.addToStudy(Pipe, "Pipe") id_Sewing = geompy.addToStudy(Sewing, "Sewing") + import salome_version + if int(salome_version.getXVersion(), 16) >= int('0x060600', 16): + [Face5, Face6] = geompy.SubShapes(Box, [31, 33]) + [b1_e1, b1_e2, b1_e3, b1_e4] = geompy.SubShapes(Box, [12, 22, 25, 29]) + [b2_e1, b2_e2, b2_e3, b2_e4] = geompy.SubShapes(Box, [ 8, 18, 26, 30]) + Path1 = geompy.RestorePath(Box, Face5, Face6) + Path2 = geompy.RestorePathEdges(Box, [b1_e1, b1_e2, b1_e3, b1_e4], [b2_e1, b2_e2, b2_e3, b2_e4]) + + id_Base1 = geompy.addToStudyInFather(Box, Face5, "Base1") + id_Base2 = geompy.addToStudyInFather(Box, Face6, "Base2") + id_Base1e1 = geompy.addToStudyInFather(Box, b1_e1, "Base1 Edge1") + id_Base1e2 = geompy.addToStudyInFather(Box, b1_e2, "Base1 Edge2") + id_Base1e3 = geompy.addToStudyInFather(Box, b1_e3, "Base1 Edge3") + id_Base1e4 = geompy.addToStudyInFather(Box, b1_e4, "Base1 Edge4") + id_Base2e1 = geompy.addToStudyInFather(Box, b2_e1, "Base2 Edge1") + id_Base2e2 = geompy.addToStudyInFather(Box, b2_e2, "Base2 Edge2") + id_Base2e3 = geompy.addToStudyInFather(Box, b2_e3, "Base2 Edge3") + id_Base2e4 = geompy.addToStudyInFather(Box, b2_e4, "Base2 Edge4") + id_Path1 = geompy.addToStudy(Path1, "Path1") + id_Path2 = geompy.addToStudy(Path2, "Path2") + pass + id_Translation = geompy.addToStudy(Translation, "Translation") id_TranslVect = geompy.addToStudy(TranslVect , "Translation along vector") id_TranslVectD = geompy.addToStudy(TranslVectD, "Translation along vector with defined distance") diff --git a/src/GEOM_SWIG/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index 4db5841a0..4f85d8183 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -78,16 +78,25 @@ def TestExportImport (geompy, shape): # Import Import = geompy.ImportFile(fileExportImport, "BREP") - id_Import = geompy.addToStudy(Import, "Import") + geompy.addToStudy(Import, "Import") # ImportBREP, ImportIGES, ImportSTEP ImportBREP = geompy.ImportBREP(fileExportImportBREP) ImportIGES = geompy.ImportIGES(fileExportImportIGES) ImportSTEP = geompy.ImportSTEP(fileExportImportSTEP) - id_ImportBREP = geompy.addToStudy(ImportBREP, "ImportBREP") - id_ImportIGES = geompy.addToStudy(ImportIGES, "ImportIGES") - id_ImportSTEP = geompy.addToStudy(ImportSTEP, "ImportSTEP") + geompy.addToStudy(ImportBREP, "ImportBREP") + geompy.addToStudy(ImportIGES, "ImportIGES") + geompy.addToStudy(ImportSTEP, "ImportSTEP") + + # GetIGESUnit and GetSTEPUnit + if geompy.GetIGESUnit(fileExportImportIGES) != "M": + ImportIGES_scaled = geompy.ImportIGES(fileExportImportIGES, True) + geompy.addToStudy(ImportIGES_scaled, "ImportIGES_scaled") + + if geompy.GetSTEPUnit(fileExportImportSTEP) != "M": + ImportSTEP_scaled = geompy.ImportSTEP(fileExportImportSTEP, True) + geompy.addToStudy(ImportSTEP_scaled, "ImportSTEP_scaled") # Remove files for Export/Import testing os.remove(fileExportImport) diff --git a/src/GEOM_SWIG/geompyDC.py b/src/GEOM_SWIG/geompyDC.py index 0dd628e5a..40a7dd53a 100644 --- a/src/GEOM_SWIG/geompyDC.py +++ b/src/GEOM_SWIG/geompyDC.py @@ -2867,6 +2867,76 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("MakePipeBiNormalAlongVector", self.PrimOp) return anObj + ## Build a middle path of a pipe-like shape. + # The path shape can be a wire or an edge. + # @param theShape It can be closed or unclosed pipe-like shell + # or a pipe-like solid. + # @param theBase1, theBase2 Two bases of the supposed pipe. This + # should be wires or faces of theShape. + # @note It is not assumed that exact or approximate copy of theShape + # can be obtained by applying existing Pipe operation on the + # resulting "Path" wire taking theBase1 as the base - it is not + # always possible; though in some particular cases it might work + # it is not guaranteed. Thus, RestorePath function should not be + # considered as an exact reverse operation of the Pipe. + # @return New GEOM.GEOM_Object, containing an edge or wire that represent + # source pipe's "path". + # + # @ref tui_creation_pipe_path "Example" + def RestorePath (self, theShape, theBase1, theBase2): + """ + Build a middle path of a pipe-like shape. + The path shape can be a wire or an edge. + + Parameters: + theShape It can be closed or unclosed pipe-like shell + or a pipe-like solid. + theBase1, theBase2 Two bases of the supposed pipe. This + should be wires or faces of theShape. + + Returns: + New GEOM_Object, containing an edge or wire that represent + source pipe's path. + """ + anObj = self.PrimOp.RestorePath(theShape, theBase1, theBase2) + RaiseIfFailed("RestorePath", self.PrimOp) + return anObj + + ## Build a middle path of a pipe-like shape. + # The path shape can be a wire or an edge. + # @param theShape It can be closed or unclosed pipe-like shell + # or a pipe-like solid. + # @param listEdges1, listEdges2 Two bases of the supposed pipe. This + # should be lists of edges of theShape. + # @note It is not assumed that exact or approximate copy of theShape + # can be obtained by applying existing Pipe operation on the + # resulting "Path" wire taking theBase1 as the base - it is not + # always possible; though in some particular cases it might work + # it is not guaranteed. Thus, RestorePath function should not be + # considered as an exact reverse operation of the Pipe. + # @return New GEOM.GEOM_Object, containing an edge or wire that represent + # source pipe's "path". + # + # @ref tui_creation_pipe_path "Example" + def RestorePathEdges (self, theShape, listEdges1, listEdges2): + """ + Build a middle path of a pipe-like shape. + The path shape can be a wire or an edge. + + Parameters: + theShape It can be closed or unclosed pipe-like shell + or a pipe-like solid. + listEdges1, listEdges2 Two bases of the supposed pipe. This + should be lists of edges of theShape. + + Returns: + New GEOM_Object, containing an edge or wire that represent + source pipe's path. + """ + anObj = self.PrimOp.RestorePathEdges(theShape, listEdges1, listEdges2) + RaiseIfFailed("RestorePath", self.PrimOp) + return anObj + # end of l3_complex ## @} @@ -7251,12 +7321,13 @@ class geompyDC(GEOM._objref_GEOM_Gen): # @param theFileName The file, containing the shape. # @param theFormatName Specify format for the file reading. # Available formats can be obtained with InsertOp.ImportTranslators() method. - # If format 'IGES_SCALE' is used instead 'IGES' length unit will be - # set to 'meter' and result model will be scaled. + # If format 'IGES_SCALE' is used instead of 'IGES' or + # format 'STEP_SCALE' is used instead of 'STEP', + # length unit will be set to 'meter' and result model will be scaled. # @return New GEOM.GEOM_Object, containing the imported shape. # # @ref swig_Import_Export "Example" - def ImportFile(self,theFileName, theFormatName): + def ImportFile(self, theFileName, theFormatName): """ Import a shape from the BREP or IGES or STEP file (depends on given format) with given name. @@ -7264,9 +7335,10 @@ class geompyDC(GEOM._objref_GEOM_Gen): Parameters: theFileName The file, containing the shape. theFormatName Specify format for the file reading. - Available formats can be obtained with geompy.InsertOp.ImportTranslators() method. - If format 'IGES_SCALE' is used instead 'IGES' length unit will be - set to 'meter' and result model will be scaled. + Available formats can be obtained with geompy.InsertOp.ImportTranslators() method. + If format 'IGES_SCALE' is used instead of 'IGES' or + format 'STEP_SCALE' is used instead of 'STEP', + length unit will be set to 'meter' and result model will be scaled. Returns: New GEOM.GEOM_Object, containing the imported shape. @@ -7277,7 +7349,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): return anObj ## Deprecated analog of ImportFile() - def Import(self,theFileName, theFormatName): + def Import(self, theFileName, theFormatName): """ Deprecated analog of geompy.ImportFile """ @@ -7286,60 +7358,118 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("Import", self.InsertOp) return anObj - ## Shortcut to ImportFile() for BREP format + ## Shortcut to ImportFile() for BREP format. + # Import a shape from the BREP file with given name. + # @param theFileName The file, containing the shape. + # @return New GEOM.GEOM_Object, containing the imported shape. # # @ref swig_Import_Export "Example" - def ImportBREP(self,theFileName): + def ImportBREP(self, theFileName): """ geompy.ImportFile(...) function for BREP format + Import a shape from the BREP file with given name. + + Parameters: + theFileName The file, containing the shape. + + Returns: + New GEOM.GEOM_Object, containing the imported shape. """ # Example: see GEOM_TestOthers.py return self.ImportFile(theFileName, "BREP") ## Shortcut to ImportFile() for IGES format + # Import a shape from the IGES file with given name. + # @param theFileName The file, containing the shape. + # @param ignoreUnits If True, file length units will be ignored (set to 'meter') + # and result model will be scaled, if its units are not meters. + # If False (default), file length units will be taken into account. + # @return New GEOM.GEOM_Object, containing the imported shape. # # @ref swig_Import_Export "Example" - def ImportIGES(self,theFileName): + def ImportIGES(self, theFileName, ignoreUnits = False): """ geompy.ImportFile(...) function for IGES format + + Parameters: + theFileName The file, containing the shape. + ignoreUnits If True, file length units will be ignored (set to 'meter') + and result model will be scaled, if its units are not meters. + If False (default), file length units will be taken into account. + + Returns: + New GEOM.GEOM_Object, containing the imported shape. """ # Example: see GEOM_TestOthers.py + if ignoreUnits: + return self.ImportFile(theFileName, "IGES_SCALE") return self.ImportFile(theFileName, "IGES") ## Return length unit from given IGES file + # @param theFileName The file, containing the shape. + # @return String, containing the units name. # # @ref swig_Import_Export "Example" - def GetIGESUnit(self,theFileName): + def GetIGESUnit(self, theFileName): """ - Return length unit from given IGES file + Return length units from given IGES file + + Parameters: + theFileName The file, containing the shape. + + Returns: + String, containing the units name. """ # Example: see GEOM_TestOthers.py - anObj = self.InsertOp.ImportFile(theFileName, "IGES_UNIT") - #RaiseIfFailed("Import", self.InsertOp) - # recieve name using returned vertex - UnitName = "M" - if anObj.GetShapeType() == GEOM.VERTEX: - vertices = [anObj] - else: - vertices = self.SubShapeAll(anObj,ShapeType["VERTEX"]) - if len(vertices)>0: - p = self.PointCoordinates(vertices[0]) - if abs(p[0]-0.01) < 1.e-6: - UnitName = "CM" - elif abs(p[0]-0.001) < 1.e-6: - UnitName = "MM" - return UnitName + aUnitName = self.InsertOp.ReadValue(theFileName, "IGES", "LEN_UNITS") + return aUnitName ## Shortcut to ImportFile() for STEP format + # Import a shape from the STEP file with given name. + # @param theFileName The file, containing the shape. + # @param ignoreUnits If True, file length units will be ignored (set to 'meter') + # and result model will be scaled, if its units are not meters. + # If False (default), file length units will be taken into account. + # @return New GEOM.GEOM_Object, containing the imported shape. # # @ref swig_Import_Export "Example" - def ImportSTEP(self,theFileName): + def ImportSTEP(self, theFileName, ignoreUnits = False): """ geompy.ImportFile(...) function for STEP format + + Parameters: + theFileName The file, containing the shape. + ignoreUnits If True, file length units will be ignored (set to 'meter') + and result model will be scaled, if its units are not meters. + If False (default), file length units will be taken into account. + + Returns: + New GEOM.GEOM_Object, containing the imported shape. """ # Example: see GEOM_TestOthers.py + if ignoreUnits: + return self.ImportFile(theFileName, "STEP_SCALE") return self.ImportFile(theFileName, "STEP") + ## Return length unit from given IGES or STEP file + # @param theFileName The file, containing the shape. + # @return String, containing the units name. + # + # @ref swig_Import_Export "Example" + def GetSTEPUnit(self, theFileName): + """ + Return length units from given STEP file + + Parameters: + theFileName The file, containing the shape. + + Returns: + String, containing the units name. + """ + # Example: see GEOM_TestOthers.py + aUnitName = self.InsertOp.ReadValue(theFileName, "STEP", "LEN_UNITS") + return aUnitName + ## Read a shape from the binary stream, containing its bounding representation (BRep). # @note This method will not be dumped to the python script by DumpStudy functionality. # @note GEOM.GEOM_Object.GetShapeStream() method can be used to obtain the shape's BRep stream. @@ -7372,7 +7502,7 @@ class geompyDC(GEOM._objref_GEOM_Gen): # Available formats can be obtained with InsertOp.ImportTranslators() method. # # @ref swig_Import_Export "Example" - def Export(self,theObject, theFileName, theFormatName): + def Export(self, theObject, theFileName, theFormatName): """ Export the given shape into a file with given name. @@ -9003,13 +9133,19 @@ class geompyDC(GEOM._objref_GEOM_Gen): RaiseIfFailed("LoadTexture", self.InsertOp) return ID - ## Get entry of the object + ## Get internal name of the object based on its study entry + # @note This method does not provide an unique identifier of the geometry object. + # @note This is internal function of GEOM component, though it can be used outside it for + # appropriate reason (e.g. for identification of geometry object). # @param obj geometry object # @return unique object identifier # @ingroup l1_geompy_auxiliary def getObjectID(self, obj): """ - Get entry of the object + Get internal name of the object based on its study entry. + Note: this method does not provide an unique identifier of the geometry object. + It is an internal function of GEOM component, though it can be used outside GEOM for + appropriate reason (e.g. for identification of geometry object). Parameters: obj geometry object diff --git a/src/GEOM_SWIG/gsketcher.py b/src/GEOM_SWIG/gsketcher.py index 11cb0771c..11ef9bb6d 100644 --- a/src/GEOM_SWIG/gsketcher.py +++ b/src/GEOM_SWIG/gsketcher.py @@ -121,11 +121,104 @@ class Sketcher3D: ## Add one straight segment, defined by two angles and length. # If the first point of sketcher is not yet defined, the # origin (0, 0, 0) will become the first sketcher point. - # @param axes can be: "OXY", "OYZ" or "OXZ" + # The radius and angles coordinates are defined + # in a local coordinate system which origin is the last point of the sketch + # + # @param length length of the segment # @param angle1 angle in a plane, defined by the \a axes # @param angle2 angle from the plane, defined by the \a axes - # @param length length of the segment - def addPointAnglesLength (self, axes, angle1, angle2, length): + # @param axes can be: "OXY", "OYZ" or "OXZ" + def addPointRadiusAnglesRelative (self, length, angle1, angle2, axes="OXY"): + """ + Add one straight segment, defined by two angles and length. + If the first point of sketcher is not yet defined, the + origin (0, 0, 0) will become the first sketcher point. + + Parameters: + length length of the segment + angle1 angle in a plane, defined by the \a axes + angle2 angle from the plane, defined by the \a axes + axes can be: "OXY", "OYZ" or "OXZ" + + Example of usage: + sk = geompy.Sketcher3D() + sk.addPointRadiusAnglesRelative(100, 50, 0, "OXY") + a3D_Sketcher_1 = sk.wire() + """ + self.myCommand = self.myCommand + ":%s"%axes+"SR"+" %s %s %s" % (printVar(angle1), printVar(angle2), printVar(length)) + pass + + ## Add one straight segment, defined by two angles and radius. + # If the first point of sketcher is not yet defined, the + # origin (0, 0, 0) will become the first sketcher point. + # The radius and angles coordinates are defined + # in a coordinate system which origin is the global coordinate system origin + # + # @param radius distance to the coordinate system origin + # @param angle1 angle in a plane, defined by the \a axes + # @param angle2 angle from the plane, defined by the \a axes + # @param axes can be: "OXY", "OYZ" or "OXZ" + def addPointRadiusAnglesAbsolute (self, radius, angle1, angle2, axes="OXY"): + """ + Add one straight segment, defined by two angles and length. + If the first point of sketcher is not yet defined, the + origin (0, 0, 0) will become the first sketcher point. + + Parameters: + radius distance to the coordinate system origin + angle1 angle in a plane, defined by the \a axes + angle2 angle from the plane, defined by the \a axes + axes can be: "OXY", "OYZ" or "OXZ" + + Example of usage: + sk = geompy.Sketcher3D() + sk.addPointRadiusAnglesAbsolute(100, 50, 0, "OXY") + a3D_Sketcher_1 = sk.wire() + """ + self.myCommand = self.myCommand + ":%s"%axes+"SA"+" %s %s %s" % (printVar(angle1), printVar(angle2), printVar(radius)) + pass + + ## Add one straight segment, defined by an angle, a height and a radius. + # If the first point of sketcher is not yet defined, the + # origin (0, 0, 0) will become the first sketcher point. + # The radius height and angle coordinates are defined + # in a local coordinate system which origin is the last point of the sketch + # + # @param axes can be: "OXY", "OYZ" or "OXZ" + # @param angle angle in a plane, defined by the \a axes + # @param height height from the plane, defined by the \a axes + # @param radius distance to the coordinate system origin + def addPointRadiusAngleHRelative (self, length, angle, height, axes="OXY"): + """ + Add one straight segment, defined by two angles and length. + If the first point of sketcher is not yet defined, the + origin (0, 0, 0) will become the first sketcher point. + + Parameters: + radius distance to the coordinate system origin + angle angle in a plane, defined by the \a axes + height height from the plane, defined by the \a axes + axes can be: "OXY", "OYZ" or "OXZ" + + Example of usage: + sk = geompy.Sketcher3D() + sk.addPointRadiusAngleHRelative(100, 50, 40, "OXY") + a3D_Sketcher_1 = sk.wire() + """ + self.myCommand = self.myCommand + ":%s"%axes+"CR"+" %s %s %s" % (printVar(angle), printVar(height), printVar(length)) + pass + + ## Add one straight segment, defined by an angle, a height and a radius. + # If the first point of sketcher is not yet defined, the + # origin (0, 0, 0) will become the first sketcher point. + # The radius height and angle coordinates are defined + # in a coordinate system which origin is the global coordinate system origin + # + # @param radius distance to the coordinate system origin + # @param angle angle in a plane, defined by the \a axes + # @param height height from the plane, defined by the \a axes + # @param axes can be: "OXY", "OYZ" or "OXZ" + def addPointRadiusAngleHAbsolute (self, radius, angle, height, axes="OXY"): """ Add one straight segment, defined by two angles and length. If the first point of sketcher is not yet defined, the @@ -134,15 +227,15 @@ class Sketcher3D: Parameters: axes can be: "OXY", "OYZ" or "OXZ" angle1 angle in a plane, defined by the \a axes - angle2 angle from the plane, defined by the \a axes - length length of the segment + height height from the plane, defined by the \a axes + radius distance to the coordinate system origin Example of usage: sk = geompy.Sketcher3D() - sk.addPointAnglesLength("OXY", 50, 0, 100) + sk.addPointRadiusAngleHAbsolute( 100, 50, 40, "OXY") a3D_Sketcher_1 = sk.wire() """ - self.myCommand = self.myCommand + ":%s %s %s %s" % (axes, printVar(angle1), printVar(angle2), printVar(length)) + self.myCommand = self.myCommand + ":%s"%axes+"CA"+" %s %s %s" % (printVar(angle), printVar(height), printVar(radius)) pass ## Set to close the wire diff --git a/src/GenerationGUI/GenerationGUI.cxx b/src/GenerationGUI/GenerationGUI.cxx index b341a92b0..3f94071ec 100644 --- a/src/GenerationGUI/GenerationGUI.cxx +++ b/src/GenerationGUI/GenerationGUI.cxx @@ -18,12 +18,11 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // GEOM GEOMGUI : GUI for Geometry component // File : GenerationGUI.cxx // Author : Damien COQUERET, Open CASCADE S.A.S. -// + #include "GenerationGUI.h" #include @@ -36,6 +35,7 @@ #include "GenerationGUI_RevolDlg.h" // Method REVOL #include "GenerationGUI_FillingDlg.h" // Method FILLING #include "GenerationGUI_PipeDlg.h" // Method PIPE +#include "GenerationGUI_PipePathDlg.h" // Method RESTORE PATH //======================================================================= // function : GenerationGUI() @@ -73,6 +73,7 @@ bool GenerationGUI::OnGUIEvent( int theCommandID, SUIT_Desktop* parent ) case GEOMOp::OpRevolution: aDlg = new GenerationGUI_RevolDlg ( getGeometryGUI(), parent ); break; case GEOMOp::OpFilling: aDlg = new GenerationGUI_FillingDlg ( getGeometryGUI(), parent ); break; case GEOMOp::OpPipe: aDlg = new GenerationGUI_PipeDlg ( getGeometryGUI(), parent ); break; + case GEOMOp::OpPipePath: aDlg = new GenerationGUI_PipePathDlg( getGeometryGUI(), parent ); break; default: app->putInfo( tr( "GEOM_PRP_COMMAND" ).arg( theCommandID ) ); break; } diff --git a/src/GenerationGUI/GenerationGUI_PipePathDlg.cxx b/src/GenerationGUI/GenerationGUI_PipePathDlg.cxx new file mode 100644 index 000000000..b2d2d8d6b --- /dev/null +++ b/src/GenerationGUI/GenerationGUI_PipePathDlg.cxx @@ -0,0 +1,392 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// GEOM GEOMGUI : GUI for Geometry component +// File : GenerationGUI_PipePathDlg.cxx + +#include "GenerationGUI_PipePathDlg.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +//================================================================================= +// class : GenerationGUI_PipePathDlg() +// purpose : Constructs a GenerationGUI_PipePathDlg which is a child of 'parent', with the +// name 'name' and widget flags set to 'f'. +// The dialog will by default be modeless, unless you set 'modal' to +// TRUE to construct a modal dialog. +//================================================================================= +GenerationGUI_PipePathDlg::GenerationGUI_PipePathDlg (GeometryGUI* theGeometryGUI, QWidget* parent, + bool modal, Qt::WindowFlags fl) + : GEOMBase_Skeleton(theGeometryGUI, parent, modal, fl) +{ + QPixmap image0 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_DLG_PIPE_PATH"))); + QPixmap image1 (SUIT_Session::session()->resourceMgr()->loadPixmap("GEOM", tr("ICON_SELECT"))); + + setWindowTitle(tr("GEOM_PIPE_PATH_TITLE")); + + /***************************************************************/ + mainFrame()->GroupConstructors->setTitle(tr("GEOM_PIPE_PATH")); + mainFrame()->RadioButton1->setIcon(image0); + mainFrame()->RadioButton2->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton3->setAttribute(Qt::WA_DeleteOnClose); + mainFrame()->RadioButton2->close(); + mainFrame()->RadioButton3->close(); + + GroupPoints = new DlgRef_3Sel1Check(centralWidget()); + + GroupPoints->GroupBox1->setTitle(tr("GEOM_ARGUMENTS")); + GroupPoints->TextLabel1->setText(tr("GEOM_PIPE_LIKE_SHAPE")); + GroupPoints->TextLabel2->setText(tr("GEOM_PIPE_BASE1_OBJECT")); + GroupPoints->TextLabel3->setText(tr("GEOM_PIPE_BASE2_OBJECT")); + GroupPoints->PushButton1->setIcon(image1); + GroupPoints->PushButton2->setIcon(image1); + GroupPoints->PushButton3->setIcon(image1); + GroupPoints->CheckButton1->setText(tr("GEOM_SELECT_UNPUBLISHED_EDGES")); + + QVBoxLayout* layout = new QVBoxLayout (centralWidget()); + layout->setMargin(0); + layout->setSpacing(6); + layout->addWidget(GroupPoints); + /***************************************************************/ + + setHelpFileName("create_pipe_path_page.html"); + + // Initialisation + Init(); +} + +//================================================================================= +// function : ~GenerationGUI_PipePathDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= +GenerationGUI_PipePathDlg::~GenerationGUI_PipePathDlg() +{ + // no need to delete child widgets, Qt does it all for us +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void GenerationGUI_PipePathDlg::Init() +{ + // init variables + GroupPoints->LineEdit1->setReadOnly(true); + GroupPoints->LineEdit2->setReadOnly(true); + GroupPoints->LineEdit3->setReadOnly(true); + + GroupPoints->LineEdit1->setText(""); + GroupPoints->LineEdit2->setText(""); + GroupPoints->LineEdit3->setText(""); + + myShape.nullify(); + + GroupPoints->CheckButton1->setEnabled(false); + + showOnlyPreviewControl(); + + // signals and slots connections + connect(buttonOk(), SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonApply(), SIGNAL(clicked()), this, SLOT(ClickOnApply())); + + connect(GroupPoints->PushButton1, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(GroupPoints->PushButton2, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + connect(GroupPoints->PushButton3, SIGNAL(clicked()), this, SLOT(SetEditCurrentArgument())); + + connect(GroupPoints->CheckButton1, SIGNAL(toggled(bool)), this, SLOT(SelectionTypeButtonClicked())); + + initName(tr("GEOM_PIPE_PATH")); + + updateGeometry(); + resize(100,100); + + GroupPoints->PushButton1->click(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : SelectionBittonClicked() +// purpose : Selection type Radio button management +//================================================================================= +void GenerationGUI_PipePathDlg::SelectionTypeButtonClicked() +{ + globalSelection(); + if (GroupPoints->CheckButton1->isChecked()) { + localSelection(GEOM::GEOM_Object::_nil(), TopAbs_EDGE); + } + else { + TColStd_MapOfInteger aMap; + aMap.Add(GEOM_FACE); + aMap.Add(GEOM_WIRE); + aMap.Add(GEOM_EDGE); + globalSelection(aMap); + } + processPreview(); +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void GenerationGUI_PipePathDlg::ClickOnOk() +{ + setIsApplyAndClose(true); + if (ClickOnApply()) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= +bool GenerationGUI_PipePathDlg::ClickOnApply() +{ + if (!onAccept()) + return false; + + initName(); + // activate selection and connect selection manager + GroupPoints->PushButton1->click(); + return true; +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection is changed or on dialog initialization or activation +//================================================================================= +void GenerationGUI_PipePathDlg::SelectionIntoArgument() +{ + erasePreview(); + myEditCurrentArgument->setText(""); + + if (myEditCurrentArgument == GroupPoints->LineEdit1) { + QList types; + types << TopAbs_SOLID << TopAbs_SHELL << TopAbs_FACE; + myShape = getSelected(types); + if (myShape) { + QString aName = GEOMBase::GetName(myShape.get()); + myEditCurrentArgument->setText(aName); + if (myBase1Objects.isEmpty()) + GroupPoints->PushButton2->click(); + else if (myBase2Objects.isEmpty()) + GroupPoints->PushButton3->click(); + } + } + else if (myEditCurrentArgument == GroupPoints->LineEdit2) { + myBase1Objects.clear(); + QList objects = getSelected(TopAbs_SHAPE, -1); + for (int i = 0; i < objects.count(); i++) { + GEOM::shape_type stype = objects[i]->GetMaxShapeType(); + if (GEOM::FACE <= stype && stype <= GEOM::EDGE) + myBase1Objects << objects[i]; + } + int nbObj = myBase1Objects.count(); + if (nbObj) { + QString aName = + nbObj > 1 ? QString("%1_objects").arg(nbObj) : GEOMBase::GetName(myBase1Objects[0].get()); + myEditCurrentArgument->setText(aName); + } + } + else if (myEditCurrentArgument == GroupPoints->LineEdit3) { + myBase2Objects.clear(); + QList objects = getSelected(TopAbs_SHAPE, -1); + for (int i = 0; i < objects.count(); i++) { + GEOM::shape_type stype = objects[i]->GetMaxShapeType(); + if (GEOM::FACE <= stype && stype <= GEOM::EDGE) + myBase2Objects << objects[i]; + } + int nbObj = myBase2Objects.count(); + if (nbObj) { + QString aName = + nbObj > 1 ? QString("%1_objects").arg(nbObj) : GEOMBase::GetName(myBase2Objects[0].get()); + myEditCurrentArgument->setText(aName); + } + } + + processPreview(); +} + +//================================================================================= +// function : SetEditCurrentArgument() +// purpose : +//================================================================================= +void GenerationGUI_PipePathDlg::SetEditCurrentArgument() +{ + QPushButton* send = (QPushButton*)sender(); + + disconnect(myGeomGUI->getApp()->selectionMgr(), 0, this, 0); + + globalSelection(GEOM_ALLSHAPES); + + GroupPoints->PushButton1->setDown(false); + GroupPoints->PushButton2->setDown(false); + GroupPoints->PushButton3->setDown(false); + GroupPoints->LineEdit1->setEnabled(false); + GroupPoints->LineEdit2->setEnabled(false); + GroupPoints->LineEdit3->setEnabled(false); + + if (send == GroupPoints->PushButton1) { + myEditCurrentArgument = GroupPoints->LineEdit1; + GroupPoints->CheckButton1->setEnabled(false); + } + else if (send == GroupPoints->PushButton2) { + myEditCurrentArgument = GroupPoints->LineEdit2; + + if (GroupPoints->CheckButton1->isChecked()) { + localSelection(GEOM::GEOM_Object::_nil(), TopAbs_EDGE); + } + else { + TColStd_MapOfInteger aMap; + aMap.Add(GEOM_FACE); + aMap.Add(GEOM_WIRE); + aMap.Add(GEOM_EDGE); + globalSelection(aMap); + } + GroupPoints->CheckButton1->setEnabled(true); + } + else if (send == GroupPoints->PushButton3) { + myEditCurrentArgument = GroupPoints->LineEdit3; + + if (GroupPoints->CheckButton1->isChecked()) { + localSelection(GEOM::GEOM_Object::_nil(), TopAbs_EDGE); + } + else { + TColStd_MapOfInteger aMap; + aMap.Add(GEOM_FACE); + aMap.Add(GEOM_WIRE); + aMap.Add(GEOM_EDGE); + globalSelection(aMap); + } + GroupPoints->CheckButton1->setEnabled(true); + } + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + // enable line edit + myEditCurrentArgument->setEnabled(true); + myEditCurrentArgument->setFocus(); + // after setFocus(), because it will be setDown(false) when loses focus + send->setDown(true); + + // seems we need it only to avoid preview disappearing, caused by selection mode change + processPreview(); +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void GenerationGUI_PipePathDlg::ActivateThisDialog() +{ + GEOMBase_Skeleton::ActivateThisDialog(); + + connect(myGeomGUI->getApp()->selectionMgr(), SIGNAL(currentSelectionChanged()), + this, SLOT(SelectionIntoArgument())); + + GroupPoints->PushButton1->click(); + SelectionIntoArgument(); +} + +//================================================================================= +// function : enterEvent() +// purpose : when mouse enter onto the QWidget +//================================================================================= +void GenerationGUI_PipePathDlg::enterEvent (QEvent*) +{ + if (!mainFrame()->GroupConstructors->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : createOperation +// purpose : +//================================================================================= +GEOM::GEOM_IOperations_ptr GenerationGUI_PipePathDlg::createOperation() +{ + return getGeomEngine()->GetI3DPrimOperations(getStudyId()); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= +bool GenerationGUI_PipePathDlg::isValid (QString&) +{ + bool ok = myShape && !myBase1Objects.isEmpty() && !myBase2Objects.isEmpty(); + return ok; +} + +//================================================================================= +// function : execute +// purpose : +//================================================================================= +bool GenerationGUI_PipePathDlg::execute (ObjectList& objects) +{ + GEOM::ListOfGO_var aBase1 = new GEOM::ListOfGO(); + GEOM::ListOfGO_var aBase2 = new GEOM::ListOfGO(); + + aBase1->length(myBase1Objects.count()); + aBase2->length(myBase2Objects.count()); + + int i; + for (i = 0; i < myBase1Objects.count(); i++) + aBase1[i] = myBase1Objects[i].copy(); + for (i = 0; i < myBase2Objects.count(); i++) + aBase2[i] = myBase2Objects[i].copy(); + + GEOM::GEOM_I3DPrimOperations_var anOper = GEOM::GEOM_I3DPrimOperations::_narrow(getOperation()); + GEOM::GEOM_Object_var anObj = anOper->RestorePathEdges(myShape.get(), aBase1.in(), aBase2.in()); + + if (!anObj->_is_nil()) + objects.push_back(anObj._retn()); + + return true; +} + +//================================================================================= +// function : addSubshapeToStudy +// purpose : virtual method to add new SubObjects if local selection +//================================================================================= +void GenerationGUI_PipePathDlg::addSubshapesToStudy() +{ + int i; + for (i = 0; i < myBase1Objects.count(); i++) + GEOMBase::PublishSubObject(myBase1Objects[i].get()); + for (i = 0; i < myBase2Objects.count(); i++) + GEOMBase::PublishSubObject(myBase2Objects[i].get()); +} diff --git a/src/GenerationGUI/GenerationGUI_PipePathDlg.h b/src/GenerationGUI/GenerationGUI_PipePathDlg.h new file mode 100644 index 000000000..2c900bbc3 --- /dev/null +++ b/src/GenerationGUI/GenerationGUI_PipePathDlg.h @@ -0,0 +1,72 @@ +// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com + +// GEOM GEOMGUI : GUI for Geometry component +// File : GenerationGUI_PipePathDlg.h + +#ifndef GENERATIONGUI_PIPEPATHDLG_H +#define GENERATIONGUI_PIPEPATHDLG_H + +#include "GEOMBase_Skeleton.h" +#include "GEOM_GenericObjPtr.h" + +class DlgRef_3Sel1Check; + +//================================================================================= +// class : GenerationGUI_PipePathDlg +// purpose : +//================================================================================= +class GenerationGUI_PipePathDlg : public GEOMBase_Skeleton +{ + Q_OBJECT + +public: + GenerationGUI_PipePathDlg (GeometryGUI*, QWidget* = 0, bool = false, Qt::WindowFlags = 0); + ~GenerationGUI_PipePathDlg(); + +protected: + // redefined from GEOMBase_Helper + virtual GEOM::GEOM_IOperations_ptr createOperation(); + virtual bool isValid (QString&); + virtual bool execute (ObjectList&); + virtual void addSubshapesToStudy(); + +private: + void Init(); + void enterEvent (QEvent*); + +private: + GEOM::GeomObjPtr myShape; /* Pipe-like shape */ + QList myBase1Objects; /* Base 1 edges / wire / face */ + QList myBase2Objects; /* Base 2 edges / wire / face */ + + DlgRef_3Sel1Check* GroupPoints; + +private slots: + void ClickOnOk(); + bool ClickOnApply(); + void ActivateThisDialog(); + void SelectionIntoArgument(); + void SetEditCurrentArgument(); + void SelectionTypeButtonClicked(); +}; + +#endif // GENERATIONGUI_PIPEPATHDLG_H diff --git a/src/GenerationGUI/Makefile.am b/src/GenerationGUI/Makefile.am index 35afde04d..cda0fad02 100644 --- a/src/GenerationGUI/Makefile.am +++ b/src/GenerationGUI/Makefile.am @@ -15,13 +15,12 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# # GEOM GENERATIONGUI : # File : Makefile.am # Author : Alexander BORODIN, Open CASCADE S.A.S. (alexander.borodin@opencascade.com) # Package : GenerationGUI -# + include $(top_srcdir)/adm_local/unix/make_common_starter.am # Libraries targets @@ -33,7 +32,8 @@ salomeinclude_HEADERS = \ GenerationGUI_PrismDlg.h \ GenerationGUI_RevolDlg.h \ GenerationGUI_FillingDlg.h \ - GenerationGUI_PipeDlg.h + GenerationGUI_PipeDlg.h \ + GenerationGUI_PipePathDlg.h dist_libGenerationGUI_la_SOURCES = \ GenerationGUI.h \ @@ -41,18 +41,21 @@ dist_libGenerationGUI_la_SOURCES = \ GenerationGUI_RevolDlg.h \ GenerationGUI_FillingDlg.h \ GenerationGUI_PipeDlg.h \ + GenerationGUI_PipePathDlg.h \ \ GenerationGUI.cxx \ GenerationGUI_PrismDlg.cxx \ GenerationGUI_RevolDlg.cxx \ GenerationGUI_FillingDlg.cxx \ - GenerationGUI_PipeDlg.cxx + GenerationGUI_PipeDlg.cxx \ + GenerationGUI_PipePathDlg.cxx MOC_FILES = \ GenerationGUI_PrismDlg_moc.cxx \ GenerationGUI_RevolDlg_moc.cxx \ GenerationGUI_FillingDlg_moc.cxx \ - GenerationGUI_PipeDlg_moc.cxx + GenerationGUI_PipeDlg_moc.cxx \ + GenerationGUI_PipePathDlg_moc.cxx nodist_libGenerationGUI_la_SOURCES = \ $(MOC_FILES) diff --git a/src/IGESImport/IGESImport.cxx b/src/IGESImport/IGESImport.cxx index e9c73ac4a..3eba47108 100644 --- a/src/IGESImport/IGESImport.cxx +++ b/src/IGESImport/IGESImport.cxx @@ -108,10 +108,10 @@ extern "C" if (!aModel.IsNull()) { aValue = aModel->GlobalSection().UnitName(); - if (!aValue.IsNull()) { - Handle(TCollection_HAsciiString) aPrefix = new TCollection_HAsciiString ("UNIT_"); - aValue->Prepend(aPrefix); - } + //if (!aValue.IsNull()) { + // Handle(TCollection_HAsciiString) aPrefix = new TCollection_HAsciiString ("UNIT_"); + // aValue->Prepend(aPrefix); + //} } } else { diff --git a/src/NMTTools/NMTTools_CheckerSI_1.cxx b/src/NMTTools/NMTTools_CheckerSI_1.cxx index eb00dec0f..fb03fa1ca 100755 --- a/src/NMTTools/NMTTools_CheckerSI_1.cxx +++ b/src/NMTTools/NMTTools_CheckerSI_1.cxx @@ -42,14 +42,6 @@ #include #include - - -static - Standard_Boolean IsValid(const TopoDS_Edge& aE, - const TopoDS_Vertex& aV, - const Standard_Real aTV1, - const Standard_Real aTV2); - //======================================================================= // function: PreparePaveBlocks // purpose: @@ -65,14 +57,13 @@ static //======================================================================= void NMTTools_CheckerSI::PreparePaveBlocks(const Standard_Integer nE) { - myIsDone=Standard_False; - // - // char buf[32]={"SR"}; - Standard_Boolean bIsValid; + //Standard_Boolean bIsValid; Standard_Integer nV1, nV2, iErr; Standard_Real aT1, aT2; TopoDS_Edge aE; TopoDS_Vertex aV1, aV2; + // + myIsDone=Standard_False; // BOPTools_ListOfPaveBlock& aLPB=mySplitShapesPool(myDS->RefEdge(nE)); // Edge @@ -99,21 +90,23 @@ static aV2=TopoDS::Vertex(myDS->Shape(nV2)); aT2=aPave2.Param(); // + //modified by NIZNHY-PKV Thu Nov 01 13:46:00 2012f + //w/a: http://salome.mantis.opencascade.com/view.php?id=21835 + /* bIsValid=Standard_True; if (nV1==nV2) { bIsValid=IsValid(aE, aV1, aT1, aT2); if (!bIsValid) { - //printf(" pb SR: nV nE: %d nV1:( %d %15.10lf ) nV2:( %d %15.10lf )\n", nE, nV1, aT1, nV2, aT2); myStopStatus=1; } } + */ + //modified by NIZNHY-PKV Thu Nov 01 13:46:09 2012t // IntTools_ShrunkRange aSR (aE, aV1, aV2, aRange, myContext); iErr=aSR.ErrorStatus(); if (!aSR.IsDone()) { - //printf(" pb SR: Done nE: %d nV1:( %d %15.10lf ) nV2:( %d %15.10lf )\n", nE, nV1, aT1, nV2, aT2); aSR.SetShrunkRange(aRange); - //throw BOPTColStd_Failure(buf) ; } else if (iErr!=6) { CorrectShrunkRanges (0, aPave1, aSR); @@ -124,7 +117,9 @@ static } //for (; aPBIt.More(); aPBIt.Next()) myIsDone=Standard_True; } - +//modified by NIZNHY-PKV Thu Nov 01 13:46:55 2012f +//w/a: http://salome.mantis.opencascade.com/view.php?id=21835 +/* //======================================================================= //function : IsValid //purpose : @@ -157,3 +152,5 @@ Standard_Boolean IsValid(const TopoDS_Edge& aE, } return bRet; } +*/ +//modified by NIZNHY-PKV Thu Nov 01 13:47:07 2012t diff --git a/src/STEPExport/STEPExport.cxx b/src/STEPExport/STEPExport.cxx index 4a0805c84..abe5c310a 100644 --- a/src/STEPExport/STEPExport.cxx +++ b/src/STEPExport/STEPExport.cxx @@ -18,13 +18,11 @@ // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// // File: STEPExport.cxx // Created: Wed May 19 14:53:52 2004 // Author: Pavel TELKOV -// -// + #include "utilities.h" #include @@ -63,36 +61,37 @@ extern "C" { -STEPEXPORT_EXPORT + STEPEXPORT_EXPORT int Export(const TopoDS_Shape& theShape, const TCollection_AsciiString& theFileName) { MESSAGE("Export STEP into file " << theFileName.ToCString()); - try - { - // Set "C" numeric locale to save numbers correctly - Kernel_Utils::Localizer loc; + try + { + // Set "C" numeric locale to save numbers correctly + Kernel_Utils::Localizer loc; - IFSelect_ReturnStatus status ; - //VRV: OCC 4.0 migration - STEPControl_Writer aWriter; - //VSR: 16/09/09: Convert to METERS - Interface_Static::SetCVal("xstep.cascade.unit","M"); - Interface_Static::SetIVal("write.step.nonmanifold", 1); -//JFA: PAL6162 status = aWriter.Transfer( theShape, STEPControl_ManifoldSolidBrep ); - status = aWriter.Transfer( theShape, STEPControl_AsIs ); - //VRV: OCC 4.0 migration - if ( status == IFSelect_RetDone ) + IFSelect_ReturnStatus status ; + //VRV: OCC 4.0 migration + STEPControl_Writer aWriter; + //VSR: 16/09/09: Convert to METERS + Interface_Static::SetCVal("xstep.cascade.unit","M"); + Interface_Static::SetCVal("write.step.unit", "M"); + Interface_Static::SetIVal("write.step.nonmanifold", 1); + //JFA: PAL6162 status = aWriter.Transfer( theShape, STEPControl_ManifoldSolidBrep ); + status = aWriter.Transfer( theShape, STEPControl_AsIs ); + //VRV: OCC 4.0 migration + if ( status == IFSelect_RetDone ) status = aWriter.Write( theFileName.ToCString() ); - // Return previous locale - if ( status == IFSelect_RetDone ) - return 1; - } - catch(Standard_Failure) - { - //THROW_SALOME_CORBA_EXCEPTION("Exception catched in STEPExport", SALOME::BAD_PARAM); - } - return 0; + // Return previous locale + if ( status == IFSelect_RetDone ) + return 1; + } + catch (Standard_Failure) + { + //THROW_SALOME_CORBA_EXCEPTION("Exception catched in STEPExport", SALOME::BAD_PARAM); + } + return 0; } } diff --git a/src/STEPImport/STEPImport.cxx b/src/STEPImport/STEPImport.cxx index 8a4015043..7ad825833 100644 --- a/src/STEPImport/STEPImport.cxx +++ b/src/STEPImport/STEPImport.cxx @@ -122,16 +122,18 @@ extern "C" TColStd_SequenceOfAsciiString anUnitSolidAngleNames; aReader.FileUnits(anUnitLengthNames, anUnitAngleNames, anUnitSolidAngleNames); if (anUnitLengthNames.Length() > 0) { + aValue = new TCollection_HAsciiString( anUnitLengthNames.First() ); + /* TCollection_AsciiString aLenUnits = anUnitLengthNames.First(); if (aLenUnits == "millimetre") - aValue = new TCollection_HAsciiString ("UNIT_MM"); + aValue = new TCollection_HAsciiString ("MM"); else if (aLenUnits == "centimetre") - aValue = new TCollection_HAsciiString ("UNIT_CM"); + aValue = new TCollection_HAsciiString ("CM"); else if (aLenUnits == "metre") - aValue = new TCollection_HAsciiString ("UNIT_M"); + aValue = new TCollection_HAsciiString ("M"); else if (aLenUnits == "INCH") - aValue = new TCollection_HAsciiString ("UNIT_INCH"); - // TODO + aValue = new TCollection_HAsciiString ("INCH"); + // TODO (for other units than mm, cm, m or inch) //else if (aLenUnits == "") // aValue = new TCollection_HAsciiString (""); @@ -141,6 +143,7 @@ extern "C" // std::cout << ", " << anUnitLengthNames.Value(ii); //std::cout << std::endl; // tmp end + */ } } else { @@ -197,7 +200,7 @@ extern "C" Interface_Static::SetCVal("xstep.cascade.unit", "MM"); else if (aLenUnits == "centimetre") Interface_Static::SetCVal("xstep.cascade.unit", "CM"); - else if (aLenUnits == "metre") + else if (aLenUnits == "metre" || aLenUnits.IsEmpty()) Interface_Static::SetCVal("xstep.cascade.unit", "M"); else if (aLenUnits == "INCH") Interface_Static::SetCVal("xstep.cascade.unit", "INCH"); @@ -205,9 +208,9 @@ extern "C" theError = "The file contains not supported units."; return aResShape; } - // TODO + // TODO (for other units than mm, cm, m or inch) //else if (aLenUnits == "") - // Interface_Static::SetCVal("xstep.cascade.unit", ""); + // Interface_Static::SetCVal("xstep.cascade.unit", "???"); } } else { diff --git a/src/ShHealOper/ShHealOper_ChangeOrientation.cxx b/src/ShHealOper/ShHealOper_ChangeOrientation.cxx index 4d2fba884..2128cd539 100644 --- a/src/ShHealOper/ShHealOper_ChangeOrientation.cxx +++ b/src/ShHealOper/ShHealOper_ChangeOrientation.cxx @@ -26,10 +26,17 @@ #include -#include #include - +#include +#include +#include +#include +#include +#include +#include +#include #include +#include //======================================================================= //function : ShHealOper_ChangeOrientation() @@ -59,7 +66,8 @@ void ShHealOper_ChangeOrientation::Init(const TopoDS_Shape& theShape) Standard_Boolean ShHealOper_ChangeOrientation::Perform() { BRep_Builder B; - if (myInitShape.ShapeType() == TopAbs_SHELL) { + if (myInitShape.ShapeType() == TopAbs_SHELL) + { myResultShape = myInitShape.EmptyCopied(); TopoDS_Iterator itr (myInitShape); while (itr.More()) { @@ -67,7 +75,8 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform() itr.Next(); } } - else if (myInitShape.ShapeType() == TopAbs_FACE) { + else if (myInitShape.ShapeType() == TopAbs_FACE) + { myResultShape = myInitShape.EmptyCopied(); TopoDS_Iterator itr (myInitShape); while (itr.More()) { @@ -76,16 +85,43 @@ Standard_Boolean ShHealOper_ChangeOrientation::Perform() } myResultShape.Reverse(); } - else if ( myInitShape.ShapeType() == TopAbs_WIRE || myInitShape.ShapeType() == TopAbs_EDGE) { - myResultShape = myInitShape.EmptyCopied(); - TopoDS_Iterator itr (myInitShape); - while (itr.More()) { - B.Add(myResultShape,itr.Value()); - itr.Next(); + else if ( myInitShape.ShapeType() == TopAbs_WIRE || myInitShape.ShapeType() == TopAbs_EDGE) + { + TopTools_ListOfShape reversedEdges; + for ( TopExp_Explorer edgeIt( myInitShape, TopAbs_EDGE ); edgeIt.More(); edgeIt.Next() ) + { + const TopoDS_Edge& edge = TopoDS::Edge( edgeIt.Current() ); + + double f,l; + Handle(Geom_Curve) curve = BRep_Tool::Curve( edge, f,l ); + Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(curve); + if ( !tc.IsNull() ) curve = tc->BasisCurve(); + + f = curve->ReversedParameter( f ); + l = curve->ReversedParameter( l ); + curve = curve->Reversed(); + reversedEdges.Prepend( BRepBuilderAPI_MakeEdge( curve, Min( f, l ), Max( f, l ))); } - myResultShape.Reverse(); + if ( myInitShape.ShapeType() == TopAbs_EDGE ) + { + myResultShape = reversedEdges.First(); + } + else + { + BRepBuilderAPI_MakeWire wire; + wire.Add( reversedEdges ); + myResultShape = wire; + } + // myResultShape = myInitShape.EmptyCopied(); + // TopoDS_Iterator itr (myInitShape); + // while (itr.More()) { + // B.Add(myResultShape,itr.Value()); + // itr.Next(); + // } + // myResultShape.Reverse(); } - else { + else + { BRepBuilderAPI_Copy Copy (myInitShape); if (!Copy.IsDone()) return false;