From 85342cd8ae1eae7673717a3295948178a869038e Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Fri, 8 Jun 2012 20:00:44 +0430 Subject: [PATCH] Pocket Feature: up to first/last/face and through all options --- data/tests/PocketTest.fcstd | Bin 0 -> 13766 bytes src/Mod/PartDesign/App/FeaturePocket.cpp | 174 ++++++++++++++---- src/Mod/PartDesign/App/FeaturePocket.h | 1 + .../PartDesign/Gui/TaskPocketParameters.cpp | 102 +++++++++- src/Mod/PartDesign/Gui/TaskPocketParameters.h | 7 +- .../PartDesign/Gui/TaskPocketParameters.ui | 120 ++++++++---- 6 files changed, 329 insertions(+), 75 deletions(-) create mode 100644 data/tests/PocketTest.fcstd diff --git a/data/tests/PocketTest.fcstd b/data/tests/PocketTest.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..6acf91ba055c2b8fd6614aecde44c161b3f5d616 GIT binary patch literal 13766 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ᦼtE8*hggt3Jh9hHn$wfCOYY8^9hq8CUpQvfhHn5p>3uOuH3{M5!Iv zqNf>9_392pBAoE)!Z?yqb!js~*k;{$DzygZOQZ?mpA)`_cp#_IN zbg@_V-d;YjTGgtHHDtj)s``t;|>m(XB&1se414TB;UtBt!r{u3P! za+)-HHsi74!glT|)H!OUR=Ejfjg2g}TSvdrUo{PDcXaJ|4Mq5t^3?lQ=Vq+=OUtOk zbQtAe+UBV&O{wGwitCd&ayPRfndG%b#vGNoRn~q_<2>Jz!kbN42ifgip7+o|>94{H z3IYG~wcT?J@R_mO7@_4((qFA3O=ynCS|NmzwdE}EhT&@Wyerx`%l8pL%)^;5jfYlvnoMSsDMcZ?1H%lws@5ResBhlj3##aBC=m#!OGl&RE! z7wOkgfqeeYU!UhGUj0utzdvpYcK8F<{Jg&&4_gk?hjQv?zqWfoR~I{df-WeMC$d(; zIpRJH7xa%52%Ll}aikD`4eWu}nb;p{tJujSl$lpWa;#>Hfv*SKz!r8jgd}NBdmV~_gl_DYE#Tgk1+wz4<5siy4$|}<@bB@^Oak8Il9)!n*dz# z6`@6Hysiac+6<+M2yHK%fR16Ng?(pc@R{ufDP)4k%v#F#suW?^@)eopo^dM@LJq4i>#TmXwL}A_mxU2(%+ct|;uy6Zr43m5K*d4p&R7)n zj$9)#N@ys3$ttVy{7_O!(}rKI;{J`_(&l23u{MI)28JKxeNvnb@2;?EG4%tFC-lfP zS$*rlW6JNnrB;O6B{p4()xo)sz~FWtq2^E?p>NXXf*s;R%iv1!sT4Q)A(<6Hk~8+G zwbW2J!C|a-D+Xdwv^Iibf(E51d$7Y{cI)8GQ&FDE&Z z%II{lC?(3FBpe-Zl{Ce|93_D>N_+qvE2}ltH0Y95fuorq*v?R&mLv#!qNyw?Q6OO| zF`8FI7Jb~2eCl+~4h&UQBb3k*>sw?Rtq3^jSZ4|`@n%z(Jh9r8A)@JRnsStPlr|_v zVc&ZO0NOA$v|O|%t-BLc{FLxpGj+uyy@4@YO)hVZi(+P!L1y6$KH`Gjq|57|$a(;q zjKt;Fwm%}&4~1yfmbdUyX%PrD&2}(4%5KC-JAI{NLsPOkP`XWR zw}glv!8-Cg`)E;;7sF|4@a?*=d%o;Kz|_DXHq%x3pM<7W8gBH&4_5Kz_I)`VlxC!B zro$bCO3d=BZ*5>1YM4Mwk@}M2scpiP6~vo4Wya7sNY!P`s-`wEnxlXt!TNZ_sRtDz z@suqmNg$Ku$XYsAywXWD3IHL(#ZKTdPzAS^n3=(FiADGZ>6=+=HxjHeJ_TQZa zb3P*tt=|T|zy*)2=e`;}vb5xUDHDrjnjiA@u$W3kxXO*B&*QCP(*(Wg3BzX-T(I%f zW+B*Gg0_X|M8w+KBIPudG69HOM57hvYVk7^Y;|2O!;$O=OImccoo7ov2QbfUXZ_Kk z!f!kdbn~{49_*Gjma~1`zbU(1txs*ge`sn3Fe-u+|H;Z{0{lks-`w_sjKXdjgjf{( z9S-V*y6E@7#CemT^nf4;`ZGG@SgFds+pH%Pueq_M3@dOPj?Ph9PBE)x;X4$Vnt}9u zpW*>2SSKC(>2eNuC+(>joUm@ts&s+Ztb0JD`Ha(ImeT2Pvc%E{AWGRcq%~=nKG@Q3 z$YvBy7^r9R+Ed?JWdE02*~P> z>iiGAkmavdGfip0evlEi=Z(g9%kbM}DEoPml6?+4+;F@K1Xi_bYb7}Or@uU8N+8Ot z(h;TCEQ9;q3pzW2*hRp*1)BM;KMD}};kv1=tkaHdc9j-^;{bwZd-s?{pIs02`^wE! zovpQ}b-F)|R0K9AXXA?Hik5X|q_~h%_-WyN$w70ov2aIN;7{dS<-KAM;-Z6L)AZUY zx%>sm3!4IB80@5DI%HY*EB-Sz4{09L?`or@soHkTuQmuF;mE{o>Gvq5`mpJVlONGp zay9NGZNtI5&ik$3;4jMA!&13U7#_Rn{CalO#^_O|-LEnX!q1L>!k>Hq@vt^P^$R71 zttq=Tl_^z3&Hree$_o_g21bm5Gsf(91z)@Wgbj(M=p>s)zJl#qN@S&1aCxaff`uEk zA7>AIMkchLcsHsH;{?JKuQm8*unms~3z`2!*M)YZpYqwlz4hJF$6lhx2k`2R@dEmaRK!fz9H7kk0Pkk zlx>+*__0m;rUS(J;&vFRjb3;4UTF{Ow4maf;wJOuc&9d>V0)`981 zLYQvbW&9=sg4c8W8Tqlxj1^a^2Z()jv?bA&=pf;-%CX7dnQ}tRb$l>McuLf8b>~8q zGP97wODZ@EZ@RE1MIEyd_Iu&@;l~BkH-#Y42zYK7QQ=x16syqpD9N`y?2}%jVOy&N zU$n!6C7-QscYd0d+_^`F_+JX^B1QTh(U$JJJ+QxuGB=ipPO8?TO!ev{LDicGy;Qq| z=~oYA8Aj}(@kX6uKW)#^6r{rF>o^3@W8WG&(O_Gy;Xs>Pr8O#ObD_1kxjW92MaGi% z%3fi}Tc6e~m+=!n8s{;(I`F2`(&#b8Z0X$j?$<(xZwt2m1hppkjR{QhZJ_^(&`y#B z#ls}Ns4;auXT$usP^muFjmo;x{r05M<#THqj>F+c_w_zeKaFq81eF;CTSJwGNmK!Y z!%TK3&6Q@gpGi5(BscKbVQUYuHpypQ2S>!tvET}>gIK3Uc#asObU01psWeyij%Xgp zduA*xnZ!IS%JLmbbNebWmyJ{$Mb!4l=1TB1pKhFsG&8rA4D_sxSgb!^aDcEx7h}2p znYRYmuj+1lJG9l8{k&Ay?|u4}@i2TZ&TjqRuaC-UXm~^%yTHS{(!*>LqS&}}irk$X zdi5-a7Hhf$MdDoJ9mmJws|%4HL**Q@YtslXIXKIe5oUidvr z{DxhifT+nywTzEso|SSR21Fs{Ywl7Q6Swt1;#K5!xch-xkgGs|7{8!N{7UvO#6UWN z7!M2w#)YwqIr^qM+kv`_XU;6Ap+`XOb!wrUdF)H0RnXe?jqFx~p8P-rB%&BU`+s1! zwOe{)=S%f`K5=i78g$@z6I(evE3y-Rj4MrWe~6Pz~e9ZX966oq<-A6szU-p(^W$0 z#N&WY2&g0&x(_9!GUzh9Iul%FzOidR26W78eSX z=~a0Um&TegTqHr0$m5>ot<-xNbb|LS${n0J>Ca0_k&_fKxnzq7lS^PWP*E4T@@N8E zQ!pXrQJ3+riY=70G zL=kTnA=DL#9vjo5#m>;-Pje9{i}SlfM^^1Qx)8$p4Y&5lMO2PHc$^pJVJV3h#Rhy`T}^q^6YTgu z-_3YN%U|jL5%O;$G%DF2{Ho%_E8K{$Q6_8`8=M@fwGd-T^&{_jB@=45)ZgugD%sJ?9*v&l=;C81q>{I*ga!<_TRG{*1INoc-mIr%HO58}POus#R%GH>R z^1CyaFW3&U&G-;5Sblou$Y>|KP#11~Uii%W#7d+&Kcs|P*n){l=<1{T zQ(OM9;o*DS#E^Kl`Fjg4`m;pM%g4xd&gw`hE6B+aCvZqVC#37h6VTnrwE}|Thtl#$ zWwiINw5votJ#(GMe5S`u4o#f2cL}_*>FzU9cKD4}xANhw)Jz=_i(j~xdErHiOQkJ$ z3$ofI9^>GVN@6zeU0n9#W38^zIidXUm*hP&5cviEx=`Zo zX$OJb{W95g-E>c!p}|kQ@^%M=QRMLwqb))xO)Q6^rfbF)NpTqxB4ch=Nw#~A8cAzZ z=4^SMDDdm7xD?`O^u+k}33W`MAm8St3_BKrrDS#BOblhTcnhDk9P`_(Y&5fDHyt^1 zyT&9e5k(xJ#X(!kjLO+;iOsZSTC#POk1922;`02M1w}kPvy2l*4dqJqPqk6(+@OhR z(!wn`#4pr$63=L&nKfGkvFh=P=Peb%QAg*dSht0fKfrpb{R7ph0oDUE{q zy_}A9!nuRKP|`OR(Xxn^*D+*WvJ(B;6fkgvc$5eSs(y9wGVU7WuwB zUI6ji)dT9?i7+oC7p&JQ*$M-~usZlC7sXzh0_rl$l`7K$37K1X5L3ky37#{-6?naZ zw55eknP7K&v>GW-Aw1rMlLV2;*8-8CLNo&u2@Ef9h&E6c!Gw5%m(FRImYbWoH7W|7 z(bGS-mvg`}V$7zMl*tDbV!o5sYcCFko0@SU5I24A{5|tA;QQNlnj}B@;9t$ zxB09gp_(NsSRMiN4tJuQ878s@c~Z%Cbf{x+&xXcKq41PT5)C%=gh?rG{1fN) z?ZW{jhV62dnQWabpj=>7{uf`}1f_MdE`sM{#OKufk_+pjFM&hoe88)Uqg8a?JM)QA zAzMZxN_z6hkDz|Gn2bB#9nB4sLKQc$U)Z3DswQFgC>P{TGn9;`vaRIQnD4@>5+hMY z7T^>o6UgMKVl}>~c{a;-D`*v!z>(Zvia({{pYnjtfJaZ(1G7^L39Q1@d$v|!;6p|IsH$GnI zve@DBV<5FjC93m;O1xX!Bq!LY*269_z|Pqq`wT-5=;GVj1z>#A2G06@7o1|Wa)_8e zkwfv$O5!gT+PvUoi-WpI)FRY_3Ci|?{fQ;D;gYbQjiei8E#ASm96LVfR)&ydN*>h$ zI}0hHDa^%|Qc6Q6wmYAIsNS^EUPVXxZPpM3c_K{wT=0C4lT~_Ka*!2ETBaGj6t4b? zD&osea@dMGmo`1aO+nsu6o(q2d-zMc(JW^_@x2gNF$qpRoFN6!9;X{AExT}VwvjA7 z!FbV5kbT3SI2nZxIQo?rdJM_DI=fqMDWE85F^xAFmBoRl*xfI$M1_a3Oc+%m&oVkb zotkNn^aZ-=N%t(wL|fxv-%c6^e+>B@V=H9~M$Gg|pR{Jn`Mcu2;$}QZMYqV{=$V)e zRuqD54Roq@@G!ta5E!6*6uVUba@!(5wLMo!e7VOI87MT3;w9?^E1 zmGX_S=qf8pdTs((o?(lQv{zWzIFE2vCVqtJ$`^!)j|3j-%w-+Ip!}BsV!@j;aE6n+ zrSyzSiji`d_(rf&ap-h6q?)^V2v}s4{34}QMF@3hmXb3?Wl7PvPbtET+{h&L6hG@m z>@9v>bI#6?*F|QW;UyM52zT;>7kZd%S#Tz38XvrK1iUrz&A=hc&A{(_|L=^aCU)X! zP^$y z--f)>nqdry(e71;+1(8@DxY;C?cGt643AVF`p1>Vreks2qqo`c9oEN>zvPM@e+XMx zGF4jypqck`;9Po1e}WSnBQwa9K(gNjm!b1`iJf~Of;uD;;0Jok!y=?9GK1Z?wj+s9 zxKQ3Y1<#uL?15B6se$)4{X#LmJ$N%liTRz3So46A<*s~CA&s0~a2sQMJD_CA?KsV& zxv&Qe9b0Am0CeU>|E-bmeTGX-zF@*vftTQ8@4^?xPxkD%@1K8{WaBqVPGCSl2XsI{ z2!E_U5^h%iFluXWyBx41288z+Uu1Nn9y-WEIE(CEm*<&I;#&P)Q;LmbV@sAmKe9ai zeAdB{B@7!rftt~~!ieovuTInG)BE7Q;a4EZRLNo-=&~rc&jmgX!esH^<;(ddH6-BU zp>*@UWVy5-QrfbM(=Q0tOm+OzLXt8}@!L!Hdaj`v384ue5)0N`RN}MhsVZ>qfT|=Q z_V6N=GPU%=yJx=N>AuJiHPltwUIS%b_NrL_VvG4VW2*6wQC0Xz;yDbKy3XvB6?+X( z3YCpz@c<>XP%XFG5IqxWv=XVEdF?0P8l9TokLJ=~!4%TSqiV%L+QXc>4DqwG8bh@7 zVUge4?dS9IaFrgLu4U8Ar|V|=LiGfmj1=49CKzU6^3zN zVtR=5=F?87s)d9RUTWYcq098S5O1JE z^(?$zH~XA#(wf({%A7kGE-j{yB1T3sFaNQU_Ub+heu^eo?g5JsV@s?zFeOuxcN~4~ zsSq!l`V$hT`qpvQ9FLUqex2c^)kKFY<+YF1rTkTYSK|!G1)ljnQk+%s$UebG0I-4? zM*7JfVZ_t6X}_LthxT}xHN9wC7B`Xhh^Zhrro=l+iHdMubRTW8A?Ll2nxO;==k7y_{_IVVhypKY^ z($Kf|{>jkS$@b%lv-ehC%TLgTDK|vGQWajOw{vn&MbafDo-#FVJ#eutX-96 z*{W%WwAbwuGIajs&zP9EtDN^#K<+}wo8)U6nAA9R*)9>kHAVJ8MD+$KY{4+Nm; zBuQMDDBKFp(egQ*_up@4C$s)HzdtJQSH_5qsH{-1+p0IquU-saJI}T14h5%{`ReU7 z(b-X%kDJWE6f6mwYwU>fYR%gE=k%J*uJ{<%8=$_t18_!9q|DEWWSkXV_UySbQ&IM_Nko0tLxvsnE2<9Gds8}{$WUv5~@ zzadQj7Yy_N1;g?;1{eet^#A)%%%27RXS4+Ub^H6yt0?nN^4~7s|HT0TwFFuH@%{e8 z^ZRe~-}cV`qSb$b`@hlum_7f^{@YdXU)B-jZ|r|O2LERNEffEj-NgGF`ybKx-|W9t z&;PQL1b<`yqk;aL{dZ0KFI)bn%KfXt{Tu#!{`_@p>3>E`kSOy%v+4hj{44YRXS4)) z{EKAzKS!(og);x2qr3k?Srlc!A^utv%%3ank93dn$0>pcB<^fxCL$zC_&>?_{{S(} B3F80& literal 0 HcmV?d00001 diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index b6aec7dcd..a0ef1cdd4 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -41,17 +41,20 @@ # include # include # include +# include +# include #endif #include #include +#include #include "FeaturePocket.h" using namespace PartDesign; -const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst",NULL}; +const char* Pocket::TypeEnums[]= {"Length","UpToLast","UpToFirst","ThroughAll","UpToFace",NULL}; PROPERTY_SOURCE(PartDesign::Pocket, PartDesign::SketchBased) @@ -60,13 +63,15 @@ Pocket::Pocket() ADD_PROPERTY(Type,((long)0)); Type.setEnums(TypeEnums); ADD_PROPERTY(Length,(100.0)); + ADD_PROPERTY(FaceName,("")); } short Pocket::mustExecute() const { if (Placement.isTouched() || Sketch.isTouched() || - Length.isTouched()) + Length.isTouched() || + FaceName.isTouched()) return 1; return 0; } @@ -114,13 +119,22 @@ App::DocumentObjectExecReturn *Pocket::execute(void) if (!SupportObject) return new App::DocumentObjectExecReturn("No support in Sketch!"); + const TopoDS_Shape& support = SupportObject->Shape.getValue(); + if (support.IsNull()) + return new App::DocumentObjectExecReturn("Support shape is invalid"); + TopExp_Explorer xp (support, TopAbs_SOLID); + if (!xp.More()) + return new App::DocumentObjectExecReturn("Support shape is not a solid"); + TopoDS_Shape aFace = makeFace(wires); if (aFace.IsNull()) return new App::DocumentObjectExecReturn("Creating a face from sketch failed"); // This is a trick to avoid problems with the cut operation. Sometimes a cut doesn't - // work as expected if faces or coincident. Thus, we move the face in normal direction + // work as expected if faces are coincident. Thus, we move the face in normal direction // but make it longer by one unit in the opposite direction. + // TODO: Isn't one unit (one millimeter) a lot, assuming someone models a really tiny solid? + // What about using 2 * Precision::Confusion() ? gp_Trsf mov; mov.SetTranslation(gp_Vec(SketchVector.x,SketchVector.y,SketchVector.z)); TopLoc_Location loc(mov); @@ -135,39 +149,133 @@ App::DocumentObjectExecReturn *Pocket::execute(void) this->positionBySketch(); TopLoc_Location invObjLoc = this->getLocation().Inverted(); - // extrude the face to a solid - gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); - vec.Transform(invObjLoc.Transformation()); - BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); - if (PrismMaker.IsDone()) { - // if the sketch has a support fuse them to get one result object (PAD!) - if (SupportObject) { - const TopoDS_Shape& support = SupportObject->Shape.getValue(); - if (support.IsNull()) - return new App::DocumentObjectExecReturn("Support shape is invalid"); - TopExp_Explorer xp (support, TopAbs_SOLID); - if (!xp.More()) - return new App::DocumentObjectExecReturn("Support shape is not a solid"); - // Let's call algorithm computing a fuse operation: - BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), PrismMaker.Shape()); - // Let's check if the fusion has been successful - if (!mkCut.IsDone()) - return new App::DocumentObjectExecReturn("Cut with support failed"); + try { + // extrude the face to a solid + TopoDS_Shape prism; - // we have to get the solids (fuse create seldomly compounds) - TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); - if (solRes.IsNull()) - return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst") || + (std::string(Type.getValueAsString()) == "UpToFace")) + { + TopoDS_Face upToFace; + gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); - this->Shape.setValue(solRes); - } - else { - return new App::DocumentObjectExecReturn("Cannot create a tool out of sketch with no support"); + if ((std::string(Type.getValueAsString()) == "UpToLast") || + (std::string(Type.getValueAsString()) == "UpToFirst")) + { + TopoDS_Shape origFace = makeFace(wires); // original sketch face before moving one unit + std::vector cfaces = Part::findAllFacesCutBy(support, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction"); + + // Find nearest/furthest face + std::vector::const_iterator it, it_near, it_far; + it_near = it_far = cfaces.begin(); + for (it = cfaces.begin(); it != cfaces.end(); it++) + if (it->distsq > it_far->distsq) + it_far = it; + else if (it->distsq < it_near->distsq) + it_near = it; + upToFace = (std::string(Type.getValueAsString()) == "UpToLast" ? it_far->face : it_near->face); + } else { + if (FaceName.getValue() == "") + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No face selected"); + + // Get active object, this is the object that the user referenced when he clicked on the face! + App::DocumentObject* baseLink = this->getDocument()->getActiveObject(); + + if (!baseLink) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: No object linked"); + if (!baseLink->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Linked object is not a Part object"); + Part::Feature *base = static_cast(baseLink); + const Part::TopoShape& baseShape = base->Shape.getShape(); + if (baseShape._Shape.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Cannot work on invalid shape"); + + TopoDS_Shape sub = baseShape.getSubShape(FaceName.getValue()); + if (!sub.IsNull() && sub.ShapeType() == TopAbs_FACE) + upToFace = TopoDS::Face(sub); + else + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Selection is not a face"); + + // Find the origin of this face (i.e. a vertex or a edge in a sketch) + TopoDS_Shape origin = base->findOriginOf(sub); + + // Validate face + // TODO: This would also exclude faces that are valid but not cut by the line + // So for now we trust to the intelligence of the user when picking the face + /*std::vector cfaces = findAllFacesCutBy(upToFace, origFace, dir); + if (cfaces.empty()) + return new App::DocumentObjectExecReturn("No faces found in this direction");*/ + } + + // Create semi-infinite prism from sketch in direction dir + dir.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),dir,0,0,1); + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Could not extrude the sketch!"); + + // Cut off the prism at the face we found + // Grab any point from the sketch + TopExp_Explorer exp; + exp.Init(aFace, TopAbs_VERTEX); + if (!exp.More()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Sketch without points?"); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(exp.Current())); + + // Create a halfspace from the face, extending in direction of sketch plane + BRepPrimAPI_MakeHalfSpace mkHalfSpace(upToFace, aPnt); + if (!mkHalfSpace.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: HalfSpace creation failed"); + + // Find common material between halfspace and prism + BRepAlgoAPI_Common mkCommon(PrismMaker.Shape(), mkHalfSpace.Solid().Moved(invObjLoc)); + if (!mkCommon.IsDone()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Common creation failed"); + + prism = this->getSolid(mkCommon.Shape()); + if (prism.IsNull()) + return new App::DocumentObjectExecReturn("Cannot extrude up to face: Resulting shape is not a solid"); + } else if (std::string(Type.getValueAsString()) == "ThroughAll") { + gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); + dir.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),dir,1,0,1); // infinite prism (in both directions!) + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } else if (std::string(Type.getValueAsString()) == "Length") { + gp_Vec vec(SketchVector.x,SketchVector.y,SketchVector.z); + vec.Transform(invObjLoc.Transformation()); + BRepPrimAPI_MakePrism PrismMaker(aFace.Moved(invObjLoc),vec,0,1); // finite prism + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } else { + return new App::DocumentObjectExecReturn("Internal error: Unknown type for Pocket feature"); } + + // TODO: Set the subtractive shape property for later usage in e.g. pattern + //this->SubShape.setValue(prism); // This crashes with "Illegal storage access". Why? + + // Cut out the pocket + BRepAlgoAPI_Cut mkCut(support.Moved(invObjLoc), prism); + + // Let's check if the fusion has been successful + if (!mkCut.IsDone()) + return new App::DocumentObjectExecReturn("Cut with support failed"); + + // we have to get the solids (fuse sometimes creates compounds) + TopoDS_Shape solRes = this->getSolid(mkCut.Shape()); + if (solRes.IsNull()) + return new App::DocumentObjectExecReturn("Resulting shape is not a solid"); + + this->Shape.setValue(solRes); + + return App::DocumentObject::StdReturn; + } catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); } - else - return new App::DocumentObjectExecReturn("Could not extrude the sketch!"); - - return App::DocumentObject::StdReturn; } diff --git a/src/Mod/PartDesign/App/FeaturePocket.h b/src/Mod/PartDesign/App/FeaturePocket.h index 7a7d57962..b9b47aa72 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.h +++ b/src/Mod/PartDesign/App/FeaturePocket.h @@ -39,6 +39,7 @@ public: App::PropertyEnumeration Type; App::PropertyLength Length; + App::PropertyString FaceName; /** @name methods override feature */ //@{ diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index 30618f621..2122bafd1 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -58,16 +58,39 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge connect(ui->doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onLengthChanged(double))); + connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), + this, SLOT(onModeChanged(int))); + connect(ui->lineFaceName, SIGNAL(textEdited(QString)), + this, SLOT(onFaceName(QString))); this->groupLayout()->addWidget(proxy); PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); double l = pcPocket->Length.getValue(); + int index = pcPocket->Type.getValue(); // must extract value here, clear() kills it! + const char* upToFace = pcPocket->FaceName.getValue(); - ui->doubleSpinBox->setMaximum(INT_MAX); - ui->doubleSpinBox->setValue(l); - ui->doubleSpinBox->selectAll(); - QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->changeMode->clear(); + ui->changeMode->insertItem(0, tr("Dimension")); + ui->changeMode->insertItem(1, tr("To last")); + ui->changeMode->insertItem(2, tr("To first")); + ui->changeMode->insertItem(3, tr("Through all")); + ui->changeMode->insertItem(4, tr("Up to face")); + ui->changeMode->setCurrentIndex(index); + + if (index == 0) { // Only this option requires a numeric value + ui->doubleSpinBox->setMaximum(INT_MAX); + ui->doubleSpinBox->setValue(l); + ui->doubleSpinBox->selectAll(); + QMetaObject::invokeMethod(ui->doubleSpinBox, "setFocus", Qt::QueuedConnection); + ui->lineFaceName->setEnabled(false); + } else if (index == 4) { // Only this option requires to select a face + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setText(upToFace == "" ? tr("No face selected") : tr(upToFace)); + } else { // Neither value nor face required + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } //// check if the sketch has support //Sketcher::SketchObject *pcSketch; @@ -81,6 +104,25 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge //} } +void TaskPocketParameters::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + if (pcPocket->Type.getValue() != 4) // ignore user selections if mode is not upToFace + return; + + if (!msg.pSubName || msg.pSubName[0] == '\0') + return; + std::string element(msg.pSubName); + if (element.substr(0,4) != "Face") + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + pcPocket->FaceName.setValue(element); + pcPocket->getDocument()->recomputeFeature(pcPocket); + ui->lineFaceName->setText(tr(element.c_str())); + } +} + void TaskPocketParameters::onLengthChanged(double len) { PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); @@ -88,11 +130,59 @@ void TaskPocketParameters::onLengthChanged(double len) pcPocket->getDocument()->recomputeFeature(pcPocket); } +void TaskPocketParameters::onModeChanged(int index) +{ + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + + switch (index) { + case 0: pcPocket->Type.setValue("Length"); break; + case 1: pcPocket->Type.setValue("UpToLast"); break; + case 2: pcPocket->Type.setValue("UpToFirst"); break; + case 3: pcPocket->Type.setValue("ThroughAll"); break; + case 4: pcPocket->Type.setValue("UpToFace"); break; + default: pcPocket->Type.setValue("Length"); + } + + if (index == 0) { + ui->doubleSpinBox->setEnabled(true); + ui->lineFaceName->setEnabled(false); + ui->doubleSpinBox->setValue(pcPocket->Length.getValue()); + } else if (index == 4) { + ui->lineFaceName->setEnabled(true); + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setText(tr(pcPocket->FaceName.getValue())); + } else { + ui->doubleSpinBox->setEnabled(false); + ui->lineFaceName->setEnabled(false); + } + + pcPocket->getDocument()->recomputeFeature(pcPocket); +} + +void TaskPocketParameters::onFaceName(const QString& text) +{ + if (text.left(4) != tr("Face")) + return; + + PartDesign::Pocket* pcPocket = static_cast(PocketView->getObject()); + pcPocket->FaceName.setValue(text.toUtf8()); + pcPocket->getDocument()->recomputeFeature(pcPocket); +} + double TaskPocketParameters::getLength(void) const { return ui->doubleSpinBox->value(); } +int TaskPocketParameters::getMode(void) const +{ + return ui->changeMode->currentIndex(); +} + +const QString TaskPocketParameters::getFaceName(void) const +{ + return ui->lineFaceName->text(); +} TaskPocketParameters::~TaskPocketParameters() { @@ -145,6 +235,8 @@ bool TaskDlgPocketParameters::accept() //Gui::Command::openCommand("Pocket changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Length = %f",name.c_str(),parameter->getLength()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Type = %u",name.c_str(),parameter->getMode()); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.FaceName = \"%s\"",name.c_str(),parameter->getFaceName().toAscii().data()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::commitCommand(); @@ -163,7 +255,7 @@ bool TaskDlgPocketParameters::reject() pcSupport = pcSketch->Support.getValue(); } - // role back the done things + // roll back the done things Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.h b/src/Mod/PartDesign/Gui/TaskPocketParameters.h index 077a9ef0c..bbb6bbb3f 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.h @@ -44,7 +44,7 @@ namespace PartDesignGui { -class TaskPocketParameters : public Gui::TaskView::TaskBox +class TaskPocketParameters : public Gui::TaskView::TaskBox, public Gui::SelectionObserver { Q_OBJECT @@ -53,14 +53,19 @@ public: ~TaskPocketParameters(); double getLength(void) const; + int getMode(void) const; + const QString getFaceName(void) const; private Q_SLOTS: void onLengthChanged(double); + void onModeChanged(int); + void onFaceName(const QString& text); protected: void changeEvent(QEvent *e); private: + void onSelectionChanged(const Gui::SelectionChanges& msg); private: QWidget* proxy; diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui index 34c8979a1..4f313be76 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui @@ -6,49 +6,97 @@ 0 0 - 137 - 68 + 241 + 134 + + + 0 + 0 + + + + + 233 + 134 + + Form - - - - - + + + + 10 + 10 + 211 + 34 + + + + + + + Type + + + + + + - Type: + Dimension - - - - - - - Dimension - - - - - - - - - - - - Length - - - - - - - - - + + + + + + + + + 10 + 90 + 211 + 34 + + + + + + + Face + + + + + + + + + + + + 10 + 50 + 211 + 34 + + + + + + + Length + + + + + + + +