From 1deab8bc715805e9ad95442ec32ce55924b2b1f0 Mon Sep 17 00:00:00 2001 From: mpa Date: Mon, 8 Dec 2014 18:14:18 +0300 Subject: [PATCH] 0022759: [EDF] Creation of a surface from several edges --- .../examples/topological_geom_objs_ex03.py | 13 + doc/salome/gui/GEOM/images/neo-obj4.png | Bin 18429 -> 15700 bytes doc/salome/gui/GEOM/images/neo-obj4_2.png | Bin 18206 -> 15824 bytes doc/salome/gui/GEOM/images/neo-obj4_3.png | Bin 0 -> 18652 bytes doc/salome/gui/GEOM/input/creating_face.doc | 31 +- idl/GEOM_Gen.idl | 27 ++ idl/GEOM_Superv.idl | 1 + resources/CMakeLists.txt | 1 + resources/GEOMCatalog.xml.in | 22 + resources/build_face_constraints.png | Bin 0 -> 966 bytes src/BuildGUI/BuildGUI_FaceDlg.cxx | 365 ++++++++++++++-- src/BuildGUI/BuildGUI_FaceDlg.h | 18 +- src/GEOMBase/GEOMBase_Helper.cxx | 6 +- src/GEOMBase/GEOMBase_Helper.h | 3 +- src/GEOMGUI/GEOM_images.ts | 4 + src/GEOMGUI/GEOM_msg_en.ts | 12 + src/GEOMGUI/GEOM_msg_fr.ts | 12 + src/GEOMGUI/GEOM_msg_ja.ts | 12 + src/GEOMImpl/GEOMImpl_FillingDriver.cxx | 412 ++++++++++-------- src/GEOMImpl/GEOMImpl_IShapesOperations.cxx | 136 ++++++ src/GEOMImpl/GEOMImpl_IShapesOperations.hxx | 7 + src/GEOMImpl/GEOMImpl_Types.hxx | 1 + src/GEOM_I/GEOM_IShapesOperations_i.cc | 50 +++ src/GEOM_I/GEOM_IShapesOperations_i.hh | 7 + src/GEOM_I_Superv/GEOM_Superv_i.cc | 18 + src/GEOM_I_Superv/GEOM_Superv_i.hh | 1 + src/GEOM_SWIG/GEOM_TestAll.py | 8 + src/GEOM_SWIG/geomBuilder.py | 68 +++ 28 files changed, 1004 insertions(+), 231 deletions(-) create mode 100644 doc/salome/gui/GEOM/images/neo-obj4_3.png create mode 100644 resources/build_face_constraints.png diff --git a/doc/salome/examples/topological_geom_objs_ex03.py b/doc/salome/examples/topological_geom_objs_ex03.py index 972d81a6f..6d9d5d43f 100644 --- a/doc/salome/examples/topological_geom_objs_ex03.py +++ b/doc/salome/examples/topological_geom_objs_ex03.py @@ -30,6 +30,10 @@ sketcher2 = geompy.MakeSketcher("Sketcher:F 0 0:TT 70 0:TT 70 70:TT 0 70:WW") sketcher3 = geompy.MakeSketcher("Sketcher:F 20 20:TT 50 20:TT 50 50:TT 20 50:WW") isPlanarFace = 1 +sphere = geompy.MakeSphereR(100) +box = geompy.MakeBoxDXDYDZ(200, 200, 200) +cut = geompy.MakeCutList(sphere, [box], True) + # create a face from the wire face1 = geompy.MakeFace(wire, isPlanarFace) @@ -38,11 +42,17 @@ face2 = geompy.MakeFaceWires([wire, sketcher1],isPlanarFace) face3 = geompy.MakeFaces([sketcher2, sketcher3],isPlanarFace) face4 = geompy.MakeFaceFromSurface(face1, sketcher1) +# create face from edges with constraints +face5 = geompy.MakeFaceWithConstraints([geompy.GetSubShape(cut, [5]), geompy.GetSubShape(cut, [3]), + geompy.GetSubShape(cut, [11]), geompy.GetSubShape(cut, [3]), + geompy.GetSubShape(cut, [13]), geompy.GetSubShape(cut, [3])]) + # add objects in the study id_face1 = geompy.addToStudy(face1,"Face1") id_face2 = geompy.addToStudy(face2,"Face2") id_face3 = geompy.addToStudy(face3,"Face3") id_face4 = geompy.addToStudy(face4,"Face4") +id_face5 = geompy.addToStudy(face5,"Face5") # display the faces gg.createAndDisplayGO(id_face1) @@ -57,3 +67,6 @@ gg.setTransparency(id_face3,0.2) gg.createAndDisplayGO(id_face4) gg.setDisplayMode(id_face4,1) gg.setTransparency(id_face4,0.2) +gg.createAndDisplayGO(id_face5) +gg.setDisplayMode(id_face5,1) +gg.setTransparency(id_face5,0.2) diff --git a/doc/salome/gui/GEOM/images/neo-obj4.png b/doc/salome/gui/GEOM/images/neo-obj4.png index 9b0f84c130b2442c7db86eb425ac145f39e7a9ca..63ce57d1d2d2949500432f3718d7ce558f851f21 100755 GIT binary patch literal 15700 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 VNnW*qU&I5E5S4jfD6ISCe*wnc1Y7_B diff --git a/doc/salome/gui/GEOM/images/neo-obj4_2.png b/doc/salome/gui/GEOM/images/neo-obj4_2.png index 233aa6fb4eaf72b57c8649949f4836bf5373888d..07f3a9de480d5f04d84c8a86994eef90966cf533 100644 GIT binary patch literal 15824 zcmbVz1wb6zwq+-Q&`5v)f#AV|OG0o6?(XjH?hxE9xCeI&!8J(mV8Pwp9RkeBeQ##o z+jM_WE|FHV&rNRuE-VD+6oiH~bd5_V(;=WF2Vj z9rbi=Y%EOmb^p8{q$DT{c0>QOn}Vr>g&~CB&QRCE@D1-9Azgh#wBNMH5Xc*dr~t2m zOWMJLs|Lo!Bi!-u;QsfHuWzo165kdGYaqDTBw;TKC+;Y7e3LjskSndAK7A#N6Y+*_oHC1gkW>DKGr&SLd$gW5~2Rx!nB`ZGOWnph(y;@)SrmM8NlD&8L zQ&Y*Yus{&T+J(w?bdm6=PDE0*sQe`BVU)jl@%|)y$JzGf%wRB5k*Sq^9oFuF&d?UJ z!#DNE`@YnPixeS2;UHHMnB|qtJuHLm{KbZBd1)Q^st=#}NJCsyf`UuFZAO2nA4HFz zazZlsl9or+EGXEkkkrV}2C=q#^-a68!!bh4&8_h*DVlt>^;dRRjY2_J*4 z_iXzpZ!?0~;ETARr+wWaledP7Y;t{L(a^%8l64SKdE{$8Z>7m^)C!vs2%jE=IFxP= z;#bb!)C3jGWs6JeydVj!hxxJbMxAa)FRv0^MOBq;7CuewRWrG1Y;O6bo1(jFdU09a z1h2~0fxi2TDRhzLjA_{5xrG5FE% z8FXf!e;*9bJ+f&9txMek9El&-HM$cxY>_FtyU;;6f&fW4F{e;W}yd_Dpm-K98&XND(uX zV(pdpcDF_v<=*Bb5m@Z@nVXTImFp)Y1D1Y8SJWPi`6MjYF7h zPUSl0-B);T8p+Ein#8a;vP9aoPr8S%)N_XgP%Pv6AC9){&y(*6>9jyFFa?fmb{bRT zszLEcY)UnYip?zv4-eGF=O=&B2}32rpjOfSU%h_jq4Hs{yPV8M!pgIkk?BPnM+cqV z@oc>DKdk$9!rBGN`jRC%S)~4{DYhj2c)7SCB_Z(=uh7bD!C_m%kRQ=U7bdWdTA`-w zph7yF+q+~nC`|b!A1uoN52w}$@8@x1U))&(Rbjig0!04ETFs66-+$3j;D6H6aYHyK za^pcv=9J>{nc$r+hV$>ek&+x@vBq4us4cm?ps9ViXl@a+RD_y1`8M@>v6m})Z@r?n z%6uKQ@s$NEr$4Iac>yE$FYjN=KB>rtaE%-brR4?EEj@5|H|!|at`{DXb-VeKK9Npm zJ=~icCiL>fBB6~$F5PK>E;A50Dekxb+R={)i>6+g4*=H_#*E;Id5B3~a)P&88L7vt7s?P3n=J8iGO|bPGa!^OJb=%;f zVXm8-nd~d%^emBG5Z>pIG>fvmx!E0V{imL&fg1^Nu57ckH|HY@cM<0kEscN9`TVhv z&nVsMol71^Ao}YmHOqr}D;5E>t>Kjt99Jp19#peWgkNntT%IDaxGXv4QEmNbQI!6H zjK976_FE*ue$B-V#basd%|(TKi*I*><1w8 zeJ9+QfC-FvaVm-P(xxPzfCyuK#iJ?Tr?v0`>|*-YF3&7rhP#pG*sny(CnGanC7wkw z>Skurnpq_d#Njg;21yh(E@f{8bbya)y28yx$aBi^i)iP4TdzS!#9*NjZ9S&%Q&+tA zlFzV45?vUnYUM2ZH(Ytz`$kc!J9Ee}HeTgg;hwa8>{OPW%KEXhnYU_Ps^MrhlR1{KC zsr8~4&Czfuj{itPr}0wKd!wbV#)b$Jd0&gyA0JA&&>#fd5@acdKjV^v{L`oH)p9Hb z1d_tlC_m=NdL=Fn)pIoy!U zv*lzavFI!zpI4kk=DJiR70=wt?tD{XpUA=da5jhD=r?b(%(5VakX0sZS4+^hqwqVh z{&Is0j>ECs%tZ9zwD7?eGU6=3L%KitT|bl16bF$8d2*%K68_cVS&gNI{LG1~U2!=E z(Ni|0E|(829|RyD6B|9GCFrl}WbpNU1c?OXTypv^_0(%1=+V|co4`)UK=dtu-GrsxyTH!Ej1dLi}MU-jlLEpf*`jCqcYjRn5IcWPO0R3Xk+9~&PpkV<#En4NIkn=I38 zN~n+q=VgEifh2p0Y#(ke8WL6sl&W&4dVZj#J(w(0r-~1KL*Q|ysHL?CH^=?OxyNM2 z_^bEtm7aKNC1QV@&LvzSVWd|9er`ZnxZUujdt zTg`qGwU?KW7_7CNOG!;-URYgQ8y_1ZMH5w3omo}JqCWRIJA^=Rp81f)_8BlG8~I#r z?y_jB|5oGk@QsLw*vw}xGWVi?@SGme^=kD>Nr;S$^uP8u&hR29BI3>0pZcj8tpxU0 za;oda^VK7QwTCGNGk_Gl_EuXnyp;=xfc3edA=mzV`m%0Te_;eyAydj_(^ZG&EMcpIss7D0rM-uC%D)#iZ;o z@Hq0sXmfs<4G~}pic%_~_a%~~?(Xio8(uv}!5-YO!^UI4O=js!_h`P-51FWxWhuXo z!ypt(o5MT(J(O~qB^yFN*(u@* z%LG%eLzV%v)Y(+^l=w07+v(_&tgp(>6xc)ppGjL}R8>{!J4HLFPI|o&_=KVcA7Yl~ z3pY`q$rnGpz5DOC<{rQOK32_9KbxPW;mCBZ&QlFt!4Qh}Dh|Y!R4$0kJBsv7F(z5H zsW+>+O&)M1oOwan>YzD0xtNN3I-)~Ux$PZu&fN~fyS~0Yn8B=mgs(`YSfa2vR&HS- z|Na{ljvB%5_qF}%bF&y@`N*!g@_q(QQnCA+o16Rl7X75=O-=`DuGG$Umsx(c!&nVL zzYkxs?hPjP*Z#QWNG$CmKa&dLG8lAcs;i;2S}Ofvd)gg{SoB#wR)HnNXYx)+YB>zg z!rzHCGS=)>AYkJ0OC@HB{che(1WzRh&~V&7MLaeM$i}6Ra)^lK<+J~ayREQS!4Q=* zW6nGL^7iw0-mmFSYNNEoF(Pz{&JD2vYpi^QU%#HN-{2A-RYl!j_jzmI%aqH&F5RzX zr>l!QnvN3&{q~$+XL7Z+5Nb325v!WFZ&GUMS+%0)_xOo;>lo8VvMe3Fr+;?B^Gn2t zl7?%P7x^0N#IKQ3Imh$E=Uk*ooTTqb%04=qk}K7X#x*4>D~O7gBqBe$U;T>TjYMAc z%9E5IqV=h4xr}^)5)kMw2gATiS>q)5Z?{fyjYS!x4*eJvUpE$lToAtls%5K|n+BGpQ7+cfBi$d6}&Zrmd?D zd@kE-#L}ecB>SzO*lwTn_4Qx0e9Dt~o1!+CI=60FMteH>T+n>MFSFLoP~ES%rGXz_ z_zuM(#h^i>JY6Y}{N~~Qj-&Qyy2gI$%Gm0f6(+ow!|DCo@^It5d6}Jg8QJx9MbC@y zsHmvAI_Hl%pK59xkF4aq4Hjcn-+ntqvEevGl^N|9|9RuInmHpNAK%-aW5rKpC3KeyE zXQywaz3n%OgL6gz@%P@OPkY{rLmSA&u`}U?F~9eIV3BrcdwWDG?6jlL>a)u3tjq3f zGfiQhSS}Mjw`aK74-bh*X0;{edrLtfe3wb$A04yj_sh&NcKt($ZQK}njac9Vd$*J< zM$zGyU-HD5pRms)P+g|qK62FYOB1#^#I8Ba{XBsimO(0bxEM%G)NF1G zcFA`9WbV*nptld**iW{3nc({RVJpsyrY91AuBaPINSLWZq1Zy2TJpiBJT!=tYvtbR zaeP74$=24@vdQzrZP7GvzjmzR11U8Hi%<=opYF{4M#! zpthHk>BpVf&A%E-lQo z#Kd|tr-o!?WK?2*uUJcD8VC#bY;T*mbKLEbO(7y6?3!WJ>~ z)pIXx>rI(k_K~!TO@oHEwzj*wdrcM>jeosHxu4&&-*?so)YK(J{DCfRZqH$1Z|?3M zZEvFHoUPF7)2pki)6+FYOnSFRb2K$HmOWD>s%oon*xXFEgLx0+8sv()7{UkEKty7E zn0(5Lwx8UJLW3N%w)*EWHucOk$(9u_MuZgMC2SB3&)t5tCs$e!A@4FVM^-PglN$DO zSCsz<E>Iy5DB~*?)nwIbqhY<=xZ2UGoZ*dh{bmbi0H=A4o{SJOp#FK=erxCj z3ZgL7wqgFeA6(nTrFvFY7FR_$DjF09nsr=xoV`jcgpi{94}5(N_kZGR$vipy>xYj* zLO)P=evhnG5&1{Q$14^DaG#uZBm%I$ZI6`ZfCYs)_lgF{J49f3$hCam3VY#gY+nMc zI_4{EX8X;-u`#(uMh*`5ALrOn5iS-TYv{;?>=G=2FhS6VY}I^o@Z^m@0OsHBOx(Ph zuhwKqgvrRsF)=Vq>Vp2HXFWY#-K_kL*eIS5f>&Ht`}O<#`z?eA5h0PH!P2bW56v-I zX6~LddnhNa><|^7e+aK6(5w#efF0~VUqXSiqW|Cko>1y0_0=_8m%pTSV=|^+ z!wW;2*6w0r2%cZoR}OjW`~w5M9=f*(2ne8AfUW%aA=HT9bJAZd=0Eb|TLi#uh$twT z?@h<1ZS{B5x#qdHb;h(NHMhGu7uKw1G`TY?luA6CJ-2U-tB3RR@)jB$#q;D|!pO?1 zjusV6eWV}yS`kIRz5%wxVRAXIe zC--+(iOsdS_4P@}G@;p{VPTpJ8Z}KV)eq^Xr>ARe1WPFmj*k!bP2BSVs2#Q%WlHEU zM2Q2EglK%hi|)iwUsBOV!@seVk%OX^Ql*j|^$TQ0EKl;1fg%VbiS8{!Z`ZJr&T_O& zmdslW1h?-$e_8>41tt$IL?BD1tEZ~;!V>-~KR9GQ zwI?H6Nv`IRn->qcqN3p#`^tdqJO_h#w@;^L?hLX!oxhfcy+Z*U=@$OSQ^fCtA0X`= z%V+-y>;8L2`o122*h0@k-&PR>fo!WuSRj!&PUEXUi72orkUANVIvMfqnpz0}p(OHG zqS3ZpUVb7ZR>fV(aQ>#)2Cv5!uM;qfH`NfAw^clq$8fTOr~(DBAi)tZm7>t#t*{27 zv+^#(M0BoMk!X6o$dI4_UkUXap(30k&c)9^=) z8pwHu*kkJ-EkfGCFgQ2oes_7`uu)uGOeUVNzOg}x5t@(yt|?8;g|R$wdpkQ14-cn< z*;g-L>UzAp;q;O=Mu3cXBEe0L4|BE{4`;+uNOM12ugxClg(Q*ooox+QsJ3ic{8Vj} z%~N>w3M-x6(X7v0Jb_MA&86u0d}n-bNmaV1ztM4zTsouK`Dk%|em*WPZprIT@(72p znOkJ}e1_UTIyE(QQ|a~&M)dRG(2(c-#nj{V8jAl&3bVOT_-otaWnNIP8|P+g%)t?~ zct1Y8GyX}V-P&APIdW|@w$zCL*)~M-7)pHZIkpS|de%-{lsu>jqF8K}+re4WB@V2e*x>Qlt_s-MokrlY#EFsdqT=J@L$jVddp_S_ zZ`}UrNea7^l+?w=MT(SobK!UjSvV#zU#*ioHpcv^NJh2hcY&Fa*4|7>bt|H zqxZBWN@Ze_lC&+VYHrmE9EcJ(hc165=8ODzN-ejYJm)3Px`u{^yu5A^Bv}kaMMXhb z3_;l+<6xqLXil{{>K<>LHYX*9D(o6GOsEx#6pq>+TXzJ}(9y@o$M^R3y7f*zlZg-F zhDea3hX_!`n}GzH^26WXe<+n@T>DN!Tue-@#m&*u(o#^c`)ruUda)4#Nid3O4-F1} z&8X+UIdy?MNv~FKvY%9Sd3l+S)#t+E$M-8~RNrVQEk4d*a|++c(2(omm%NXU4>B@x z$`5=FCyi#8(Vsu1&X`ss@j2dxA|N4!hlQoG+2?1OrIc)~Fu6f)VPdx`-7*i^Xb7T= z4Gr_yf`FU=135pk2NIeNQK`3iWWYAT$#-f$$T=I7=Kf6vWIJd%8ufpQY&!QuE1?_I zw{B3#C#{ad_Rx?B-Q67JCy;wWJhZ3(haUI$%`{;lnZ_JGlT2y`=h4~C?@u< zTeogBkNP395s~!$ynsJOjIM#{QgQqd|VA%XM)o>?wye3svrAC-^jJCOsvWKCdT zAeOcZBNNlhxF~K21pmz+FTiOYmbRIN#jp9RwHCrC95yOO#;Px0J~}svdAI_Hch`&`-MpWs1qi9EL313S)N*GI zZ=Jp5`y&++a%a;23wR<~prEC-1Tx~3czGC^ULzS7m*?)UBIOEA%{r?EkezPW9gcia z8v&gSL8mD0QWT@9gZP z2j;4axpM|0d?r;@&^TYrzuG<`qi$A6%7_79SxtTa7xH6%^&bD*mPYliRF0n6!%IFT zkCN4;FhB;Fn3%$)Qx;$D{xooNbJOF~J2~pspi>@~KN2~=e9zQeU(c$nJf-b@6W@B# zD=n<2r}y;fv-kHoLPGIzaW)O}nO?V|MG6FLcDXq@ISmbL3=AV9T`5fB9^5=^WY|n4 zSUQHz;vOE)j^YDnGmFZkk?FmTS zfUm`pOX6@?l`b-m4WuiTEd&+aOqFKmCsTFLdRqw@Ww6q~aA)Wt3;H2)jK{1+j7oSMY{{V*y2 zD+!IJm*+gyFuc*EGi4_Zsxt1XWlDRO9>(_^8yg!v-dwHB_Ip6|aQ3W6B=TRYS1Tij z^3f%xel-jG*`^gJWU?y3#QZra=`{sK0f}%V6y~Y7_oI|)04hQh^zq31u|%mPv9DuXJyxNMGoWnk}0VmPJjkKIX_>z zg9*5NLIQb=NPmAnW?Q357XKApx>9bP?_v$&Uy#<33XPe`Y^q%I#fujl&ii=GW^sp9 z>}BNx$O}}3buM;xUrRMVY~8RG6%`doXXfL!G`9e9H9tLFuYZTkZ(n{-Eq@k;n$2R| zbBPbGnfG5KG$Uo4f7ZC~;)g6|Xd+wRgl-Ue9DfgL;@0@;5OSy~ghY6f`S^QlW-CMS zEyghS)xLMzZ)+P7n}U}qr+9k+Nnas9e=1IwIR04JUsI}8eftmS3$^r5NtK(*f6)4U zSDDrM+vEN{Er0;BV{<=NxAjr${IzHVV~aIo|$l{zNdBfpr7z?JQ=27t^5tNGVlR4IIMS!`1e z@kKWUN4T%B<6~p1jfQYY=B78Gk1XN8e(k@Tk&TfRihg8GyKU@4l!fdYwSzU8iHB7XLWk+`j-T1^gTUbTzJKYf>P72?`KhDA@F zj!06)Q+ev&{)Rn+Lm`;wFrUBL;D(lFFnEcWYyyD4Jta&~M7_Y<#?0>YK61^vN*CwI0W5sskdV^U;h>oj2dJBOF zRgzSq@`2#1mf5gf`+?8u($3fY1cIa|sZ%7%l}U~SamlSDuM}~d$}B^MxYSpXSDt%m z`)#P)mSRJqF!H6)tH~=RZZ2_**x1-cm$JiklZ<%Jv>~5DKF7u;vr7)9v@_YFgpu~K z*>8#%t~b`n6O)kaR7^0T2cllSDFd9sM&b`Dui$>%KLhNHp@|#vMIA`AD9$Jc+Kz21%@pB;XbJK0 z2Xj}Bo;e*n40e-edu4)Ja@ev<0{cAI=KTEkxuUUY>FG^PLT)``YoKcLL04E0x3^i{ z&P{|Vgd1^#^kYUI*Vm-C13AxP}HEp9pbGsYb)8$9LB} zIne@jPtSW?>*kou#G{Rk_~dwOOw4>hd-?gmv~8ZxTvK4WxCALqd<*MlHgu+|`!Ged zZt2Kemn-Q^ARSJSne^5&7L*W&Jv`3KDODQ0PWZHs(3dd0r~)P?+W}`-tX+OZ<1`-i zd;EW>PiR!s)#+unx=;j;qK3xc+Q};Vs;7qsDj!qwJ`h*{2q#vT1s8isNy&+>$?h}A z>j(W2ZYm7%uD|gd|B*TC7JMAE+Zp3bc$lY+bN`OoSR3-Yt4uIYY$#q3#h{z-t~(#a zX${`zx86!;vFW z$ZCH(*z9^1j>0cb2+{e@-%&kd4Em)&KgyFUdf)T`EC`{+-N#rZXcoveJP*ff{jaEB z@;T6L8=9bq&yp*a*qU<4)qGf}w`(lgMDtNVV4Di0Al&8{nV5+0SpxziUMJ<}-OG(r zZ_VD1C>FzQSEw*6>+9!T=+dZZaOwi|^G(i2gFEkl%wbl8)5$PYHp)1PhfKln_87>T z4*IUHH-KwJ67oc%jvbncB;rF{98`{N^#7v*Sw|Ncj+E|DS6xjqao~6nff2yWq6D?P zrY#dwH#eNGXXVbcwzlRm=tV_AK>1RuL8N`@ z98PAlJMyQm0|Do%lfk&yT~!X?)0Gx_+Md(rn;ArwI1o?^BJkqj?#LWRIEtXfeoG3p z8%#wdBqXGzD=I3m!n(y1Xc!eFC5tZ}g7*ci=(1Cac_>5IPfJ}nAHuQ6vFN?XIEgtO zOiXNSDiiAxd!+yIe)k-E!CWyoxMGa$;4LW zfJ8wNpHJSt*u$dLc<(f*0;FR}{U1%(iQa8^uTcxx=HgGRo(B{%=JX7vuu)S|_Q^2I zN#fjwL`7jOvGIR4Q|E9-IKg|)dVPC+>jFaTuD+>B9kGeJv5Z;|1jKmtKuaPHb2-tSNQKkjv-BBeDil#HT4Y%Z_# zCfJ}x7n%i2KX~ONA9AF5ejdS|?%7(C7oYw1b}%M}!|V_lq60grv8Mlf9LEMPlgoVe z3eF2{N-R~ap+`C`gZ-ipu=q+nWs$33dN#5Ku*M&GdQ#eV?UZ}FyEpnm;2YR(oZm{N zD$Gt!8iD3h*3}RL;wn4@y=wU=d2(aM7Ww-L&USoKFJfUS@FZY}Qm!KmBItKZVM5w5 zO5thb%Xuo%RBpgrU*DRjiG&Kokp;m*wgva$OSO17GCrq`4Vc3~UjO;XjVO`GkO-fn zho@iKbR~7ZU%&ww{EyQF6t54ZOCwYKz`o4r1cR9-`xNpftn~&P=#4;x`ZucjzDqm< z5B*a1g}$CXjT#}O9SU~iGnxHnidoEQHP2da^c13`BdNo9VfhjQxdfH+e?Pl8b%&?* zoJ9I0j38eSqKdB4^817dN(7qqgP*j3ow~GEuN&c?MRUHBSk&%k8k-z;!{I?(Z?A~& z_V=r1eJD`bdYHAbgy=s4tzLN=U4=Z;!JB5kD!=wgrsoN5)G#74@}^zGW?4)mh3^{% zBoZiJ^+)3bSLP=WuJ2$fPIH^Y@*3?n`t!sS?d*pm@Y_bdcN<@2&{L597))YZXlB-X z4eDa#ih~+RHSBHM>r55okS`RVQy3#l()O@v?(OaEKLYq&HG8rxZK44gWP@y|3MZn?X;DJd!@x0nKn z@0?FM6mt9)G`0Z_K0Q0TzrR0PXi`>CP*79DK}EGW>FA!GR`HiX8Arh8B5ek6rO^@l z-BvCsa)^cLo{3qEvX~kUE~#CB#yZC7I6YPuT3@jub(5z>FbPtR%~J~2EKYZc{{K|nKnA=X z__Q}RzL9HK+8$NMdO#HCOmw%pu3QNS2w3|Ov37P%98;K=2TMeX7V^Pz_M7<>U6l$D z05z1A>l}8*($eq%i_mOx5)=@4txb~I!{X@z;q(Oyy`8j8t6uxYAK?@+fnM9|a(^Zu z3{#8MTemy(Rk|BsYy>>E^P{6LiN1lV))z|w)`0~)fQVYRNrX@o$@QPR;>(Nko- zD~0`Lfg=ygzOAU@A(p~M*7;kB!2~xq0Vu9=Mc-=5;(NBT4%6JmxJkn!BJP*{P+T~* zczM4A#14YL8pNruuP+!ib$E-!fBTWx-wI6i!*ADHsKdc*O||jxVw?BlA3GMkww8*D ziAO{VF)*0DMx-GmB*g0hdQG`@TkFO>ZKmg?s-$Fu2Hn-=<>9ZhbmzsFAp+-im&yBt z-q*Gpq47{6JeJGRmw}g+xt4M@IEl3+iss`H)CH+#bT38nqU|kRPJLRRX=-Y^auNh} zerHT0E;`hti@HAw;N#)p@qI%@MOCiZR0|~5DDKbXLL^v3j5l`1;mZ5tQf140TKRK>;pVAK8hr@$d~=y|fL+(FX89~Af;4$j@xJ!D@1bmu7LtYOjXtj@Pb0VK)zt5Z%%X?k_I;Py;h zT~2OnccKIU25Ks*4DSb5bY&O_gMS|o9z#s6tRkbLgrVIOT>}PR>6Sjm{jKhbNdGtL zuEcyJXt3nx=fk6uzwyuTIPJTq3#PXrSA zV>UA^%}J8AI**RC>^fZDOeQFWW-}n=yzTGBXLg2zR6aF-8ulKc=VYcjpKY$DKaW|m zY<`VGisi$H;t8|0tL%$SrFJ+T$Ow9=E4^-F6CWKNowSrh?@(VGzwK=9SZ(bGTwGk_ z0&mMVc=u06(C_z-W`gO4BkiG)Qy(k31hhUH0@p{bh!~Nwj#4Gov-VCuW*@`;5PNE$ z_^65~@SPu!D*|)(9>Pfj3QmicQ(Ef-0c6A*R8O~?eHYLP^0>l++`lk?idfDAf&69P z1Vhy5-Uqf4JcWFTsv@ae4o8DPs7w zX9aP9R8$<^0!bV1{~=3Dc*c(`3@u~>yD4Ws=>(d5qvIMo4LbEx$j3Su*yqVE6Cln1 z_eE{o#LUEDg(6{L2@8pW1YrXl-A-nLnHMZ5`aS`uDIY9x{3Zz8KoKrT#4!7(yVQJ&8x*~#VM z^mMm(XQruJ@%+k`zt<_;oH-m$7Y3(fWp(&&nDgvnO1r1Kn^7^A(k<-qxDy4)v-S2{ zkp%@?p|7YjJTGUoUW+E?F!6h5xDJ$64HI&|W8nAz(0i4N#kR6|#ljd3fy$ESm8Oo) zGU%4D7!AJ8H)9g4yPl~w1}`rR4h{wf2ZJngFjvO|`V=h;Xlpr4(qJ^ivML@<4ilt0rA*@*IA=y0>b8`-_-`79WIi%BAM`vfnSlnD)Tdo$}!PO_9FF^@}_OW18 zcIQJ44UIIhyliy?rWsIveGvBq#t1M!x~k366+}2BjQ&^(B``l2K5|ZK4}57)5INaAs6FA9w}sGI<`x zy*g_?dRMYYJ2qc@W!k%L%H&hY!HMJLICT zpb%GGeYVmWw3F}*4p~4@5O6?8wNWs8;^N|Uz*4N+`FzMTUd#}jsJeAa9%VgnBQom$ zSl`;h#jyc0E*N|fy8vs^bu0b&__(>b`6Y=^sdih2m4u|Eq_}t!D3dHp9yzX5;6<<1 zt`GnKN|YT}(yE#HP6oHm~Sb4$E)-my_t&CL)?~H2@lw z$L>zSuUybB-}$rB-*!+IeUDeg=@Cj{>FGV#7>Q)<>02Vqa!4b%mC z_0A>!97owU(0)@tST?$Em5b#OL;39YO2V`^&TgWlT|5AGa99gK#Hwv>3(y)kTxfEH zlK}odg}qwy+QZfEFoysDGPt=PY#VJS_f@g6u}Or&UG!Gbv5$;KB7l6v187pJb!*5U z4}rBL`k#e)cQ&}|dh&35oa}S5n#Ur}Jn)47X}ERFNdd37{&#y7;JyWVGU)YDE0+oY zS%xk~1jH9AUv7#*$wY2SE^1yw;-XNE8ve_dE6d9^=i9PAAD2OgZ)Y}Frn=Uddtvdo?B4T2`YRrWvB@?^KTCQXyTqG4v<#w$A@;GXH(WH6{=I4lBpEZ85ZW|O?DGvveT(j_OZEf7WIDKarzoNSWx<>i$%?cHY&m(ruum%Y^T`DO{bOQ3k z6L!5e19!$v0=<~dTH03b1-ut+z@P+UO)InE-e=Wvi@vC0Qd04?;_i21SB1TA{bfK~ z(rK-`BTVR!;1zbj+I6Gzr0Ol67|-|K4`XK*dM98cF71GUZfr;j3buVpim&_=+mClFCVDS>i69pC=}tAm|} literal 18206 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 diff --git a/doc/salome/gui/GEOM/images/neo-obj4_3.png b/doc/salome/gui/GEOM/images/neo-obj4_3.png new file mode 100644 index 0000000000000000000000000000000000000000..f819ed4ca97c426010f7b275e95e8c6c2f764d98 GIT binary patch literal 18652 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 Menu select New Entity - > Build - > Face -There are two algorithms to create a \b Face. In both cases the \b Result +There are three algorithms to create a \b Face. In all cases the \b Result of the operation will be a GEOM_Object (FACE). \n Firstly, to create a \b Face you need to select input shape(s). The list of @@ -20,14 +20,18 @@ that can be interpreted as an outer one; other wires can be considered as inner ones. \n Check Try to create a planar face to create a planar face or nothing if it is impossible. -\note Please note, that the resulting face can have a huge tolerance, if the initial wire has a big deviation from the plane. If the final tolerance exceeds 1e-06, a warning will be shown, but the face will be created and published in the study in a normal way. Using such faces can lead to failures or unpredictable results in most operations. +\note Please note, that the resulting face can have a huge tolerance, if +the initial wire has a big deviation from the plane. If the final tolerance +exceeds 1e-06, a warning will be shown, but the face will be created +and published in the study in a normal way. Using such faces can lead to failures +or unpredictable results in most operations. \n The \b Result will be a \b GEOM_Object (FACE). \n TUI Command: geompy.MakeFaceWires([list of Shapes], isPlanarWanted) \n Arguments: Name + 1 wire. -\image html neo-obj4.png +\image html neo-obj4.png "Create face by input shape(s)" \n Secondly, it is possible to create a face based on another face's surface and bounded by a wire. @@ -36,7 +40,24 @@ face or nothing if it is impossible. \n TUI Command: geompy.MakeFaceFromSurface(theFace, theWire) \n Arguments: Name + 1 face + 1 wire. -\image html neo-obj4_2.png +\image html neo-obj4_2.png "Create face by another face's surface" + +Thirdly, it is possible to create a \b Face by specifying a set of edges forming a closed wire +and constraints: +- Specify an input wire by selecting it in the object browser or in the viewer. + The input wire will be exploded on edges which will be shown in the \b Constraints list box. +- Specify constraints by associating faces with the edges. + +\note Please note, that the constraint face must be connected to a reference edge. + +\n The \b Result will be a \b GEOM_Object (FACE). + +\n TUI Command: geompy.MakeFaceWithConstraints([List of constraints]) +\n Arguments: Name + List of input edges and constraint faces. If a constraint +face is missing for some edge, this means that there is no constraint associated to this edge. +\note Set of edges should form a closed wire. + +\image html neo-obj4_3.png "Create face by a wire and its constraints" \n Example: @@ -46,7 +67,7 @@ face or nothing if it is impossible. \image html facesn3.png "Examples of faces" -Our TUI Scripts provide you with useful examples of creation of +Our TUI Scripts provide you with useful examples of creation of \ref tui_creation_face "Advanced Geometric Objects". */ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 83faa46bb..0880b9fd6 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1938,6 +1938,16 @@ module GEOM GEOM_Object MakeFaceFromSurface(in GEOM_Object theFace, in GEOM_Object theWire); + /*! + * \brief Create a face from a set of edges with the given constraints. + * \param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + * - edges should form a closed wire; + * - for each edge, constraint face is optional: if a constraint face is missing + * for some edge, this means that there no constraint associated with this edge. + * \return New GEOM_Object, containing the created face. + */ + GEOM_Object MakeFaceWithConstraints(in ListOfGO theConstraints); + /*! * \brief Create a shell from the set of faces and shells. * \param theFacesAndShells List of faces and/or shells. @@ -2165,6 +2175,23 @@ module GEOM */ string GetShapeTypeString (in GEOM_Object theShape); + /*! + * \brief Check if the object is a sub-object of another GEOM object. + * + * \param theSubObject Checked sub-object (or its parent object, in case if + * \a theSubObjectIndex is non-zero). + * \param theSubObjectIndex When non-zero, specifies a sub-shape index that + * identifies a sub-object within its parent specified via \a theSubObject. + * \param theObject An object that is checked for ownership (or its parent object, + * in case if \a theObjectIndex is non-zero). + * \param theObjectIndex When non-zero, specifies a sub-shape index that + * identifies an object within its parent specified via \a theObject. + * \return TRUE, if the given object contains sub-object. + */ + boolean IsSubShapeBelongsTo( in GEOM_Object theSubObject, + in long theSubObjectIndex, + in GEOM_Object theObject, + in long theObjectIndex); /*! * \brief Count number of faces in the given shape. * \param theShape Shape to count faces in. diff --git a/idl/GEOM_Superv.idl b/idl/GEOM_Superv.idl index 4843422c5..de885b9b3 100644 --- a/idl/GEOM_Superv.idl +++ b/idl/GEOM_Superv.idl @@ -391,6 +391,7 @@ module GEOM in boolean isPlanarWanted) ; GEOM_Object MakeFaceWires (in GEOM_List theWires, in boolean isPlanarWanted) ; + GEOM_Object MakeFaceWithConstraints(in GEOM_List theConstraints); GEOM_Object MakeShell (in GEOM_List theFacesAndShells) ; GEOM_Object MakeSolidShell (in GEOM_Object theShell) ; GEOM_Object MakeSolidShells (in GEOM_List theShells) ; diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 49a7e5362..d887216b3 100755 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -55,6 +55,7 @@ SET( _res_files build_edge_curve.png build_face.png build_face_surface.png + build_face_constraints.png build_shell.png build_solid.png build_wire.png diff --git a/resources/GEOMCatalog.xml.in b/resources/GEOMCatalog.xml.in index eeed1d6b1..7ccc9c80c 100644 --- a/resources/GEOMCatalog.xml.in +++ b/resources/GEOMCatalog.xml.in @@ -4283,6 +4283,28 @@ + + MakeFaceWithConstraints + SALOME team + @SALOMEGEOM_VERSION@ + unknown + 0 + + + theConstraints + GEOM/GEOM_List + unknown + + + + + return + GEOM/GEOM_Object + unknown + + + + MakeSolidShell SALOME team diff --git a/resources/build_face_constraints.png b/resources/build_face_constraints.png new file mode 100644 index 0000000000000000000000000000000000000000..81cab3b87a1ad78568c4f959a8d5569dd1db8517 GIT binary patch literal 966 zcmV;%13CPOP)Px#24YJ`L;zU;RRC90I6lb$000SaNLh0L01FZT01FZU(%pXi00007bV*G`2i^<{ z4H_}0hO;OD00TxzL_t(I%e|CcXdGn}hM#k0c4xO)o5b3Xpp+=NF3Cc{6;dZv3`DkQ z?LsLjD#cnY2wkZlNWrUuNG|MR{kbU8g2sR=hAstZZPmK%jSVT+?iI^{Hh=8b}YKR!3#)atuTl-%=r(*f@Q^%%S|JT-s{@#2R4a%YsEV@=; z8o`F2eUq<$c-KESb?p10E&H?os<6K|KcGTc9P?I`h!DcmP%*xpF0k$SBWN;34dvdO zS1Eov#^Vp~OP{&;!PFXsqKt`}Cm1S3ih{6ALYTk%Fp_A)bzPjsGRqSFu4-dzN=`p? zFsov|D5$P@wt9czasfa08l>9s5=lgrMx#M#{B53iE_`3jX(HzI;K4skb5Jeg#}#%{WM?&rpD*D(vQ zRqvzl*wh4uNroRJ66;y?5~#X3u1hTLky_tQPtOBv?CN6fkDGur+e0L1hPbLwZALWc z16XWSF#`)4G#Wq+mgeXA_4+lc%eSf3Yp5!sx~ed2v6*JdB0*UN1~(s|^zmE7D!;?R zEY->^OO-kPn!Uj0}l3;`}E^ z0C;NqbKH)lxMeYx+B&J%Yb26ws5&@qjJn&_Oj^_?)=bJ^|ADVW179`tMHJ3ldcT?Y zlTYtw&S@vsv4Oak#LTEKFVVShjpF!GBx1R%lM>`btt^5UHn@dNtDqWiy7(Rd{?0>G zJGyY)7&soq@uTb*8BJ3<`Oj_RZ+S7R%7lt}&E?QC*P_O$v&R`4Jxo2>!8ae~*)cM@ zy;wRqdB^qjSZ3dVij9flOEk;c3K#g|%Z~tfW@JzLv(kyFyIQcrTlZ!~EGJ4v#ri~o oswgv}R#vfz&rhG2 #include +#include + +//================================================================================= +// class : BuildGUI_TreeWidgetItem +// purpose : class for constraint(Edge-Face) creation +//================================================================================= +class BuildGUI_FaceDlg::TreeWidgetItem : public QTreeWidgetItem +{ +public: + TreeWidgetItem( QTreeWidget*, const GEOM::GeomObjPtr, int = Type ); + TreeWidgetItem( QTreeWidgetItem*, const GEOM::GeomObjPtr, int = Type ); + ~TreeWidgetItem(); + void setFace( const GEOM::GeomObjPtr ); + GEOM::GeomObjPtr getFace() const; + GEOM::GeomObjPtr getEdge() const; +private: + GEOM::GeomObjPtr myEdge; + GEOM::GeomObjPtr myFace; +}; + +BuildGUI_FaceDlg::TreeWidgetItem::TreeWidgetItem( QTreeWidget* view, const GEOM::GeomObjPtr edge, int type ) +:QTreeWidgetItem( view, QStringList()<resizeColumnToContents(1); + myFace = face; +} + +GEOM::GeomObjPtr BuildGUI_FaceDlg::TreeWidgetItem::getFace() const +{ + return myFace; +} + +GEOM::GeomObjPtr BuildGUI_FaceDlg::TreeWidgetItem::getEdge() const +{ + return myEdge; +} + //================================================================================= // class : BuildGUI_FaceDlg() // purpose : Constructs a BuildGUI_FaceDlg which is a child of 'parent', with the @@ -50,12 +106,14 @@ //================================================================================= BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent ) : GEOMBase_Skeleton( theGeometryGUI, parent ), - GroupWire (0), - myGroupSurf (0) + myGroupWire(0), + myGroupSurf(0), + myGroupWireConstraints(0) { QPixmap image0( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_SELECT" ) ) ); QPixmap image1( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE" ) ) ); QPixmap image2( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE_SURFACE" ) ) ); + QPixmap image3( SUIT_Session::session()->resourceMgr()->loadPixmap( "GEOM", tr( "ICON_DLG_BUILD_FACE_CONSTRAINTS" ) ) ); setWindowTitle( tr( "GEOM_FACE_TITLE" ) ); @@ -63,15 +121,18 @@ BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent mainFrame()->GroupConstructors->setTitle( tr( "GEOM_FACE" ) ); mainFrame()->RadioButton1->setIcon( image1 ); mainFrame()->RadioButton2->setIcon( image2 ); - mainFrame()->RadioButton3->setAttribute( Qt::WA_DeleteOnClose ); - mainFrame()->RadioButton3->close(); + mainFrame()->RadioButton3->setIcon( image3 ); - GroupWire = new DlgRef_1Sel1Check( centralWidget() ); + // Face creation from wires and/or edges - GroupWire->GroupBox1->setTitle( tr( "GEOM_FACE_FFW" ) ); - GroupWire->TextLabel1->setText( tr( "GEOM_OBJECTS" ) ); - GroupWire->CheckButton1->setText( tr( "GEOM_FACE_OPT" ) ); - GroupWire->PushButton1->setIcon( image0 ); + myGroupWire = new DlgRef_1Sel1Check( centralWidget() ); + + myGroupWire->GroupBox1->setTitle( tr( "GEOM_FACE_FFW" ) ); + myGroupWire->TextLabel1->setText( tr( "GEOM_OBJECTS" ) ); + myGroupWire->CheckButton1->setText( tr( "GEOM_FACE_OPT" ) ); + myGroupWire->PushButton1->setIcon( image0 ); + + // Face creation from surface myGroupSurf = new DlgRef_2Sel(centralWidget()); @@ -80,11 +141,35 @@ BuildGUI_FaceDlg::BuildGUI_FaceDlg( GeometryGUI* theGeometryGUI, QWidget* parent myGroupSurf->TextLabel2->setText(tr("GEOM_WIRE")); myGroupSurf->PushButton1->setIcon(image0); myGroupSurf->PushButton2->setIcon(image0); + + // Face creation from wire and constraints + + myGroupWireConstraints = new DlgRef_1SelExt( centralWidget() ); + myGroupWireConstraints->GroupBox1->setTitle( tr( "GEOM_FACE_FFWC" ) ); + myGroupWireConstraints->TextLabel1->setText( tr( "GEOM_WIRE" ) ); + myGroupWireConstraints->PushButton1->setIcon( image0 ); + + QLabel* aLabel = new QLabel( tr( "GEOM_CONSTRAINTS" ) ); + myTreeConstraints = new QTreeWidget( myGroupWireConstraints->Box ); + myTreeConstraints->setColumnCount(2); + QStringList columnNames; + columnNames.append( tr( "GEOM_EDGE" )); + columnNames.append( tr( "GEOM_FACE_CONSTRAINT" ) ); + myTreeConstraints->setHeaderLabels( columnNames ); + myTreeConstraints->header()->setMovable( false ); + myTreeConstraints->header()->setResizeMode( QHeaderView::ResizeToContents ); + myTreeConstraints->setMinimumHeight( 140 ); + + QHBoxLayout* l = new QHBoxLayout( myGroupWireConstraints->Box ); + l->setMargin( 0 ); l->setSpacing( 6 ); + l->addWidget( aLabel); + l->addWidget( myTreeConstraints ); QVBoxLayout* layout = new QVBoxLayout( centralWidget() ); layout->setMargin( 0 ); layout->setSpacing( 6 ); - layout->addWidget( GroupWire ); - layout->addWidget(myGroupSurf); + layout->addWidget( myGroupWire ); + layout->addWidget( myGroupSurf ); + layout->addWidget( myGroupWireConstraints ); /***************************************************************/ setHelpFileName("create_face_page.html"); @@ -111,33 +196,39 @@ BuildGUI_FaceDlg::~BuildGUI_FaceDlg() void BuildGUI_FaceDlg::Init() { /* init variables */ - myEditCurrentArgument = GroupWire->LineEdit1; - GroupWire->LineEdit1->setReadOnly( true ); + myEditCurrentArgument = myGroupWire->LineEdit1; + myGroupWire->LineEdit1->setReadOnly( true ); myGroupSurf->LineEdit1->setReadOnly( true ); myGroupSurf->LineEdit2->setReadOnly( true ); + myGroupWireConstraints->LineEdit1->setReadOnly( true ); - GroupWire->CheckButton1->setChecked( true ); + myGroupWire->CheckButton1->setChecked( true ); myWires.clear(); myFace.nullify(); myWire.nullify(); + myCurrentItem = 0; /* signals and slots connections */ connect(myGeomGUI, SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog())); connect(myGeomGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(ClickOnCancel())); - connect(this, SIGNAL(constructorsClicked(int)), this, SLOT(ConstructorsClicked(int))); + connect(this, SIGNAL( constructorsClicked( int ) ), this, SLOT( ConstructorsClicked( int ) ) ); connect( buttonOk(), SIGNAL( clicked() ), this, SLOT( ClickOnOk() ) ); connect( buttonApply(), SIGNAL( clicked() ), this, SLOT( ClickOnApply() ) ); - connect( GroupWire->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); - connect( GroupWire->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); + connect( myGroupWire->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); + connect( myGroupWire->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( myGroupSurf->LineEdit1, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); connect( myGroupSurf->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( myGroupSurf->LineEdit2, SIGNAL( returnPressed()), this, SLOT( LineEditReturnPressed() ) ); connect( myGroupSurf->PushButton2, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); + connect( myGroupWireConstraints->LineEdit1, SIGNAL( returnPressed() ), this, SLOT( LineEditReturnPressed() ) ); + connect( myGroupWireConstraints->PushButton1, SIGNAL( clicked() ), this, SLOT( SetEditCurrentArgument() ) ); connect( ( (SalomeApp_Application*)( SUIT_Session::session()->activeApplication() ) )->selectionMgr(), SIGNAL( currentSelectionChanged() ), this, SLOT( SelectionIntoArgument() ) ); + connect( myTreeConstraints, SIGNAL( itemClicked( QTreeWidgetItem*, int) ), this, SLOT( onItemClicked( QTreeWidgetItem*, int ) ) ); + initName( tr( "GEOM_FACE" ) ); ConstructorsClicked(0); @@ -162,22 +253,40 @@ void BuildGUI_FaceDlg::ConstructorsClicked(int constructorId) aMap.Add(GEOM_COMPOUND); globalSelection(aMap); - myEditCurrentArgument = GroupWire->LineEdit1; - GroupWire->LineEdit1->setText(""); - GroupWire->show(); + myEditCurrentArgument = myGroupWire->LineEdit1; + myGroupWire->LineEdit1->setText(""); + myGroupWire->show(); myGroupSurf->hide(); + myGroupWireConstraints->hide(); break; } case 1: { globalSelection(GEOM_FACE); // For the first element. + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); myEditCurrentArgument = myGroupSurf->LineEdit1; myGroupSurf->LineEdit1->setText(""); myGroupSurf->PushButton1->setDown(true); myGroupSurf->PushButton2->setDown(false); - GroupWire->hide(); + myGroupWire->hide(); myGroupSurf->show(); + myGroupWireConstraints->hide(); + break; + } + case 2: + { + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); + + myTreeConstraints->clear(); + myCurrentItem = 0; + myEditCurrentArgument = myGroupWireConstraints->LineEdit1; + myGroupWireConstraints->LineEdit1->setText(""); + myGroupWireConstraints->LineEdit1->setEnabled(true); + myGroupWire->hide(); + myGroupSurf->hide(); + myGroupWireConstraints->show(); break; } } @@ -191,6 +300,84 @@ void BuildGUI_FaceDlg::ConstructorsClicked(int constructorId) SelectionIntoArgument(); } +//================================================================================= +// function : updateConstraintsTree +// purpose : +//================================================================================= +void BuildGUI_FaceDlg::updateConstraintsTree() +{ + if ( myEditCurrentArgument != myGroupWireConstraints->LineEdit1 || myWire.isNull() ) + return; + + myTreeConstraints->clear(); + + GEOM::GEOM_IShapesOperations_ptr anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation()); + GEOM::ListOfGO_var aList = anOper->ExtractSubShapes( myWire.get(), TopAbs_EDGE, false ); + if ( !aList->length() ) + return; + + for ( int i = 0, n = aList->length(); i < n; i++ ) { + TreeWidgetItem* item = new TreeWidgetItem( myTreeConstraints, + GEOM::GeomObjPtr( aList[i] ) ); + } + + myEditCurrentArgument->setEnabled(false); + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); + + myTreeConstraints->resizeColumnToContents(0); + QTreeWidgetItem* firstItem = myTreeConstraints->topLevelItem(0); + firstItem->setSelected( true ); + onItemClicked( firstItem, 0 ); +} + +//================================================================================= +// function : findEmptyTreeItem() +// purpose : +//================================================================================= +void BuildGUI_FaceDlg::findEmptyTreeItem() +{ + if ( isTreeFull() ) + return; + + QTreeWidgetItem* nextItem = 0; + QTreeWidgetItem* item; + for ( item = myTreeConstraints->itemBelow( myCurrentItem ); + item && !nextItem; + item = myTreeConstraints->itemBelow( item ) ) { + if ( (dynamic_cast(item))->getFace().isNull() ) + nextItem = item; + } + for ( item = myTreeConstraints->topLevelItem(0); + item && item != myCurrentItem && !nextItem; + item = myTreeConstraints->itemBelow( item ) ) { + if ( (dynamic_cast(item))->getFace().isNull() ) + nextItem = item; + } + + if ( nextItem && nextItem != myCurrentItem ) { + myCurrentItem->setSelected( false ); + nextItem->setSelected( true ); + onItemClicked( nextItem, 0 ); + } +} + +//================================================================================= +// function : isTreeFull() +// purpose : +//================================================================================= +bool BuildGUI_FaceDlg::isTreeFull() +{ + bool ok = true; + QTreeWidgetItem* item; + for ( item = myTreeConstraints->topLevelItem(0); + item && ok; + item = myTreeConstraints->itemBelow( item ) ) { + ok = !(dynamic_cast(item))->getFace().isNull(); + } + return ok; +} + //================================================================================= // function : ClickOnOk() // purpose : @@ -213,6 +400,9 @@ bool BuildGUI_FaceDlg::ClickOnApply() return false; initName(); + + myEditCurrentArgument->setText(""); + ConstructorsClicked( getConstructorId() ); return true; } @@ -223,7 +413,8 @@ bool BuildGUI_FaceDlg::ClickOnApply() //================================================================================= void BuildGUI_FaceDlg::SelectionIntoArgument() { - if (myEditCurrentArgument == GroupWire->LineEdit1) { + erasePreview(); + if ( myEditCurrentArgument == myGroupWire->LineEdit1 ) { myEditCurrentArgument->setText( "" ); QList types; @@ -235,8 +426,9 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() QString aName = myWires.count() > 1 ? QString( "%1_objects").arg( myWires.count() ) : GEOMBase::GetName( myWires[0].get() ); myEditCurrentArgument->setText( aName ); } - } else if (myEditCurrentArgument == myGroupSurf->LineEdit1 || - myEditCurrentArgument == myGroupSurf->LineEdit2) { + } + else if (myEditCurrentArgument == myGroupSurf->LineEdit1 || + myEditCurrentArgument == myGroupSurf->LineEdit2) { const bool isEditFace = myEditCurrentArgument == myGroupSurf->LineEdit1; const TopAbs_ShapeEnum aType = isEditFace ? TopAbs_FACE : TopAbs_WIRE; GEOM::GeomObjPtr aSelectedObject = getSelected(aType); @@ -260,8 +452,39 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() } } } - - displayPreview(true); + else if ( myEditCurrentArgument == myGroupWireConstraints->LineEdit1 ) { + if ( myCurrentItem ) { + GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_FACE ); + TopoDS_Shape aFaceShape; + GEOM::GEOM_IShapesOperations_ptr anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation()); + if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aFaceShape ) && !aFaceShape.IsNull() + && anOper->IsSubShapeBelongsTo( myCurrentItem->getEdge().get(), 0, aSelectedObject.get(), 0 ) ) { + myCurrentItem->setFace( aSelectedObject ); + findEmptyTreeItem(); + } + else { + myCurrentItem->setFace( 0 ); + displayPreview( myCurrentItem->getEdge().get(), true, false, true, 5, -1, Quantity_NOC_RED ); + } + } + else { + myWire.nullify(); + myEditCurrentArgument->setText( "" ); + GEOM::GeomObjPtr aSelectedObject = getSelected( TopAbs_WIRE ); + TopoDS_Shape aWireShape; + if ( aSelectedObject && GEOMBase::GetShape( aSelectedObject.get(), aWireShape ) && !aWireShape.IsNull() ) { + QString aName = GEOMBase::GetName( aSelectedObject.get() ); + myEditCurrentArgument->setText( aName ); + myWire = aSelectedObject; + updateConstraintsTree(); + } + else { + myTreeConstraints->clear(); + erasePreview( true ); + } + } + } + displayPreview( true, false, true, true, -1, -1, -1, true ); } @@ -272,7 +495,7 @@ void BuildGUI_FaceDlg::SelectionIntoArgument() void BuildGUI_FaceDlg::SetEditCurrentArgument() { QPushButton* send = (QPushButton*)sender(); - if (send == GroupWire->PushButton1) { + if ( send == myGroupWire->PushButton1 ) { TColStd_MapOfInteger aMap; aMap.Add(GEOM_EDGE); @@ -282,26 +505,33 @@ void BuildGUI_FaceDlg::SetEditCurrentArgument() aMap.Add(GEOM_SOLID); aMap.Add(GEOM_COMPOUND); globalSelection(aMap); - myEditCurrentArgument = GroupWire->LineEdit1; + myEditCurrentArgument = myGroupWire->LineEdit1; } else if (send == myGroupSurf->PushButton1) { globalSelection(GEOM_FACE); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_FACE ); myEditCurrentArgument = myGroupSurf->LineEdit1; myGroupSurf->PushButton2->setDown(false); myGroupSurf->LineEdit2->setEnabled(false); } else if (send == myGroupSurf->PushButton2) { globalSelection(GEOM_WIRE); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); myEditCurrentArgument = myGroupSurf->LineEdit2; myGroupSurf->PushButton1->setDown(false); myGroupSurf->LineEdit1->setEnabled(false); } + else if (send == myGroupWireConstraints->PushButton1) { + globalSelection(); + localSelection( GEOM::GEOM_Object::_nil(), TopAbs_WIRE ); + myEditCurrentArgument = myGroupWireConstraints->LineEdit1; + myCurrentItem = 0; + } // enable line edit myEditCurrentArgument->setEnabled(true); myEditCurrentArgument->setFocus(); - send->setDown(true); - displayPreview(true); + SelectionIntoArgument(); } @@ -320,6 +550,19 @@ void BuildGUI_FaceDlg::ActivateThisDialog() ConstructorsClicked(getConstructorId()); } +//================================================================================= +// function : onItemClicked() +// purpose : called when tree item was clicked +//================================================================================= +void BuildGUI_FaceDlg::onItemClicked( QTreeWidgetItem* theItem, int theColumn ) +{ + if ( !theItem || !( theItem->flags() & Qt::ItemIsSelectable ) ) + return; + + myCurrentItem = dynamic_cast( theItem ); + displayPreview( true ); + displayPreview( myCurrentItem->getEdge().get(), true, false, true, 5, -1, Quantity_NOC_RED ); +} //================================================================================= // function : enterEvent() @@ -355,6 +598,9 @@ bool BuildGUI_FaceDlg::isValid( QString& ) case 1: ok = myFace && myWire; break; + case 2: + ok = myWire; + break; default: break; } @@ -383,13 +629,30 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) objlist[i] = myWires[i].copy(); } - anObj = anOper->MakeFaceWires( objlist.in(), GroupWire->CheckButton1->isChecked() ); - res = true; + anObj = anOper->MakeFaceWires( objlist.in(), myGroupWire->CheckButton1->isChecked() ); + res = true; } break; case 1: anObj = anOper->MakeFaceFromSurface(myFace.get(), myWire.get()); - res = true; + res = true; + break; + case 2: + { + int numberOfItems = myTreeConstraints->topLevelItemCount(); + GEOM::ListOfGO_var constraints = new GEOM::ListOfGO(); + constraints->length( 2 * numberOfItems ); + int j = 0; + for ( int i = 0; i < numberOfItems; i++ ) { + TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + constraints[j++] = item->getEdge().copy(); + if ( item->getFace() ) + constraints[j++] = item->getFace().copy(); + } + constraints->length(j); + anObj = anOper->MakeFaceWithConstraints( constraints.in() ); + res = true; + } break; default: break; @@ -398,14 +661,40 @@ bool BuildGUI_FaceDlg::execute( ObjectList& objects ) if (!anObj->_is_nil()) { objects.push_back(anObj._retn()); - if (!anOper->IsDone() && QString(anOper->GetErrorCode()) == "MAKE_FACE_TOLERANCE_TOO_BIG") { - SUIT_OverrideCursor wc; - wc.suspend(); - QString msgw = QObject::tr(anOper->GetErrorCode()); - SUIT_MessageBox::warning(this, tr("WRN_WARNING"), msgw, tr("BUT_OK")); + if ( !anOper->IsDone() && QString(anOper->GetErrorCode()) == "MAKE_FACE_TOLERANCE_TOO_BIG") { + if ( !IsPreview() ) { + SUIT_OverrideCursor wc; + wc.suspend(); + QString msgw = QObject::tr(anOper->GetErrorCode()); + SUIT_MessageBox::warning(this, tr("WRN_WARNING"), msgw, tr("BUT_OK")); + } anOper->SetErrorCode("PAL_NO_ERROR"); } } return res; } + +//================================================================================= +// function : addSubshapeToStudy +// purpose : virtual method to add new SubObjects if local selection +//================================================================================= +void BuildGUI_FaceDlg::addSubshapesToStudy() +{ + switch (getConstructorId()) { + case 0: + break; + case 1: + break; + case 2: + for( int i = 0; i < myTreeConstraints->topLevelItemCount(); i++ ) { + TreeWidgetItem* item = dynamic_cast( myTreeConstraints->topLevelItem(i) ); + if ( item->getFace().get() ) + GEOMBase::PublishSubObject( item->getFace().get() ); + GEOMBase::PublishSubObject( myWire.get() ); + } + break; + default: + break; + } +} diff --git a/src/BuildGUI/BuildGUI_FaceDlg.h b/src/BuildGUI/BuildGUI_FaceDlg.h index 29e152781..929630f58 100644 --- a/src/BuildGUI/BuildGUI_FaceDlg.h +++ b/src/BuildGUI/BuildGUI_FaceDlg.h @@ -32,6 +32,9 @@ class DlgRef_1Sel1Check; class DlgRef_2Sel; +class DlgRef_1SelExt; +class QTreeWidget; +class QTreeWidgetItem; //================================================================================= // class : BuildGUI_FaceDlg @@ -41,6 +44,8 @@ class BuildGUI_FaceDlg : public GEOMBase_Skeleton { Q_OBJECT + class TreeWidgetItem; + public: BuildGUI_FaceDlg( GeometryGUI*, QWidget* = 0 ); ~BuildGUI_FaceDlg(); @@ -50,26 +55,35 @@ protected: virtual GEOM::GEOM_IOperations_ptr createOperation(); virtual bool isValid( QString& ); virtual bool execute( ObjectList& ); + virtual void addSubshapesToStudy(); private: void Init(); void enterEvent( QEvent* ); + void updateConstraintsTree(); + void findEmptyTreeItem(); + bool isTreeFull(); private: QList myWires; GEOM::GeomObjPtr myFace; GEOM::GeomObjPtr myWire; - DlgRef_1Sel1Check* GroupWire; + DlgRef_1Sel1Check* myGroupWire; DlgRef_2Sel* myGroupSurf; + DlgRef_1SelExt* myGroupWireConstraints; + + QTreeWidget* myTreeConstraints; + TreeWidgetItem* myCurrentItem; private slots: - void ConstructorsClicked (int); + void ConstructorsClicked( int ); void ClickOnOk(); bool ClickOnApply(); void ActivateThisDialog(); void SelectionIntoArgument(); void SetEditCurrentArgument(); + void onItemClicked( QTreeWidgetItem*, int ); }; #endif // BUILDGUI_FACEDLG_H diff --git a/src/GEOMBase/GEOMBase_Helper.cxx b/src/GEOMBase/GEOMBase_Helper.cxx index 037fd087a..439bfe7ee 100755 --- a/src/GEOMBase/GEOMBase_Helper.cxx +++ b/src/GEOMBase/GEOMBase_Helper.cxx @@ -259,7 +259,8 @@ void GEOMBase_Helper::displayPreview( const bool display, const bool toRemoveFromEngine, const double lineWidth, const int displayMode, - const int color ) + const int color, + const bool append ) { if(!display) { erasePreview( update ); @@ -275,7 +276,8 @@ void GEOMBase_Helper::displayPreview( const bool display, return; } - erasePreview( false ); + if( !append ) + erasePreview( false ); try { SUIT_OverrideCursor wc; diff --git a/src/GEOMBase/GEOMBase_Helper.h b/src/GEOMBase/GEOMBase_Helper.h index 731b63d06..1878610e2 100755 --- a/src/GEOMBase/GEOMBase_Helper.h +++ b/src/GEOMBase/GEOMBase_Helper.h @@ -79,7 +79,8 @@ protected: const bool toRemoveFromEngine = true, const double lineWidth = -1, const int displayMode = -1, - const int color = -1 ); + const int color = -1, + const bool append = false ); // This is the easiest way to show preview. It is based on execute() method. // It removes temporary GEOM::GEOM_Objects automatically. diff --git a/src/GEOMGUI/GEOM_images.ts b/src/GEOMGUI/GEOM_images.ts index 14cf841bc..8b6d59b49 100644 --- a/src/GEOMGUI/GEOM_images.ts +++ b/src/GEOMGUI/GEOM_images.ts @@ -163,6 +163,10 @@ ICON_DLG_BUILD_FACE_SURFACE build_face_surface.png + + ICON_DLG_BUILD_FACE_CONSTRAINTS + build_face_constraints.png + ICON_DLG_FACE_HW face_hw.png diff --git a/src/GEOMGUI/GEOM_msg_en.ts b/src/GEOMGUI/GEOM_msg_en.ts index e3c19fbe2..b5e65a385 100644 --- a/src/GEOMGUI/GEOM_msg_en.ts +++ b/src/GEOMGUI/GEOM_msg_en.ts @@ -707,6 +707,18 @@ Please, select face, shell or solid and try again GEOM_FACE_OPT Try to create a planar face + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMGUI/GEOM_msg_fr.ts b/src/GEOMGUI/GEOM_msg_fr.ts index 037d015c5..0d42a5b67 100644 --- a/src/GEOMGUI/GEOM_msg_fr.ts +++ b/src/GEOMGUI/GEOM_msg_fr.ts @@ -723,6 +723,18 @@ Choisissez une face, une coque ou un solide et essayez de nouveau GEOM_FACE_OPT Privilégier la création d'une face plane + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMGUI/GEOM_msg_ja.ts b/src/GEOMGUI/GEOM_msg_ja.ts index 65c9fcd45..d7d25aab4 100644 --- a/src/GEOMGUI/GEOM_msg_ja.ts +++ b/src/GEOMGUI/GEOM_msg_ja.ts @@ -703,6 +703,18 @@ GEOM_FACE_OPT 平らなフェースを作成 + + GEOM_FACE_FFWC + Face creation from wire and constraints + + + GEOM_CONSTRAINTS + Constraints + + + GEOM_FACE_CONSTRAINT + Constraint Face + GEOM_SOLID_FROM_FACE_OPT Intersect shapes diff --git a/src/GEOMImpl/GEOMImpl_FillingDriver.cxx b/src/GEOMImpl/GEOMImpl_FillingDriver.cxx index 51d554ea7..2c48ce1d0 100644 --- a/src/GEOMImpl/GEOMImpl_FillingDriver.cxx +++ b/src/GEOMImpl/GEOMImpl_FillingDriver.cxx @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,7 @@ #include #include #include +#include #include #include @@ -97,217 +99,255 @@ Standard_Integer GEOMImpl_FillingDriver::Execute(TFunction_Logbook& log) const if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); if (aFunction.IsNull()) return 0; - if (aFunction->GetType() != BASIC_FILLING) return 0; - + TopoDS_Shape aShape; GEOMImpl_IFilling IF (aFunction); - Standard_Integer mindeg = IF.GetMinDeg(); - Standard_Integer maxdeg = IF.GetMaxDeg(); - Standard_Real tol3d = IF.GetTol3D(); - Standard_Boolean isApprox = IF.GetApprox(); - - if (mindeg > maxdeg) { - Standard_RangeError::Raise("Minimal degree can not be more than maximal degree"); - } - - /* we verify the contents of the shape */ - TopExp_Explorer Ex; - TopoDS_Shape Scurrent; - Standard_Real First, Last; - Handle(Geom_Curve) C; - - TopoDS_Compound aComp; - BRep_Builder B; - B.MakeCompound(aComp); - - // input is either a list or compound of contours - TopTools_SequenceOfShape contours; - Handle(TColStd_HSequenceOfTransient) aShapeFunctions = IF.GetShapes(); - if ( aShapeFunctions.IsNull() || aShapeFunctions->IsEmpty() ) return 0; - for ( int i = 1; i <= aShapeFunctions->Length(); ++i ) + if( aFunction->GetType() == BASIC_FILLING ) { - Handle(GEOM_Function) fun = Handle(GEOM_Function)::DownCast( aShapeFunctions->Value( i )); - if ( fun.IsNull() ) return 0; - TopoDS_Shape s = fun->GetValue(); - if ( s.IsNull() ) return 0; - BRepBuilderAPI_Copy Copy (s); - if ( Copy.IsDone() ) - contours.Append( Copy.Shape() ); - } + GEOMImpl_IFilling IF (aFunction); + Standard_Integer mindeg = IF.GetMinDeg(); + Standard_Integer maxdeg = IF.GetMaxDeg(); + Standard_Real tol3d = IF.GetTol3D(); + Standard_Boolean isApprox = IF.GetApprox(); + + if (mindeg > maxdeg) { + Standard_RangeError::Raise("Minimal degree can not be more than maximal degree"); + } - // 1. Convert argument wires, if any, into BSpline edges - for ( int i = 1; i <= contours.Length(); ++i ) - { - Scurrent = contours.Value( i ); - if (Scurrent.ShapeType() != TopAbs_EDGE) { + /* we verify the contents of the shape */ + TopExp_Explorer Ex; + TopoDS_Shape Scurrent; + Standard_Real First, Last; + Handle(Geom_Curve) C; + + TopoDS_Compound aComp; + BRep_Builder B; + B.MakeCompound(aComp); + + // input is either a list or compound of contours + TopTools_SequenceOfShape contours; + Handle(TColStd_HSequenceOfTransient) aShapeFunctions = IF.GetShapes(); + if ( aShapeFunctions.IsNull() || aShapeFunctions->IsEmpty() ) return 0; + for ( int i = 1; i <= aShapeFunctions->Length(); ++i ) + { + Handle(GEOM_Function) fun = Handle(GEOM_Function)::DownCast( aShapeFunctions->Value( i )); + if ( fun.IsNull() ) return 0; + TopoDS_Shape s = fun->GetValue(); + if ( s.IsNull() ) return 0; + BRepBuilderAPI_Copy Copy (s); + if ( Copy.IsDone() ) + contours.Append( Copy.Shape() ); + } + + // 1. Convert argument wires, if any, into BSpline edges + for ( int i = 1; i <= contours.Length(); ++i ) + { + Scurrent = contours.Value( i ); + if (Scurrent.ShapeType() != TopAbs_EDGE) { - if (Scurrent.ShapeType() == TopAbs_WIRE) - { - const TopoDS_Wire& CurWire = TopoDS::Wire(Scurrent); - TopoDS_Edge NewEdge = BRepAlgo::ConcatenateWireC0(CurWire); - if (NewEdge.IsNull()) - Standard_ConstructionError::Raise("Failed to join several edges into one"); - Scurrent = NewEdge; - } - else if (Scurrent.ShapeType() == TopAbs_COMPOUND) - { - for ( TopoDS_Iterator It( Scurrent ); It.More(); It.Next() ) - contours.Append( It.Value() ); - continue; - } - else - { - Standard_ConstructionError::Raise("Input must contain only edges or/and wires"); + if (Scurrent.ShapeType() == TopAbs_WIRE) + { + const TopoDS_Wire& CurWire = TopoDS::Wire(Scurrent); + TopoDS_Edge NewEdge = BRepAlgo::ConcatenateWireC0(CurWire); + if (NewEdge.IsNull()) + Standard_ConstructionError::Raise("Failed to join several edges into one"); + Scurrent = NewEdge; + } + else if (Scurrent.ShapeType() == TopAbs_COMPOUND) + { + for ( TopoDS_Iterator It( Scurrent ); It.More(); It.Next() ) + contours.Append( It.Value() ); + continue; + } + else + { + Standard_ConstructionError::Raise("Input must contain only edges or/and wires"); + } } + B.Add(aComp,Scurrent); } - B.Add(aComp,Scurrent); - } - TopoDS_Shape aShape = aComp; - - // 2. The surface construction - if (!isApprox) { - // make filling as in old version of SALOME (before 4.1.1) - - Standard_Real tol2d = IF.GetTol2D(); - Standard_Integer nbiter = IF.GetNbIter(); - Standard_Integer aMethod = IF.GetMethod(); - - GeomFill_SectionGenerator Section; - Standard_Integer i = 0; - Handle(Geom_Curve) aLastC; - gp_Pnt PL1,PL2; - for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { - Scurrent = Ex.Current(); - if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; - if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; - C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); - //if (Scurrent.Orientation() == TopAbs_REVERSED) - // // Mantis isuue 0020659: consider the orientation of the edges - // C = new Geom_TrimmedCurve(C, Last, First); - //else - // C = new Geom_TrimmedCurve(C, First, Last); - C = new Geom_TrimmedCurve(C, First, Last); - gp_Pnt P1,P2; - C->D0(First,P1); - C->D0(Last,P2); - - if (aMethod == 1 && Scurrent.Orientation() == TopAbs_REVERSED) { - C->Reverse(); - } - else if (aMethod == 2) { - if (i == 0) { - PL1 = P1; - PL2 = P2; + aShape = aComp; + + // 2. The surface construction + if (!isApprox) { + // make filling as in old version of SALOME (before 4.1.1) + + Standard_Real tol2d = IF.GetTol2D(); + Standard_Integer nbiter = IF.GetNbIter(); + Standard_Integer aMethod = IF.GetMethod(); + + GeomFill_SectionGenerator Section; + Standard_Integer i = 0; + Handle(Geom_Curve) aLastC; + gp_Pnt PL1,PL2; + for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { + Scurrent = Ex.Current(); + if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; + if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; + C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); + //if (Scurrent.Orientation() == TopAbs_REVERSED) + // // Mantis isuue 0020659: consider the orientation of the edges + // C = new Geom_TrimmedCurve(C, Last, First); + //else + // C = new Geom_TrimmedCurve(C, First, Last); + C = new Geom_TrimmedCurve(C, First, Last); + gp_Pnt P1,P2; + C->D0(First,P1); + C->D0(Last,P2); + + if (aMethod == 1 && Scurrent.Orientation() == TopAbs_REVERSED) { + C->Reverse(); } - else { - double d1 = PL1.Distance(P1) + PL2.Distance(P2); - double d2 = PL1.Distance(P2) + PL2.Distance(P1); - if (d2 < d1) { - C->Reverse(); - PL1 = P2; - PL2 = P1; - } - else { + else if (aMethod == 2) { + if (i == 0) { PL1 = P1; PL2 = P2; } + else { + double d1 = PL1.Distance(P1) + PL2.Distance(P2); + double d2 = PL1.Distance(P2) + PL2.Distance(P1); + if (d2 < d1) { + C->Reverse(); + PL1 = P2; + PL2 = P1; + } + else { + PL1 = P1; + PL2 = P2; + } + } } - } - Section.AddCurve(C); - i++; - } + Section.AddCurve(C); + i++; + } - /* a 'tolerance' is used to compare 2 knots : see GeomFill_Generator.cdl */ - Section.Perform(Precision::PConfusion()); - Handle(GeomFill_Line) Line = new GeomFill_Line(i); + /* a 'tolerance' is used to compare 2 knots : see GeomFill_Generator.cdl */ + Section.Perform(Precision::PConfusion()); + Handle(GeomFill_Line) Line = new GeomFill_Line(i); - GeomFill_AppSurf App (mindeg, maxdeg, tol3d, tol2d, nbiter); /* user parameters */ - App.Perform(Line, Section); + GeomFill_AppSurf App (mindeg, maxdeg, tol3d, tol2d, nbiter); /* user parameters */ + App.Perform(Line, Section); - if (!App.IsDone()) return 0; - Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots; - App.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots); - Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface - (App.SurfPoles(), App.SurfWeights(), App.SurfUKnots(), App.SurfVKnots(), - App.SurfUMults(), App.SurfVMults(), App.UDegree(), App.VDegree()); + if (!App.IsDone()) return 0; + Standard_Integer UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots; + App.SurfShape(UDegree, VDegree, NbUPoles, NbVPoles, NbUKnots, NbVKnots); + Handle(Geom_BSplineSurface) GBS = new Geom_BSplineSurface + (App.SurfPoles(), App.SurfWeights(), App.SurfUKnots(), App.SurfVKnots(), + App.SurfUMults(), App.SurfVMults(), App.UDegree(), App.VDegree()); - if (GBS.IsNull()) return 0; - aShape = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion()); - } - else { - // implemented by skl 20.03.2008 for bug 16568 - // make approximation - try to create bspline surface - // using GeomAPI_PointsToBSplineSurface - - TColGeom_SequenceOfCurve aSeq; - int MaxNbPoles = 0; - - // add curves from edges to sequence and find maximal - // number of poles if some of them are bsplines - for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { - Scurrent = Ex.Current(); - if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; - if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; - C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); - Handle(Geom_TrimmedCurve) TC = Handle(Geom_TrimmedCurve)::DownCast(C); - if (TC.IsNull()) { - Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(C); - if (!BC.IsNull()) { - MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + if (GBS.IsNull()) return 0; + aShape = BRepBuilderAPI_MakeFace(GBS, Precision::Confusion()); + } + else { + // implemented by skl 20.03.2008 for bug 16568 + // make approximation - try to create bspline surface + // using GeomAPI_PointsToBSplineSurface + + TColGeom_SequenceOfCurve aSeq; + int MaxNbPoles = 0; + + // add curves from edges to sequence and find maximal + // number of poles if some of them are bsplines + for (Ex.Init(aShape, TopAbs_EDGE); Ex.More(); Ex.Next()) { + Scurrent = Ex.Current(); + if (Scurrent.IsNull() || Scurrent.ShapeType() != TopAbs_EDGE) return 0; + if (BRep_Tool::Degenerated(TopoDS::Edge(Scurrent))) continue; + C = BRep_Tool::Curve(TopoDS::Edge(Scurrent), First, Last); + Handle(Geom_TrimmedCurve) TC = Handle(Geom_TrimmedCurve)::DownCast(C); + if (TC.IsNull()) { + Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(C); + if (!BC.IsNull()) { + MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + } } - } - else { - Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(TC->BasisCurve()); - if (BC.IsNull()) { - Handle(Geom_TrimmedCurve) TC1 = Handle(Geom_TrimmedCurve)::DownCast(TC->BasisCurve()); - if (!TC1.IsNull()) { - BC = Handle(Geom_BSplineCurve)::DownCast(TC1->BasisCurve()); + else { + Handle(Geom_BSplineCurve) BC = Handle(Geom_BSplineCurve)::DownCast(TC->BasisCurve()); + if (BC.IsNull()) { + Handle(Geom_TrimmedCurve) TC1 = Handle(Geom_TrimmedCurve)::DownCast(TC->BasisCurve()); + if (!TC1.IsNull()) { + BC = Handle(Geom_BSplineCurve)::DownCast(TC1->BasisCurve()); + } + } + if (!BC.IsNull()) { + MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); } } - if (!BC.IsNull()) { - MaxNbPoles = Max(MaxNbPoles,BC->NbPoles()); + aSeq.Append(C); + } + // prepare array of points for creation bspline surface + // size of this array: by U parameter - number of curves, + // by V parameter - determ using MaxNbPoles but it's + // value must be between 21(min) and 101(max) + int nbc = aSeq.Length(); + int nbp = Max(21, 2*MaxNbPoles-1); + + // commented for Mantis issue 0021541 + //if (nbp > 101) nbp = 101; + + TColgp_Array2OfPnt Points (1, nbc, 1, nbp); + int ic = 1; + for (; ic <= nbc; ic++) { + Handle(Geom_Curve) C = aSeq.Value(ic); + double fp = C->FirstParameter(); + double lp = C->LastParameter(); + double dp = (lp-fp)/(nbp-1); + int j = 0; + gp_Pnt P; + for (; j < nbp; j++) { + C->D0(fp+dp*j, P); + Points.SetValue(ic, j+1, P); + } + } + GeomAPI_PointsToBSplineSurface PTB (Points, mindeg, maxdeg, GeomAbs_C2, tol3d); + Handle(Geom_BSplineSurface) BS = PTB.Surface(); + BRepBuilderAPI_MakeFace BB (BS, Precision::Confusion()); + TopoDS_Face NewF = BB.Face(); + Handle(ShapeFix_Face) sff = new ShapeFix_Face (NewF); + sff->Perform(); + sff->FixOrientation(); + aShape = sff->Face(); + } + } + else if( aFunction->GetType() == FILLING_ON_CONSTRAINTS ) + { + BRepOffsetAPI_MakeFilling MakeFilling; + + Handle(TColStd_HSequenceOfTransient) aConstraints = IF.GetShapes(); + + for ( unsigned int ind = 1; ind <= aConstraints->Length(); ind++ ) { + TopoDS_Edge E; + TopoDS_Face F; + Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast( aConstraints->Value(ind) ); + if ( !aRefShape->GetValue().IsNull() && aRefShape->GetValue().ShapeType() == TopAbs_EDGE ) + E = TopoDS::Edge(aRefShape->GetValue() ); + else { + Standard_RangeError::Raise("Wrong parameters"); + } + if ( ind < aConstraints->Length() ) { + Handle(GEOM_Function) aRefFaceShape = Handle(GEOM_Function)::DownCast( aConstraints->Value(ind+1) ); + if ( !aRefFaceShape->GetValue().IsNull() && aRefFaceShape->GetValue().ShapeType() == TopAbs_FACE ) { + F = TopoDS::Face( aRefFaceShape->GetValue() ); + ind++; } } - aSeq.Append(C); + if ( !F.IsNull() ) + MakeFilling.Add( E, F, GeomAbs_G1 ); + else + MakeFilling.Add( E, GeomAbs_C0 ); } - // prepare array of points for creation bspline surface - // size of this array: by U parameter - number of curves, - // by V parameter - determ using MaxNbPoles but it's - // value must be between 21(min) and 101(max) - int nbc = aSeq.Length(); - int nbp = Max(21, 2*MaxNbPoles-1); - - // commented for Mantis issue 0021541 - //if (nbp > 101) nbp = 101; - - TColgp_Array2OfPnt Points (1, nbc, 1, nbp); - int ic = 1; - for (; ic <= nbc; ic++) { - Handle(Geom_Curve) C = aSeq.Value(ic); - double fp = C->FirstParameter(); - double lp = C->LastParameter(); - double dp = (lp-fp)/(nbp-1); - int j = 0; - gp_Pnt P; - for (; j < nbp; j++) { - C->D0(fp+dp*j, P); - Points.SetValue(ic, j+1, P); - } + + MakeFilling.Build(); + if ( !MakeFilling.IsDone() ) + { + Standard_RangeError::Raise("Filling on constraints failed"); } - GeomAPI_PointsToBSplineSurface PTB (Points, mindeg, maxdeg, GeomAbs_C2, tol3d); - Handle(Geom_BSplineSurface) BS = PTB.Surface(); - BRepBuilderAPI_MakeFace BB (BS, Precision::Confusion()); - TopoDS_Face NewF = BB.Face(); - Handle(ShapeFix_Face) sff = new ShapeFix_Face (NewF); - sff->Perform(); - sff->FixOrientation(); - aShape = sff->Face(); + + aShape = TopoDS::Face( MakeFilling.Shape() ); } /* We test the validity of resulting shape */ if (!BRepAlgo::IsValid((aShape))) { Standard_ConstructionError::Raise("Algorithm has produced an invalid shape result"); - return 0; } aFunction->SetValue(aShape); @@ -351,6 +391,12 @@ GetCreationInformation(std::string& theOperationName, AddParam( theParams, "Approximation", aCI.GetApprox() ); break; } + case FILLING_ON_CONSTRAINTS: + { + theOperationName = "FACE"; + AddParam( theParams, "Edges/Faces", aCI.GetShapes() ); + break; + } default: return false; } diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index da8445efc..1a7c43205 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -34,11 +34,13 @@ #include "GEOMImpl_VectorDriver.hxx" #include "GEOMImpl_ShapeDriver.hxx" #include "GEOMImpl_GlueDriver.hxx" +#include "GEOMImpl_FillingDriver.hxx" #include "GEOMImpl_IVector.hxx" #include "GEOMImpl_IShapes.hxx" #include "GEOMImpl_IShapeExtend.hxx" #include "GEOMImpl_IGlue.hxx" +#include "GEOMImpl_IFilling.hxx" #include "GEOMImpl_Block6Explorer.hxx" #include "GEOMImpl_IHealingOperations.hxx" @@ -677,6 +679,107 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceFromSurface return aShape; } +//============================================================================= +/*! + * MakeFaceWithConstraints + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IShapesOperations::MakeFaceWithConstraints + (std::list theConstraints) +{ + SetErrorCode(KO); + + //Add a new object + Handle(GEOM_Object) aShape = GetEngine()->AddObject(GetDocID(), GEOM_FILLING); + + //Add a new function + Handle(GEOM_Function) aFunction = + aShape->AddFunction(GEOMImpl_FillingDriver::GetID(), FILLING_ON_CONSTRAINTS); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_FillingDriver::GetID()) return NULL; + + GEOMImpl_IFilling aCI (aFunction); + Handle(TColStd_HSequenceOfTransient) aConstraints = new TColStd_HSequenceOfTransient; + + // Shapes + std::list::iterator it = theConstraints.begin(); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it); + if ( anObject.IsNull() || anObject->GetValue().ShapeType() != TopAbs_EDGE ) { + SetErrorCode("NULL argument edge for the face construction"); + return NULL; + } + Handle(GEOM_Function) aRefSh = anObject->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + if ( it != theConstraints.end() ) { + Handle(GEOM_Object) aFace = (*it); + if ( aFace.IsNull() ) { + // null constraint face - it is a valid case + it++; + continue; + } + if ( aFace->GetValue().ShapeType() != TopAbs_FACE ) + // constraint face can be omitted - it is a valid case + continue; + if ( IsSubShapeBelongsTo( anObject, 0, aFace, 0 ) ) { + // valid constraint + aRefSh = aFace->GetLastFunction(); + aConstraints->Append(aRefSh); + it++; + } + else { + // bad constraint + SetErrorCode("Face is NULL or not connected to the Edge"); + return NULL; + } + } + } + aCI.SetShapes( aConstraints ); + + //Compute the shape + Standard_Boolean isWarning = Standard_False; + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Shape driver failed"); + return NULL; + } + } + catch (Standard_Failure) { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + SetErrorCode(aFail->GetMessageString()); + // to provide warning + if (!aFunction->GetValue().IsNull()) { + isWarning = Standard_True; + } else { + return NULL; + } + } + + //Make a Python command + GEOM::TPythonDump pd (aFunction); + pd << aShape << " = geompy.MakeFaceWithConstraints(["; + + // Constraints + it = theConstraints.begin(); + if (it != theConstraints.end() ) { + pd << (*it++); + while (it != theConstraints.end()) { + Handle(GEOM_Object) anObject = (*it++); + if( !anObject.IsNull() ) + pd << ", " << anObject; + } + } + pd << "])"; + + // to provide warning + if (!isWarning) SetErrorCode(OK); + return aShape; +} + //============================================================================= /*! * MakeShell @@ -1940,6 +2043,39 @@ TCollection_AsciiString GEOMImpl_IShapesOperations::GetShapeTypeString (Handle(G return aTypeName; } +//============================================================================= +/*! + * IsSubShapeBelongsTo + */ +//============================================================================= +Standard_Boolean GEOMImpl_IShapesOperations::IsSubShapeBelongsTo( Handle(GEOM_Object) theSubObject, + const Standard_Integer theSubObjectIndex, + Handle(GEOM_Object) theObject, + const Standard_Integer theObjectIndex) +{ + if ( theObject.IsNull() || theSubObject.IsNull() ) + return false; + + TopoDS_Shape shape = theObject->GetValue(); + TopoDS_Shape subShape = theSubObject->GetValue(); + + if ( shape.IsNull() || subShape.IsNull() ) + return false; + + TopTools_IndexedMapOfShape anIndices; + if ( theObjectIndex > 0 ) { + TopExp::MapShapes( shape, anIndices ); + shape = anIndices.FindKey(theObjectIndex); + } + if ( theSubObjectIndex > 0 ) { + TopExp::MapShapes( subShape, anIndices ); + subShape = anIndices.FindKey(theSubObjectIndex); + } + + TopExp::MapShapes( shape, anIndices ); + return anIndices.Contains( subShape ); +} + //============================================================================= /*! * NumberOfSubShapes diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index dca4233a9..06b35dac4 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -88,6 +88,8 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Standard_EXPORT Handle(GEOM_Object) MakeFaceFromSurface (Handle(GEOM_Object) theFace, Handle(GEOM_Object) theWire); + + Standard_EXPORT Handle(GEOM_Object) MakeFaceWithConstraints (std::list theConstraints); Standard_EXPORT Handle(GEOM_Object) MakeShell (std::list theShapes); @@ -160,6 +162,11 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Standard_EXPORT TCollection_AsciiString GetShapeTypeString (Handle(GEOM_Object) theShape); + Standard_EXPORT Standard_Boolean IsSubShapeBelongsTo(Handle(GEOM_Object) theSubObject, + const Standard_Integer theSubObjectIndex, + Handle(GEOM_Object) theObject, + const Standard_Integer theObjectIndex); + Standard_EXPORT Standard_Integer NumberOfSubShapes (Handle(GEOM_Object) theShape, const Standard_Integer theShapeType); diff --git a/src/GEOMImpl/GEOMImpl_Types.hxx b/src/GEOMImpl/GEOMImpl_Types.hxx index f7f329ebb..272db63b8 100644 --- a/src/GEOMImpl/GEOMImpl_Types.hxx +++ b/src/GEOMImpl/GEOMImpl_Types.hxx @@ -331,6 +331,7 @@ #define DIVIDE_EDGE_BY_POINT 13 #define BASIC_FILLING 1 +#define FILLING_ON_CONSTRAINTS 2 #define GLUE_FACES 1 #define GLUE_FACES_BY_LIST 2 diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc index dce57e0aa..334846938 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -279,6 +279,37 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeFaceFromSurface return GetObject(anObject); } +//============================================================================= +/*! + * MakeFaceWithConstraints + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::MakeFaceWithConstraints + (const GEOM::ListOfGO& theConstraints) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the shapes + std::list aConstraints; + for( int ind = 0; ind < theConstraints.length(); ind++ ) { + Handle(GEOM_Object) anObject = GetObjectImpl( theConstraints[ind] ); + aConstraints.push_back(anObject); + } + + // Make Face + Handle(GEOM_Object) anObject = + GetOperations()->MakeFaceWithConstraints( aConstraints ); + + // enable warning status + if (anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * MakeShell @@ -976,6 +1007,25 @@ char* GEOM_IShapesOperations_i::GetShapeTypeString (GEOM::GEOM_Object_ptr theSha return CORBA::string_dup(aDescription.ToCString()); } +//============================================================================= +/*! + * IsSubShapeBelongsTo + */ +//============================================================================= +CORBA::Boolean GEOM_IShapesOperations_i::IsSubShapeBelongsTo( GEOM::GEOM_Object_ptr theSubObject, + const CORBA::Long theSubObjectIndex, + GEOM::GEOM_Object_ptr theObject, + const CORBA::Long theObjectIndex) +{ + Handle(GEOM_Object) aSubObject = GetObjectImpl( theSubObject ); + Handle(GEOM_Object) anObject = GetObjectImpl( theObject ); + if( anObject.IsNull() || aSubObject.IsNull() ) + return false; + + // Get parameters + return GetOperations()->IsSubShapeBelongsTo( aSubObject, theSubObjectIndex, anObject, theObjectIndex ); +} + //============================================================================= /*! * NumberOfFaces diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index 5ba281994..944096750 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -67,6 +67,8 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : GEOM::GEOM_Object_ptr MakeFaceFromSurface(GEOM::GEOM_Object_ptr theFace, GEOM::GEOM_Object_ptr theWire); + GEOM::GEOM_Object_ptr MakeFaceWithConstraints (const GEOM::ListOfGO& theConstraints); + GEOM::GEOM_Object_ptr MakeShell (const GEOM::ListOfGO& theFacesAndShells); GEOM::GEOM_Object_ptr MakeSolidShell (GEOM::GEOM_Object_ptr theShell); @@ -144,6 +146,11 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : char* GetShapeTypeString (GEOM::GEOM_Object_ptr theShape); + CORBA::Boolean IsSubShapeBelongsTo( GEOM::GEOM_Object_ptr theSubobject, + const CORBA::Long theSubObjectIndex, + GEOM::GEOM_Object_ptr theObject, + const CORBA::Long theObjectIndex ); + CORBA::Long NumberOfFaces (GEOM::GEOM_Object_ptr theShape); CORBA::Long NumberOfEdges (GEOM::GEOM_Object_ptr theShape); CORBA::Long NumberOfSubShapes (GEOM::GEOM_Object_ptr theShape, diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.cc b/src/GEOM_I_Superv/GEOM_Superv_i.cc index 266252668..7c4409f7e 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.cc +++ b/src/GEOM_I_Superv/GEOM_Superv_i.cc @@ -2274,6 +2274,24 @@ GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFaceWires (GEOM::GEOM_List_ptr theWires return NULL; } +//============================================================================= +// MakeFaceWithConstraints: +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_Superv_i::MakeFaceWithConstraints (GEOM::GEOM_List_ptr theConstraints) +{ + beginService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + MESSAGE("GEOM_Superv_i::MakeFaceWithConstraints"); + if (GEOM_List_i* aConstraints = + dynamic_cast*>(GetServant(theConstraints, myPOA).in())) { + getShapesOp(); + GEOM::GEOM_Object_ptr anObj = myShapesOp->MakeFaceWithConstraints(aConstraints->GetList()); + endService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + return anObj; + } + endService( " GEOM_Superv_i::MakeFaceWithConstraints" ); + return NULL; +} + //============================================================================= // MakeShell: //============================================================================= diff --git a/src/GEOM_I_Superv/GEOM_Superv_i.hh b/src/GEOM_I_Superv/GEOM_Superv_i.hh index a41e6b32f..3d59b32bc 100644 --- a/src/GEOM_I_Superv/GEOM_Superv_i.hh +++ b/src/GEOM_I_Superv/GEOM_Superv_i.hh @@ -503,6 +503,7 @@ public: CORBA::Boolean isPlanarWanted); GEOM::GEOM_Object_ptr MakeFaceWires (GEOM::GEOM_List_ptr theWires, CORBA::Boolean isPlanarWanted); + GEOM::GEOM_Object_ptr MakeFaceWithConstraints (GEOM::GEOM_List_ptr theConstraints); GEOM::GEOM_Object_ptr MakeShell (GEOM::GEOM_List_ptr theFacesAndShells); GEOM::GEOM_Object_ptr MakeSolidShell (GEOM::GEOM_Object_ptr theShell); GEOM::GEOM_Object_ptr MakeSolidShells (GEOM::GEOM_List_ptr theShells); diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index 6dafa5265..2fef6a4c5 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -179,6 +179,12 @@ def TestAll (geompy, math): Face3 = geompy.MakeFaceHW (100., 200., 1) #(2 Doubles, 1 Int)->GEOM_Object Face4 = geompy.MakeFaceObjHW (vz, 200., 100.) #(1 GEOM_Object, 2 Doubles)->GEOM_Object Face5 = geompy.MakeFaceFromSurface(Face, Sketcher) #(2 GEOM_Objects)->GEOM_Object + + Cut2 = geompy.MakeCutList(Sphere1, [Box1], True) + #(List of GEOM_Object)->GEOM_Object + Face6 = geompy.MakeFaceWithConstraints([geompy.GetSubShape(Cut2, [5]), geompy.GetSubShape(Cut2, [3]), + geompy.GetSubShape(Cut2, [11]), geompy.GetSubShape(Cut2, [3]), + geompy.GetSubShape(Cut2, [13]), geompy.GetSubShape(Cut2, [3])]) Disk = geompy.MakeDiskPntVecR (p0, vz, radius) #(2 GEOM_Object, 1 Double)->GEOM_Object Disk2 = geompy.MakeDiskThreePnt(p0, p200, pz) #(3 GEOM_Object)->GEOM_Object Disk3 = geompy.MakeDiskR(100., 1) #(1 Doubles, 1 Int)->GEOM_Object @@ -396,6 +402,7 @@ def TestAll (geompy, math): id_Common = geompy.addToStudy(Common, "Common") id_Cut = geompy.addToStudy(Cut, "Cut") + id_Cut2 = geompy.addToStudy(Cut2, "Cut2") id_Fuse = geompy.addToStudy(Fuse, "Fuse") id_Section = geompy.addToStudy(Section, "Section") @@ -408,6 +415,7 @@ def TestAll (geompy, math): id_Face3 = geompy.addToStudy(Face3, "Face Height Width") id_Face4 = geompy.addToStudy(Face4, "Face Plane_HW") id_Face5 = geompy.addToStudy(Face5, "Face from surface and wire") + id_Face6 = geompy.addToStudy(Face6, "Face from edges with constraints") id_Disk = geompy.addToStudy(Disk, "Disk PntVecR") id_Disk2 = geompy.addToStudy(Disk2, "Disk Three Points") id_Disk3 = geompy.addToStudy(Disk3, "Disk OXY Radius") diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 83c2e34b0..07535cdf9 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -4555,6 +4555,42 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): RaiseIfFailed("MakeFaceFromSurface", self.ShapesOp) self._autoPublish(anObj, theName, "face") return anObj + + ## Create a face from a set of edges with the given constraints. + # @param theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + # - edges should form a closed wire; + # - for each edge, constraint face is optional: if a constraint face is missing + # for some edge, this means that there no constraint associated with this edge. + # @param theName Object name; when specified, this parameter is used + # for result publication in the study. Otherwise, if automatic + # publication is switched on, default value is used for result name. + # + # @return New GEOM.GEOM_Object, containing the created face. + # + # @ref tui_creation_face "Example" + @ManageTransactions("ShapesOp") + def MakeFaceWithConstraints(self, theConstraints, theName=None): + """ + Create a face from a set of edges with the given constraints. + + Parameters: + theConstraints List of edges and constraint faces (as a sequence of a Edge + Face couples): + - edges should form a closed wire; + - for each edge, constraint face is optional: if a constraint face is missing + for some edge, this means that there no constraint associated with this edge. + theName Object name; when specified, this parameter is used + for result publication in the study. Otherwise, if automatic + publication is switched on, default value is used for result name. + + Returns: + New GEOM.GEOM_Object, containing the created face. + """ + # Example: see GEOM_TestAll.py + anObj = self.ShapesOp.MakeFaceWithConstraints(theConstraints) + if anObj is None: + RaiseIfFailed("MakeFaceWithConstraints", self.ShapesOp) + self._autoPublish(anObj, theName, "face") + return anObj ## Create a shell from the set of faces and shells. # @param theFacesAndShells List of faces and/or shells. @@ -6244,6 +6280,38 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): self._autoPublish(ListObj, theName, "subshape") return ListObj + ## Check if the object is a sub-object of another GEOM object. + # @param aSubObject Checked sub-object (or its parent object, in case if + # \a theSubObjectIndex is non-zero). + # @param anObject An object that is checked for ownership (or its parent object, + # in case if \a theObjectIndex is non-zero). + # @param aSubObjectIndex When non-zero, specifies a sub-shape index that + # identifies a sub-object within its parent specified via \a theSubObject. + # @param anObjectIndex When non-zero, specifies a sub-shape index that + # identifies an object within its parent specified via \a theObject. + # @return TRUE, if the given object contains sub-object. + @ManageTransactions("ShapesOp") + def IsSubShapeBelongsTo(self, aSubObject, anObject, aSubObjectIndex = 0, anObjectIndex = 0): + """ + Check if the object is a sub-object of another GEOM object. + + Parameters: + aSubObject Checked sub-object (or its parent object, in case if + \a theSubObjectIndex is non-zero). + anObject An object that is checked for ownership (or its parent object, + in case if \a theObjectIndex is non-zero). + aSubObjectIndex When non-zero, specifies a sub-shape index that + identifies a sub-object within its parent specified via \a theSubObject. + anObjectIndex When non-zero, specifies a sub-shape index that + identifies an object within its parent specified via \a theObject. + + Returns + TRUE, if the given object contains sub-object. + """ + IsOk = self.ShapesOp.IsSubShapeBelongsTo(aSubObject, aSubObjectIndex, anObject, anObjectIndex) + RaiseIfFailed("IsSubShapeBelongsTo", self.ShapesOp) + return IsOk + # end of l4_decompose ## @} -- 2.39.2